]> git.ipfire.org Git - thirdparty/qemu.git/blame - target/sparc/translate.c
tcg/loongarch64: Set vector registers call clobbered
[thirdparty/qemu.git] / target / sparc / translate.c
CommitLineData
7a3f1944
FB
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
3475187d 5 Copyright (C) 2003-2005 Fabrice Bellard
7a3f1944
FB
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
5650b549 10 version 2.1 of the License, or (at your option) any later version.
7a3f1944
FB
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
8167ee88 18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
7a3f1944
FB
19 */
20
db5ebe5f 21#include "qemu/osdep.h"
7a3f1944
FB
22
23#include "cpu.h"
76cad711 24#include "disas/disas.h"
2ef6175a 25#include "exec/helper-proto.h"
63c91552 26#include "exec/exec-all.h"
dcb32f1d 27#include "tcg/tcg-op.h"
fafba1bb 28#include "tcg/tcg-op-gvec.h"
2ef6175a 29#include "exec/helper-gen.h"
c5e6ccdf 30#include "exec/translator.h"
508127e2 31#include "exec/log.h"
0cc1f4bf 32#include "asi.h"
a7e30d84 33
d53106c9
RH
34#define HELPER_H "helper.h"
35#include "exec/helper-info.c.inc"
36#undef HELPER_H
a7e30d84 37
668bb9b7
RH
38#ifdef TARGET_SPARC64
39# define gen_helper_rdpsr(D, E) qemu_build_not_reached()
86b82fe0 40# define gen_helper_rett(E) qemu_build_not_reached()
0faef01b 41# define gen_helper_power_down(E) qemu_build_not_reached()
25524734 42# define gen_helper_wrpsr(E, S) qemu_build_not_reached()
668bb9b7 43#else
0faef01b 44# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
8f75b8a4 45# define gen_helper_done(E) qemu_build_not_reached()
c6d83e4f 46# define gen_helper_fabsd(D, S) qemu_build_not_reached()
e8325dc0 47# define gen_helper_flushw(E) qemu_build_not_reached()
c6d83e4f 48# define gen_helper_fnegd(D, S) qemu_build_not_reached()
af25071c 49# define gen_helper_rdccr(D, E) qemu_build_not_reached()
5d617bfb 50# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
25524734 51# define gen_helper_restored(E) qemu_build_not_reached()
8f75b8a4 52# define gen_helper_retry(E) qemu_build_not_reached()
25524734 53# define gen_helper_saved(E) qemu_build_not_reached()
0faef01b 54# define gen_helper_set_softint(E, S) qemu_build_not_reached()
af25071c 55# define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
9422278e 56# define gen_helper_tick_set_count(P, S) qemu_build_not_reached()
bb97f2f5 57# define gen_helper_tick_set_limit(P, S) qemu_build_not_reached()
0faef01b 58# define gen_helper_wrccr(E, S) qemu_build_not_reached()
9422278e
RH
59# define gen_helper_wrcwp(E, S) qemu_build_not_reached()
60# define gen_helper_wrgl(E, S) qemu_build_not_reached()
0faef01b 61# define gen_helper_write_softint(E, S) qemu_build_not_reached()
9422278e
RH
62# define gen_helper_wrpil(E, S) qemu_build_not_reached()
63# define gen_helper_wrpstate(E, S) qemu_build_not_reached()
f4e18df5 64# define gen_helper_fabsq ({ qemu_build_not_reached(); NULL; })
e2fa6bd1
RH
65# define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; })
66# define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; })
67# define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; })
68# define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; })
69# define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; })
70# define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; })
71# define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; })
72# define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; })
8aa418b3 73# define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; })
e06c9f83
RH
74# define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; })
75# define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; })
76# define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; })
77# define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; })
78# define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; })
79# define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; })
80# define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; })
81# define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; })
f4e18df5 82# define gen_helper_fnegq ({ qemu_build_not_reached(); NULL; })
e06c9f83 83# define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; })
1617586f 84# define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; })
199d43ef 85# define gen_helper_fstox ({ qemu_build_not_reached(); NULL; })
8aa418b3 86# define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; })
7b8e3e1a 87# define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; })
f4e18df5 88# define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; })
afb04344 89# define gen_helper_pdist ({ qemu_build_not_reached(); NULL; })
da681406
RH
90# define FSR_LDXFSR_MASK 0
91# define FSR_LDXFSR_OLDMASK 0
668bb9b7 92# define MAXTL_MASK 0
af25071c
RH
93#endif
94
633c4283
RH
95/* Dynamic PC, must exit to main loop. */
96#define DYNAMIC_PC 1
97/* Dynamic PC, one of two values according to jump_pc[T2]. */
98#define JUMP_PC 2
99/* Dynamic PC, may lookup next TB. */
100#define DYNAMIC_PC_LOOKUP 3
72cbca10 101
46bb0137
MCA
102#define DISAS_EXIT DISAS_TARGET_0
103
1a2fb1c0 104/* global register indexes */
1bcea73e 105static TCGv_ptr cpu_regwptr;
d2dc4069
RH
106static TCGv cpu_fsr, cpu_pc, cpu_npc;
107static TCGv cpu_regs[32];
255e1fcb 108static TCGv cpu_y;
255e1fcb 109static TCGv cpu_tbr;
5793f2a4 110static TCGv cpu_cond;
2a1905c7
RH
111static TCGv cpu_cc_N;
112static TCGv cpu_cc_V;
113static TCGv cpu_icc_Z;
114static TCGv cpu_icc_C;
dc99a3f2 115#ifdef TARGET_SPARC64
2a1905c7
RH
116static TCGv cpu_xcc_Z;
117static TCGv cpu_xcc_C;
118static TCGv_i32 cpu_fprs;
a7812ae4 119static TCGv cpu_gsr;
255e1fcb 120#else
af25071c
RH
121# define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; })
122# define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; })
dc99a3f2 123#endif
2a1905c7
RH
124
125#ifdef TARGET_SPARC64
126#define cpu_cc_Z cpu_xcc_Z
127#define cpu_cc_C cpu_xcc_C
128#else
129#define cpu_cc_Z cpu_icc_Z
130#define cpu_cc_C cpu_icc_C
131#define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
132#define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
133#endif
134
714547bb 135/* Floating point registers */
30038fd8 136static TCGv_i64 cpu_fpr[TARGET_DPREGS];
1a2fb1c0 137
af25071c
RH
138#define env_field_offsetof(X) offsetof(CPUSPARCState, X)
139#ifdef TARGET_SPARC64
cd6269f7 140# define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
af25071c
RH
141# define env64_field_offsetof(X) env_field_offsetof(X)
142#else
cd6269f7 143# define env32_field_offsetof(X) env_field_offsetof(X)
af25071c
RH
144# define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
145#endif
146
533f042f
RH
147typedef struct DisasCompare {
148 TCGCond cond;
149 TCGv c1;
150 int c2;
151} DisasCompare;
152
186e7890
RH
153typedef struct DisasDelayException {
154 struct DisasDelayException *next;
155 TCGLabel *lab;
156 TCGv_i32 excp;
157 /* Saved state at parent insn. */
158 target_ulong pc;
159 target_ulong npc;
160} DisasDelayException;
161
7a3f1944 162typedef struct DisasContext {
af00be49 163 DisasContextBase base;
0f8a249a
BS
164 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
165 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
533f042f
RH
166
167 /* Used when JUMP_PC value is used. */
168 DisasCompare jump;
169 target_ulong jump_pc[2];
170
e8af50a3 171 int mem_idx;
89527e3a 172 bool cpu_cond_live;
c9b459aa
AT
173 bool fpu_enabled;
174 bool address_mask_32bit;
c9b459aa
AT
175#ifndef CONFIG_USER_ONLY
176 bool supervisor;
177#ifdef TARGET_SPARC64
178 bool hypervisor;
179#endif
180#endif
181
5578ceab 182 sparc_def_t *def;
a6d567e5 183#ifdef TARGET_SPARC64
f9c816c0 184 int fprs_dirty;
a6d567e5
RH
185 int asi;
186#endif
186e7890 187 DisasDelayException *delay_excp_list;
7a3f1944
FB
188} DisasContext;
189
3475187d 190// This function uses non-native bit order
dc1a6971
BS
191#define GET_FIELD(X, FROM, TO) \
192 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
7a3f1944 193
3475187d 194// This function uses the order in the manuals, i.e. bit 0 is 2^0
dc1a6971 195#define GET_FIELD_SP(X, FROM, TO) \
3475187d
FB
196 GET_FIELD(X, 31 - (TO), 31 - (FROM))
197
198#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
46d38ba8 199#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
3475187d
FB
200
201#ifdef TARGET_SPARC64
0387d928 202#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
1f587329 203#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
3475187d 204#else
c185970a 205#define DFPREG(r) (r & 0x1e)
1f587329 206#define QFPREG(r) (r & 0x1c)
3475187d
FB
207#endif
208
b158a785
BS
209#define UA2005_HTRAP_MASK 0xff
210#define V8_TRAP_MASK 0x7f
211
7a3f1944
FB
212#define IS_IMM (insn & (1<<13))
213
0c2e96c1 214static void gen_update_fprs_dirty(DisasContext *dc, int rd)
141ae5c1
RH
215{
216#if defined(TARGET_SPARC64)
f9c816c0
RH
217 int bit = (rd < 32) ? 1 : 2;
218 /* If we know we've already set this bit within the TB,
219 we can avoid setting it again. */
220 if (!(dc->fprs_dirty & bit)) {
221 dc->fprs_dirty |= bit;
222 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
223 }
141ae5c1
RH
224#endif
225}
226
ff07ec83 227/* floating point registers moves */
208ae657
RH
228static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
229{
36ab4623 230 TCGv_i32 ret = tcg_temp_new_i32();
30038fd8 231 if (src & 1) {
dc41aa7d 232 tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]);
30038fd8 233 } else {
dc41aa7d 234 tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]);
30038fd8 235 }
dc41aa7d 236 return ret;
208ae657
RH
237}
238
239static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
240{
8e7bbc75
RH
241 TCGv_i64 t = tcg_temp_new_i64();
242
243 tcg_gen_extu_i32_i64(t, v);
30038fd8
RH
244 tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
245 (dst & 1 ? 0 : 32), 32);
f9c816c0 246 gen_update_fprs_dirty(dc, dst);
208ae657
RH
247}
248
ba5f5179 249static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
208ae657 250{
36ab4623 251 return tcg_temp_new_i32();
208ae657
RH
252}
253
96eda024
RH
254static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
255{
96eda024 256 src = DFPREG(src);
30038fd8 257 return cpu_fpr[src / 2];
96eda024
RH
258}
259
260static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
261{
262 dst = DFPREG(dst);
30038fd8 263 tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
f9c816c0 264 gen_update_fprs_dirty(dc, dst);
96eda024
RH
265}
266
3886b8a3 267static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
96eda024 268{
3886b8a3 269 return cpu_fpr[DFPREG(dst) / 2];
96eda024
RH
270}
271
ff07ec83
BS
272static void gen_op_load_fpr_QT0(unsigned int src)
273{
ad75a51e 274 tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
30038fd8 275 offsetof(CPU_QuadU, ll.upper));
ad75a51e 276 tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) +
30038fd8 277 offsetof(CPU_QuadU, ll.lower));
ff07ec83
BS
278}
279
280static void gen_op_load_fpr_QT1(unsigned int src)
281{
ad75a51e 282 tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt1) +
30038fd8 283 offsetof(CPU_QuadU, ll.upper));
ad75a51e 284 tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt1) +
30038fd8 285 offsetof(CPU_QuadU, ll.lower));
ff07ec83
BS
286}
287
288static void gen_op_store_QT0_fpr(unsigned int dst)
289{
ad75a51e 290 tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) +
30038fd8 291 offsetof(CPU_QuadU, ll.upper));
ad75a51e 292 tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) +
30038fd8 293 offsetof(CPU_QuadU, ll.lower));
ff07ec83 294}
1f587329 295
81ad8ba2
BS
296/* moves */
297#ifdef CONFIG_USER_ONLY
3475187d 298#define supervisor(dc) 0
e9ebed4d 299#define hypervisor(dc) 0
3475187d 300#else
81ad8ba2 301#ifdef TARGET_SPARC64
c9b459aa
AT
302#define hypervisor(dc) (dc->hypervisor)
303#define supervisor(dc) (dc->supervisor | dc->hypervisor)
6f27aba6 304#else
c9b459aa 305#define supervisor(dc) (dc->supervisor)
668bb9b7 306#define hypervisor(dc) 0
3475187d 307#endif
81ad8ba2
BS
308#endif
309
b1bc09ea
RH
310#if !defined(TARGET_SPARC64)
311# define AM_CHECK(dc) false
312#elif defined(TARGET_ABI32)
313# define AM_CHECK(dc) true
314#elif defined(CONFIG_USER_ONLY)
315# define AM_CHECK(dc) false
1a2fb1c0 316#else
b1bc09ea 317# define AM_CHECK(dc) ((dc)->address_mask_32bit)
1a2fb1c0 318#endif
3391c818 319
0c2e96c1 320static void gen_address_mask(DisasContext *dc, TCGv addr)
2cade6a3 321{
b1bc09ea 322 if (AM_CHECK(dc)) {
2cade6a3 323 tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
b1bc09ea 324 }
2cade6a3
BS
325}
326
23ada1b1
RH
327static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
328{
329 return AM_CHECK(dc) ? (uint32_t)addr : addr;
330}
331
0c2e96c1 332static TCGv gen_load_gpr(DisasContext *dc, int reg)
88023616 333{
d2dc4069
RH
334 if (reg > 0) {
335 assert(reg < 32);
336 return cpu_regs[reg];
337 } else {
52123f14 338 TCGv t = tcg_temp_new();
d2dc4069 339 tcg_gen_movi_tl(t, 0);
88023616 340 return t;
88023616
RH
341 }
342}
343
0c2e96c1 344static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
88023616
RH
345{
346 if (reg > 0) {
d2dc4069
RH
347 assert(reg < 32);
348 tcg_gen_mov_tl(cpu_regs[reg], v);
88023616
RH
349 }
350}
351
0c2e96c1 352static TCGv gen_dest_gpr(DisasContext *dc, int reg)
88023616 353{
d2dc4069
RH
354 if (reg > 0) {
355 assert(reg < 32);
356 return cpu_regs[reg];
88023616 357 } else {
52123f14 358 return tcg_temp_new();
88023616
RH
359 }
360}
361
5645aa2e 362static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
90aa39a1 363{
5645aa2e
RH
364 return translator_use_goto_tb(&s->base, pc) &&
365 translator_use_goto_tb(&s->base, npc);
90aa39a1
SF
366}
367
5645aa2e
RH
368static void gen_goto_tb(DisasContext *s, int tb_num,
369 target_ulong pc, target_ulong npc)
6e256c93 370{
90aa39a1 371 if (use_goto_tb(s, pc, npc)) {
6e256c93 372 /* jump to same page: we can use a direct jump */
57fec1fe 373 tcg_gen_goto_tb(tb_num);
2f5680ee
BS
374 tcg_gen_movi_tl(cpu_pc, pc);
375 tcg_gen_movi_tl(cpu_npc, npc);
07ea28b4 376 tcg_gen_exit_tb(s->base.tb, tb_num);
6e256c93 377 } else {
f67ccb2f 378 /* jump to another page: we can use an indirect jump */
2f5680ee
BS
379 tcg_gen_movi_tl(cpu_pc, pc);
380 tcg_gen_movi_tl(cpu_npc, npc);
f67ccb2f 381 tcg_gen_lookup_and_goto_ptr();
6e256c93
FB
382 }
383}
384
b989ce73 385static TCGv gen_carry32(void)
dc99a3f2 386{
b989ce73
RH
387 if (TARGET_LONG_BITS == 64) {
388 TCGv t = tcg_temp_new();
389 tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
390 return t;
391 }
392 return cpu_icc_C;
41d72852
BS
393}
394
b989ce73 395static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
dc99a3f2 396{
b989ce73 397 TCGv z = tcg_constant_tl(0);
70c48285 398
b989ce73
RH
399 if (cin) {
400 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
401 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
402 } else {
403 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
404 }
405 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
406 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
407 tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
408 if (TARGET_LONG_BITS == 64) {
409 /*
410 * Carry-in to bit 32 is result ^ src1 ^ src2.
411 * We already have the src xor term in Z, from computation of V.
412 */
413 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
414 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
415 }
416 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
417 tcg_gen_mov_tl(dst, cpu_cc_N);
418}
70c48285 419
b989ce73
RH
420static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
421{
422 gen_op_addcc_int(dst, src1, src2, NULL);
423}
70c48285 424
b989ce73
RH
425static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
426{
427 TCGv t = tcg_temp_new();
428
429 /* Save the tag bits around modification of dst. */
430 tcg_gen_or_tl(t, src1, src2);
431
432 gen_op_addcc(dst, src1, src2);
433
434 /* Incorprate tag bits into icc.V */
435 tcg_gen_andi_tl(t, t, 3);
436 tcg_gen_neg_tl(t, t);
437 tcg_gen_ext32u_tl(t, t);
438 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
439}
440
441static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
442{
443 tcg_gen_add_tl(dst, src1, src2);
444 tcg_gen_add_tl(dst, dst, gen_carry32());
445}
446
447static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
448{
449 gen_op_addcc_int(dst, src1, src2, gen_carry32());
41d72852
BS
450}
451
f828df74 452static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
41d72852 453{
f828df74 454 TCGv z = tcg_constant_tl(0);
70c48285 455
f828df74
RH
456 if (cin) {
457 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
458 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
459 } else {
460 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
70c48285 461 }
f828df74
RH
462 tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
463 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
464 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
465 tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
466#ifdef TARGET_SPARC64
467 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
468 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
469#endif
470 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
471 tcg_gen_mov_tl(dst, cpu_cc_N);
dc99a3f2
BS
472}
473
f828df74 474static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
dfebb950 475{
f828df74 476 gen_op_subcc_int(dst, src1, src2, NULL);
dfebb950
RH
477}
478
f828df74 479static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
dfebb950 480{
f828df74 481 TCGv t = tcg_temp_new();
dfebb950 482
f828df74
RH
483 /* Save the tag bits around modification of dst. */
484 tcg_gen_or_tl(t, src1, src2);
dfebb950 485
f828df74 486 gen_op_subcc(dst, src1, src2);
dfebb950 487
f828df74
RH
488 /* Incorprate tag bits into icc.V */
489 tcg_gen_andi_tl(t, t, 3);
490 tcg_gen_neg_tl(t, t);
491 tcg_gen_ext32u_tl(t, t);
492 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
dfebb950
RH
493}
494
f828df74 495static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
dfebb950 496{
f828df74
RH
497 tcg_gen_sub_tl(dst, src1, src2);
498 tcg_gen_sub_tl(dst, dst, gen_carry32());
dfebb950
RH
499}
500
f828df74 501static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
dfebb950 502{
f828df74 503 gen_op_subcc_int(dst, src1, src2, gen_carry32());
dfebb950
RH
504}
505
0c2e96c1 506static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
d9bdab86 507{
b989ce73
RH
508 TCGv zero = tcg_constant_tl(0);
509 TCGv t_src1 = tcg_temp_new();
510 TCGv t_src2 = tcg_temp_new();
511 TCGv t0 = tcg_temp_new();
d9bdab86 512
b989ce73
RH
513 tcg_gen_ext32u_tl(t_src1, src1);
514 tcg_gen_ext32u_tl(t_src2, src2);
d9bdab86 515
b989ce73
RH
516 /*
517 * if (!(env->y & 1))
518 * src2 = 0;
519 */
520 tcg_gen_andi_tl(t0, cpu_y, 0x1);
521 tcg_gen_movcond_tl(TCG_COND_EQ, t_src2, t0, zero, zero, t_src2);
d9bdab86 522
b989ce73
RH
523 /*
524 * b2 = src1 & 1;
525 * y = (b2 << 31) | (y >> 1);
526 */
0b1183e3 527 tcg_gen_extract_tl(t0, cpu_y, 1, 31);
b989ce73 528 tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
d9bdab86
BS
529
530 // b1 = N ^ V;
2a1905c7 531 tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
d9bdab86 532
b989ce73
RH
533 /*
534 * src1 = (b1 << 31) | (src1 >> 1)
535 */
2a1905c7 536 tcg_gen_andi_tl(t0, t0, 1u << 31);
b989ce73
RH
537 tcg_gen_shri_tl(t_src1, t_src1, 1);
538 tcg_gen_or_tl(t_src1, t_src1, t0);
d9bdab86 539
b989ce73 540 gen_op_addcc(dst, t_src1, t_src2);
d9bdab86
BS
541}
542
0c2e96c1 543static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
8879d139 544{
528692a8 545#if TARGET_LONG_BITS == 32
fb170183 546 if (sign_ext) {
528692a8 547 tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
fb170183 548 } else {
528692a8 549 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
fb170183 550 }
528692a8
RH
551#else
552 TCGv t0 = tcg_temp_new_i64();
553 TCGv t1 = tcg_temp_new_i64();
fb170183 554
528692a8
RH
555 if (sign_ext) {
556 tcg_gen_ext32s_i64(t0, src1);
557 tcg_gen_ext32s_i64(t1, src2);
558 } else {
559 tcg_gen_ext32u_i64(t0, src1);
560 tcg_gen_ext32u_i64(t1, src2);
561 }
fb170183 562
528692a8 563 tcg_gen_mul_i64(dst, t0, t1);
528692a8
RH
564 tcg_gen_shri_i64(cpu_y, dst, 32);
565#endif
8879d139
BS
566}
567
0c2e96c1 568static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
8879d139 569{
fb170183
IK
570 /* zero-extend truncated operands before multiplication */
571 gen_op_multiply(dst, src1, src2, 0);
572}
8879d139 573
0c2e96c1 574static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
fb170183
IK
575{
576 /* sign-extend truncated operands before multiplication */
577 gen_op_multiply(dst, src1, src2, 1);
8879d139
BS
578}
579
c2636853
RH
580static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
581{
13260103 582#ifdef TARGET_SPARC64
c2636853 583 gen_helper_sdiv(dst, tcg_env, src1, src2);
13260103
RH
584 tcg_gen_ext32s_tl(dst, dst);
585#else
586 TCGv_i64 t64 = tcg_temp_new_i64();
587 gen_helper_sdiv(t64, tcg_env, src1, src2);
588 tcg_gen_trunc_i64_tl(dst, t64);
589#endif
c2636853
RH
590}
591
592static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
593{
13260103
RH
594 TCGv_i64 t64;
595
596#ifdef TARGET_SPARC64
597 t64 = cpu_cc_V;
598#else
599 t64 = tcg_temp_new_i64();
600#endif
601
602 gen_helper_udiv(t64, tcg_env, src1, src2);
603
604#ifdef TARGET_SPARC64
605 tcg_gen_ext32u_tl(cpu_cc_N, t64);
606 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
607 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
608 tcg_gen_movi_tl(cpu_icc_C, 0);
609#else
610 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
611#endif
612 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
613 tcg_gen_movi_tl(cpu_cc_C, 0);
614 tcg_gen_mov_tl(dst, cpu_cc_N);
c2636853
RH
615}
616
617static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
618{
13260103
RH
619 TCGv_i64 t64;
620
621#ifdef TARGET_SPARC64
622 t64 = cpu_cc_V;
623#else
624 t64 = tcg_temp_new_i64();
625#endif
626
627 gen_helper_sdiv(t64, tcg_env, src1, src2);
628
629#ifdef TARGET_SPARC64
630 tcg_gen_ext32s_tl(cpu_cc_N, t64);
631 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
632 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
633 tcg_gen_movi_tl(cpu_icc_C, 0);
634#else
635 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
636#endif
637 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
638 tcg_gen_movi_tl(cpu_cc_C, 0);
639 tcg_gen_mov_tl(dst, cpu_cc_N);
c2636853
RH
640}
641
a9aba13d
RH
642static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
643{
644 gen_helper_taddcctv(dst, tcg_env, src1, src2);
645}
646
647static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
648{
649 gen_helper_tsubcctv(dst, tcg_env, src1, src2);
650}
651
9c6ec5bc
RH
652static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
653{
654 tcg_gen_ctpop_tl(dst, src2);
655}
656
45bfed3b
RH
657#ifndef TARGET_SPARC64
658static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
659{
660 g_assert_not_reached();
661}
662#endif
663
664static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
665{
666 gen_helper_array8(dst, src1, src2);
667 tcg_gen_shli_tl(dst, dst, 1);
668}
669
670static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
671{
672 gen_helper_array8(dst, src1, src2);
673 tcg_gen_shli_tl(dst, dst, 2);
674}
675
2f722641
RH
676static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
677{
678#ifdef TARGET_SPARC64
679 gen_helper_fpack16(dst, cpu_gsr, src);
680#else
681 g_assert_not_reached();
682#endif
683}
684
685static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
686{
687#ifdef TARGET_SPARC64
688 gen_helper_fpackfix(dst, cpu_gsr, src);
689#else
690 g_assert_not_reached();
691#endif
692}
693
4b6edc0a
RH
694static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
695{
696#ifdef TARGET_SPARC64
697 gen_helper_fpack32(dst, cpu_gsr, src1, src2);
698#else
699 g_assert_not_reached();
700#endif
701}
702
703static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
704{
705#ifdef TARGET_SPARC64
706 TCGv t1, t2, shift;
707
708 t1 = tcg_temp_new();
709 t2 = tcg_temp_new();
710 shift = tcg_temp_new();
711
712 tcg_gen_andi_tl(shift, cpu_gsr, 7);
713 tcg_gen_shli_tl(shift, shift, 3);
714 tcg_gen_shl_tl(t1, s1, shift);
715
716 /*
717 * A shift of 64 does not produce 0 in TCG. Divide this into a
718 * shift of (up to 63) followed by a constant shift of 1.
719 */
720 tcg_gen_xori_tl(shift, shift, 63);
721 tcg_gen_shr_tl(t2, s2, shift);
722 tcg_gen_shri_tl(t2, t2, 1);
723
724 tcg_gen_or_tl(dst, t1, t2);
725#else
726 g_assert_not_reached();
727#endif
728}
729
730static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
731{
732#ifdef TARGET_SPARC64
733 gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
734#else
735 g_assert_not_reached();
736#endif
737}
738
19f329ad 739// 1
0c2e96c1 740static void gen_op_eval_ba(TCGv dst)
19f329ad
BS
741{
742 tcg_gen_movi_tl(dst, 1);
743}
744
19f329ad 745// 0
0c2e96c1 746static void gen_op_eval_bn(TCGv dst)
19f329ad
BS
747{
748 tcg_gen_movi_tl(dst, 0);
749}
750
19f329ad
BS
751/*
752 FPSR bit field FCC1 | FCC0:
753 0 =
754 1 <
755 2 >
756 3 unordered
757*/
0c2e96c1 758static void gen_mov_reg_FCC0(TCGv reg, TCGv src,
19f329ad
BS
759 unsigned int fcc_offset)
760{
ba6a9d8c 761 tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
19f329ad
BS
762 tcg_gen_andi_tl(reg, reg, 0x1);
763}
764
0c2e96c1 765static void gen_mov_reg_FCC1(TCGv reg, TCGv src, unsigned int fcc_offset)
19f329ad 766{
ba6a9d8c 767 tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
19f329ad
BS
768 tcg_gen_andi_tl(reg, reg, 0x1);
769}
770
771// !0: FCC0 | FCC1
0c2e96c1 772static void gen_op_eval_fbne(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 773{
de9e9d9f 774 TCGv t0 = tcg_temp_new();
19f329ad 775 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
776 gen_mov_reg_FCC1(t0, src, fcc_offset);
777 tcg_gen_or_tl(dst, dst, t0);
19f329ad
BS
778}
779
780// 1 or 2: FCC0 ^ FCC1
0c2e96c1 781static void gen_op_eval_fblg(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 782{
de9e9d9f 783 TCGv t0 = tcg_temp_new();
19f329ad 784 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
785 gen_mov_reg_FCC1(t0, src, fcc_offset);
786 tcg_gen_xor_tl(dst, dst, t0);
19f329ad
BS
787}
788
789// 1 or 3: FCC0
0c2e96c1 790static void gen_op_eval_fbul(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad
BS
791{
792 gen_mov_reg_FCC0(dst, src, fcc_offset);
793}
794
795// 1: FCC0 & !FCC1
0c2e96c1 796static void gen_op_eval_fbl(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 797{
de9e9d9f 798 TCGv t0 = tcg_temp_new();
19f329ad 799 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
800 gen_mov_reg_FCC1(t0, src, fcc_offset);
801 tcg_gen_andc_tl(dst, dst, t0);
19f329ad
BS
802}
803
804// 2 or 3: FCC1
0c2e96c1 805static void gen_op_eval_fbug(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad
BS
806{
807 gen_mov_reg_FCC1(dst, src, fcc_offset);
808}
809
810// 2: !FCC0 & FCC1
0c2e96c1 811static void gen_op_eval_fbg(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 812{
de9e9d9f 813 TCGv t0 = tcg_temp_new();
19f329ad 814 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
815 gen_mov_reg_FCC1(t0, src, fcc_offset);
816 tcg_gen_andc_tl(dst, t0, dst);
19f329ad
BS
817}
818
819// 3: FCC0 & FCC1
0c2e96c1 820static void gen_op_eval_fbu(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 821{
de9e9d9f 822 TCGv t0 = tcg_temp_new();
19f329ad 823 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
824 gen_mov_reg_FCC1(t0, src, fcc_offset);
825 tcg_gen_and_tl(dst, dst, t0);
19f329ad
BS
826}
827
828// 0: !(FCC0 | FCC1)
0c2e96c1 829static void gen_op_eval_fbe(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 830{
de9e9d9f 831 TCGv t0 = tcg_temp_new();
19f329ad 832 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
833 gen_mov_reg_FCC1(t0, src, fcc_offset);
834 tcg_gen_or_tl(dst, dst, t0);
19f329ad
BS
835 tcg_gen_xori_tl(dst, dst, 0x1);
836}
837
838// 0 or 3: !(FCC0 ^ FCC1)
0c2e96c1 839static void gen_op_eval_fbue(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 840{
de9e9d9f 841 TCGv t0 = tcg_temp_new();
19f329ad 842 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
843 gen_mov_reg_FCC1(t0, src, fcc_offset);
844 tcg_gen_xor_tl(dst, dst, t0);
19f329ad
BS
845 tcg_gen_xori_tl(dst, dst, 0x1);
846}
847
848// 0 or 2: !FCC0
0c2e96c1 849static void gen_op_eval_fbge(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad
BS
850{
851 gen_mov_reg_FCC0(dst, src, fcc_offset);
852 tcg_gen_xori_tl(dst, dst, 0x1);
853}
854
855// !1: !(FCC0 & !FCC1)
0c2e96c1 856static void gen_op_eval_fbuge(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 857{
de9e9d9f 858 TCGv t0 = tcg_temp_new();
19f329ad 859 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
860 gen_mov_reg_FCC1(t0, src, fcc_offset);
861 tcg_gen_andc_tl(dst, dst, t0);
19f329ad
BS
862 tcg_gen_xori_tl(dst, dst, 0x1);
863}
864
865// 0 or 1: !FCC1
0c2e96c1 866static void gen_op_eval_fble(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad
BS
867{
868 gen_mov_reg_FCC1(dst, src, fcc_offset);
869 tcg_gen_xori_tl(dst, dst, 0x1);
870}
871
872// !2: !(!FCC0 & FCC1)
0c2e96c1 873static void gen_op_eval_fbule(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 874{
de9e9d9f 875 TCGv t0 = tcg_temp_new();
19f329ad 876 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
877 gen_mov_reg_FCC1(t0, src, fcc_offset);
878 tcg_gen_andc_tl(dst, t0, dst);
19f329ad 879 tcg_gen_xori_tl(dst, dst, 0x1);
19f329ad
BS
880}
881
882// !3: !(FCC0 & FCC1)
0c2e96c1 883static void gen_op_eval_fbo(TCGv dst, TCGv src, unsigned int fcc_offset)
19f329ad 884{
de9e9d9f 885 TCGv t0 = tcg_temp_new();
19f329ad 886 gen_mov_reg_FCC0(dst, src, fcc_offset);
de9e9d9f
RH
887 gen_mov_reg_FCC1(t0, src, fcc_offset);
888 tcg_gen_and_tl(dst, dst, t0);
19f329ad
BS
889 tcg_gen_xori_tl(dst, dst, 0x1);
890}
891
89527e3a
RH
892static void finishing_insn(DisasContext *dc)
893{
894 /*
895 * From here, there is no future path through an unwinding exception.
896 * If the current insn cannot raise an exception, the computation of
897 * cpu_cond may be able to be elided.
898 */
899 if (dc->cpu_cond_live) {
900 tcg_gen_discard_tl(cpu_cond);
901 dc->cpu_cond_live = false;
902 }
903}
904
0c2e96c1 905static void gen_generic_branch(DisasContext *dc)
83469015 906{
00ab7e61
RH
907 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
908 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
533f042f 909 TCGv c2 = tcg_constant_tl(dc->jump.c2);
19f329ad 910
533f042f 911 tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
83469015
FB
912}
913
4af984a7
BS
914/* call this function before using the condition register as it may
915 have been set for a jump */
0c2e96c1 916static void flush_cond(DisasContext *dc)
83469015
FB
917{
918 if (dc->npc == JUMP_PC) {
2e655fe7 919 gen_generic_branch(dc);
99c82c47 920 dc->npc = DYNAMIC_PC_LOOKUP;
83469015
FB
921 }
922}
923
0c2e96c1 924static void save_npc(DisasContext *dc)
72cbca10 925{
633c4283
RH
926 if (dc->npc & 3) {
927 switch (dc->npc) {
928 case JUMP_PC:
929 gen_generic_branch(dc);
99c82c47 930 dc->npc = DYNAMIC_PC_LOOKUP;
633c4283
RH
931 break;
932 case DYNAMIC_PC:
933 case DYNAMIC_PC_LOOKUP:
934 break;
935 default:
936 g_assert_not_reached();
937 }
938 } else {
2f5680ee 939 tcg_gen_movi_tl(cpu_npc, dc->npc);
72cbca10
FB
940 }
941}
942
0c2e96c1 943static void save_state(DisasContext *dc)
20132b96
RH
944{
945 tcg_gen_movi_tl(cpu_pc, dc->pc);
934da7ee 946 save_npc(dc);
72cbca10
FB
947}
948
4fbe0067
RH
949static void gen_exception(DisasContext *dc, int which)
950{
89527e3a 951 finishing_insn(dc);
4fbe0067 952 save_state(dc);
ad75a51e 953 gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
af00be49 954 dc->base.is_jmp = DISAS_NORETURN;
4fbe0067
RH
955}
956
186e7890 957static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
35e94905 958{
186e7890
RH
959 DisasDelayException *e = g_new0(DisasDelayException, 1);
960
961 e->next = dc->delay_excp_list;
962 dc->delay_excp_list = e;
963
964 e->lab = gen_new_label();
965 e->excp = excp;
966 e->pc = dc->pc;
967 /* Caller must have used flush_cond before branch. */
968 assert(e->npc != JUMP_PC);
969 e->npc = dc->npc;
970
971 return e->lab;
972}
973
974static TCGLabel *delay_exception(DisasContext *dc, int excp)
975{
976 return delay_exceptionv(dc, tcg_constant_i32(excp));
977}
978
979static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
980{
981 TCGv t = tcg_temp_new();
982 TCGLabel *lab;
983
984 tcg_gen_andi_tl(t, addr, mask);
985
986 flush_cond(dc);
987 lab = delay_exception(dc, TT_UNALIGNED);
988 tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
35e94905
RH
989}
990
0c2e96c1 991static void gen_mov_pc_npc(DisasContext *dc)
0bee699e 992{
89527e3a
RH
993 finishing_insn(dc);
994
633c4283
RH
995 if (dc->npc & 3) {
996 switch (dc->npc) {
997 case JUMP_PC:
998 gen_generic_branch(dc);
999 tcg_gen_mov_tl(cpu_pc, cpu_npc);
99c82c47 1000 dc->pc = DYNAMIC_PC_LOOKUP;
633c4283
RH
1001 break;
1002 case DYNAMIC_PC:
1003 case DYNAMIC_PC_LOOKUP:
1004 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1005 dc->pc = dc->npc;
1006 break;
1007 default:
1008 g_assert_not_reached();
1009 }
0bee699e
FB
1010 } else {
1011 dc->pc = dc->npc;
1012 }
1013}
1014
2a484ecf 1015static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
416fcaea 1016 DisasContext *dc)
19f329ad 1017{
b597eedc 1018 TCGv t1;
416fcaea 1019
2a1905c7 1020 cmp->c1 = t1 = tcg_temp_new();
c8507ebf 1021 cmp->c2 = 0;
2a1905c7
RH
1022
1023 switch (cond & 7) {
1024 case 0x0: /* never */
1025 cmp->cond = TCG_COND_NEVER;
c8507ebf 1026 cmp->c1 = tcg_constant_tl(0);
2a1905c7
RH
1027 break;
1028
1029 case 0x1: /* eq: Z */
1030 cmp->cond = TCG_COND_EQ;
1031 if (TARGET_LONG_BITS == 32 || xcc) {
1032 tcg_gen_mov_tl(t1, cpu_cc_Z);
1033 } else {
1034 tcg_gen_ext32u_tl(t1, cpu_icc_Z);
1035 }
1036 break;
1037
1038 case 0x2: /* le: Z | (N ^ V) */
1039 /*
1040 * Simplify:
1041 * cc_Z || (N ^ V) < 0 NE
1042 * cc_Z && !((N ^ V) < 0) EQ
1043 * cc_Z & ~((N ^ V) >> TLB) EQ
1044 */
1045 cmp->cond = TCG_COND_EQ;
1046 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1047 tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
1048 tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
1049 if (TARGET_LONG_BITS == 64 && !xcc) {
1050 tcg_gen_ext32u_tl(t1, t1);
1051 }
1052 break;
1053
1054 case 0x3: /* lt: N ^ V */
1055 cmp->cond = TCG_COND_LT;
1056 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1057 if (TARGET_LONG_BITS == 64 && !xcc) {
1058 tcg_gen_ext32s_tl(t1, t1);
1059 }
1060 break;
1061
1062 case 0x4: /* leu: Z | C */
1063 /*
1064 * Simplify:
1065 * cc_Z == 0 || cc_C != 0 NE
1066 * cc_Z != 0 && cc_C == 0 EQ
1067 * cc_Z & (cc_C ? 0 : -1) EQ
1068 * cc_Z & (cc_C - 1) EQ
1069 */
1070 cmp->cond = TCG_COND_EQ;
1071 if (TARGET_LONG_BITS == 32 || xcc) {
1072 tcg_gen_subi_tl(t1, cpu_cc_C, 1);
1073 tcg_gen_and_tl(t1, t1, cpu_cc_Z);
1074 } else {
1075 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1076 tcg_gen_subi_tl(t1, t1, 1);
1077 tcg_gen_and_tl(t1, t1, cpu_icc_Z);
1078 tcg_gen_ext32u_tl(t1, t1);
1079 }
1080 break;
1081
1082 case 0x5: /* ltu: C */
2a484ecf 1083 cmp->cond = TCG_COND_NE;
2a1905c7
RH
1084 if (TARGET_LONG_BITS == 32 || xcc) {
1085 tcg_gen_mov_tl(t1, cpu_cc_C);
1086 } else {
1087 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1088 }
1089 break;
2a484ecf 1090
2a1905c7
RH
1091 case 0x6: /* neg: N */
1092 cmp->cond = TCG_COND_LT;
1093 if (TARGET_LONG_BITS == 32 || xcc) {
1094 tcg_gen_mov_tl(t1, cpu_cc_N);
1095 } else {
1096 tcg_gen_ext32s_tl(t1, cpu_cc_N);
2a484ecf 1097 }
19f329ad 1098 break;
2a1905c7
RH
1099
1100 case 0x7: /* vs: V */
1101 cmp->cond = TCG_COND_LT;
1102 if (TARGET_LONG_BITS == 32 || xcc) {
1103 tcg_gen_mov_tl(t1, cpu_cc_V);
1104 } else {
1105 tcg_gen_ext32s_tl(t1, cpu_cc_V);
1106 }
1107 break;
1108 }
1109 if (cond & 8) {
1110 cmp->cond = tcg_invert_cond(cmp->cond);
19f329ad
BS
1111 }
1112}
7a3f1944 1113
416fcaea 1114static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
e8af50a3 1115{
19f329ad 1116 unsigned int offset;
416fcaea
RH
1117 TCGv r_dst;
1118
1119 /* For now we still generate a straight boolean result. */
1120 cmp->cond = TCG_COND_NE;
416fcaea 1121 cmp->c1 = r_dst = tcg_temp_new();
c8507ebf 1122 cmp->c2 = 0;
19f329ad 1123
19f329ad
BS
1124 switch (cc) {
1125 default:
1126 case 0x0:
1127 offset = 0;
1128 break;
1129 case 0x1:
1130 offset = 32 - 10;
1131 break;
1132 case 0x2:
1133 offset = 34 - 10;
1134 break;
1135 case 0x3:
1136 offset = 36 - 10;
1137 break;
1138 }
1139
1140 switch (cond) {
1141 case 0x0:
1142 gen_op_eval_bn(r_dst);
1143 break;
1144 case 0x1:
87e92502 1145 gen_op_eval_fbne(r_dst, cpu_fsr, offset);
19f329ad
BS
1146 break;
1147 case 0x2:
87e92502 1148 gen_op_eval_fblg(r_dst, cpu_fsr, offset);
19f329ad
BS
1149 break;
1150 case 0x3:
87e92502 1151 gen_op_eval_fbul(r_dst, cpu_fsr, offset);
19f329ad
BS
1152 break;
1153 case 0x4:
87e92502 1154 gen_op_eval_fbl(r_dst, cpu_fsr, offset);
19f329ad
BS
1155 break;
1156 case 0x5:
87e92502 1157 gen_op_eval_fbug(r_dst, cpu_fsr, offset);
19f329ad
BS
1158 break;
1159 case 0x6:
87e92502 1160 gen_op_eval_fbg(r_dst, cpu_fsr, offset);
19f329ad
BS
1161 break;
1162 case 0x7:
87e92502 1163 gen_op_eval_fbu(r_dst, cpu_fsr, offset);
19f329ad
BS
1164 break;
1165 case 0x8:
1166 gen_op_eval_ba(r_dst);
1167 break;
1168 case 0x9:
87e92502 1169 gen_op_eval_fbe(r_dst, cpu_fsr, offset);
19f329ad
BS
1170 break;
1171 case 0xa:
87e92502 1172 gen_op_eval_fbue(r_dst, cpu_fsr, offset);
19f329ad
BS
1173 break;
1174 case 0xb:
87e92502 1175 gen_op_eval_fbge(r_dst, cpu_fsr, offset);
19f329ad
BS
1176 break;
1177 case 0xc:
87e92502 1178 gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
19f329ad
BS
1179 break;
1180 case 0xd:
87e92502 1181 gen_op_eval_fble(r_dst, cpu_fsr, offset);
19f329ad
BS
1182 break;
1183 case 0xe:
87e92502 1184 gen_op_eval_fbule(r_dst, cpu_fsr, offset);
19f329ad
BS
1185 break;
1186 case 0xf:
87e92502 1187 gen_op_eval_fbo(r_dst, cpu_fsr, offset);
19f329ad
BS
1188 break;
1189 }
e8af50a3 1190}
00f219bf 1191
2c4f56c9
RH
1192static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
1193{
1194 static const TCGCond cond_reg[4] = {
1195 TCG_COND_NEVER, /* reserved */
1196 TCG_COND_EQ,
1197 TCG_COND_LE,
1198 TCG_COND_LT,
1199 };
1200 TCGCond tcond;
1201
1202 if ((cond & 3) == 0) {
1203 return false;
1204 }
1205 tcond = cond_reg[cond & 3];
1206 if (cond & 4) {
1207 tcond = tcg_invert_cond(tcond);
1208 }
1209
1210 cmp->cond = tcond;
816f89b7 1211 cmp->c1 = tcg_temp_new();
c8507ebf 1212 cmp->c2 = 0;
816f89b7 1213 tcg_gen_mov_tl(cmp->c1, r_src);
2c4f56c9 1214 return true;
416fcaea
RH
1215}
1216
baf3dbf2
RH
1217static void gen_op_clear_ieee_excp_and_FTT(void)
1218{
1219 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1220}
1221
1222static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1223{
1224 gen_op_clear_ieee_excp_and_FTT();
1225 tcg_gen_mov_i32(dst, src);
1226}
1227
1228static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1229{
1230 gen_op_clear_ieee_excp_and_FTT();
1231 gen_helper_fnegs(dst, src);
1232}
1233
1234static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1235{
1236 gen_op_clear_ieee_excp_and_FTT();
1237 gen_helper_fabss(dst, src);
1238}
1239
c6d83e4f
RH
1240static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1241{
1242 gen_op_clear_ieee_excp_and_FTT();
1243 tcg_gen_mov_i64(dst, src);
1244}
1245
1246static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1247{
1248 gen_op_clear_ieee_excp_and_FTT();
1249 gen_helper_fnegd(dst, src);
1250}
1251
1252static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1253{
1254 gen_op_clear_ieee_excp_and_FTT();
1255 gen_helper_fabsd(dst, src);
1256}
1257
3475187d 1258#ifdef TARGET_SPARC64
0c2e96c1 1259static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
7e8c2b6c 1260{
714547bb
BS
1261 switch (fccno) {
1262 case 0:
ad75a51e 1263 gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1264 break;
1265 case 1:
ad75a51e 1266 gen_helper_fcmps_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1267 break;
1268 case 2:
ad75a51e 1269 gen_helper_fcmps_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1270 break;
1271 case 3:
ad75a51e 1272 gen_helper_fcmps_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1273 break;
1274 }
7e8c2b6c
BS
1275}
1276
0c2e96c1 1277static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1278{
a7812ae4
PB
1279 switch (fccno) {
1280 case 0:
ad75a51e 1281 gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1282 break;
1283 case 1:
ad75a51e 1284 gen_helper_fcmpd_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1285 break;
1286 case 2:
ad75a51e 1287 gen_helper_fcmpd_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1288 break;
1289 case 3:
ad75a51e 1290 gen_helper_fcmpd_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1291 break;
1292 }
7e8c2b6c
BS
1293}
1294
0c2e96c1 1295static void gen_op_fcmpq(int fccno)
7e8c2b6c 1296{
a7812ae4
PB
1297 switch (fccno) {
1298 case 0:
ad75a51e 1299 gen_helper_fcmpq(cpu_fsr, tcg_env);
a7812ae4
PB
1300 break;
1301 case 1:
ad75a51e 1302 gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env);
a7812ae4
PB
1303 break;
1304 case 2:
ad75a51e 1305 gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env);
a7812ae4
PB
1306 break;
1307 case 3:
ad75a51e 1308 gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env);
a7812ae4
PB
1309 break;
1310 }
7e8c2b6c 1311}
7e8c2b6c 1312
0c2e96c1 1313static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
7e8c2b6c 1314{
714547bb
BS
1315 switch (fccno) {
1316 case 0:
ad75a51e 1317 gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1318 break;
1319 case 1:
ad75a51e 1320 gen_helper_fcmpes_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1321 break;
1322 case 2:
ad75a51e 1323 gen_helper_fcmpes_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1324 break;
1325 case 3:
ad75a51e 1326 gen_helper_fcmpes_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
714547bb
BS
1327 break;
1328 }
7e8c2b6c
BS
1329}
1330
0c2e96c1 1331static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1332{
a7812ae4
PB
1333 switch (fccno) {
1334 case 0:
ad75a51e 1335 gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1336 break;
1337 case 1:
ad75a51e 1338 gen_helper_fcmped_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1339 break;
1340 case 2:
ad75a51e 1341 gen_helper_fcmped_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1342 break;
1343 case 3:
ad75a51e 1344 gen_helper_fcmped_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2);
a7812ae4
PB
1345 break;
1346 }
7e8c2b6c
BS
1347}
1348
0c2e96c1 1349static void gen_op_fcmpeq(int fccno)
7e8c2b6c 1350{
a7812ae4
PB
1351 switch (fccno) {
1352 case 0:
ad75a51e 1353 gen_helper_fcmpeq(cpu_fsr, tcg_env);
a7812ae4
PB
1354 break;
1355 case 1:
ad75a51e 1356 gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env);
a7812ae4
PB
1357 break;
1358 case 2:
ad75a51e 1359 gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env);
a7812ae4
PB
1360 break;
1361 case 3:
ad75a51e 1362 gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env);
a7812ae4
PB
1363 break;
1364 }
7e8c2b6c 1365}
7e8c2b6c
BS
1366
1367#else
1368
0c2e96c1 1369static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
7e8c2b6c 1370{
ad75a51e 1371 gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2);
7e8c2b6c
BS
1372}
1373
0c2e96c1 1374static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1375{
ad75a51e 1376 gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2);
7e8c2b6c
BS
1377}
1378
0c2e96c1 1379static void gen_op_fcmpq(int fccno)
7e8c2b6c 1380{
ad75a51e 1381 gen_helper_fcmpq(cpu_fsr, tcg_env);
7e8c2b6c 1382}
7e8c2b6c 1383
0c2e96c1 1384static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
7e8c2b6c 1385{
ad75a51e 1386 gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2);
7e8c2b6c
BS
1387}
1388
0c2e96c1 1389static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
7e8c2b6c 1390{
ad75a51e 1391 gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2);
7e8c2b6c
BS
1392}
1393
0c2e96c1 1394static void gen_op_fcmpeq(int fccno)
7e8c2b6c 1395{
ad75a51e 1396 gen_helper_fcmpeq(cpu_fsr, tcg_env);
7e8c2b6c
BS
1397}
1398#endif
1399
4fbe0067 1400static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags)
134d77a1 1401{
47ad35f1 1402 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
87e92502 1403 tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
4fbe0067 1404 gen_exception(dc, TT_FP_EXCP);
134d77a1
BS
1405}
1406
5b12f1e8 1407static int gen_trap_ifnofpu(DisasContext *dc)
a80dde08
FB
1408{
1409#if !defined(CONFIG_USER_ONLY)
1410 if (!dc->fpu_enabled) {
4fbe0067 1411 gen_exception(dc, TT_NFPU_INSN);
a80dde08
FB
1412 return 1;
1413 }
1414#endif
1415 return 0;
1416}
1417
1a2fb1c0 1418/* asi moves */
7ec1e5ea
RH
1419typedef enum {
1420 GET_ASI_HELPER,
1421 GET_ASI_EXCP,
f0913be0 1422 GET_ASI_DIRECT,
e4dc0052 1423 GET_ASI_DTWINX,
ca5ce572
RH
1424 GET_ASI_BLOCK,
1425 GET_ASI_SHORT,
34810610
RH
1426 GET_ASI_BCOPY,
1427 GET_ASI_BFILL,
7ec1e5ea
RH
1428} ASIType;
1429
1430typedef struct {
1431 ASIType type;
a6d567e5 1432 int asi;
f0913be0 1433 int mem_idx;
14776ab5 1434 MemOp memop;
7ec1e5ea 1435} DisasASI;
1a2fb1c0 1436
811cc0b0
RH
1437/*
1438 * Build DisasASI.
1439 * For asi == -1, treat as non-asi.
1440 * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1441 */
1442static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
7ec1e5ea 1443{
7ec1e5ea 1444 ASIType type = GET_ASI_HELPER;
f0913be0 1445 int mem_idx = dc->mem_idx;
7ec1e5ea 1446
811cc0b0
RH
1447 if (asi == -1) {
1448 /* Artificial "non-asi" case. */
1449 type = GET_ASI_DIRECT;
1450 goto done;
1451 }
1452
7ec1e5ea
RH
1453#ifndef TARGET_SPARC64
1454 /* Before v9, all asis are immediate and privileged. */
811cc0b0 1455 if (asi < 0) {
22e70060 1456 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
1457 type = GET_ASI_EXCP;
1458 } else if (supervisor(dc)
1459 /* Note that LEON accepts ASI_USERDATA in user mode, for
1460 use with CASA. Also note that previous versions of
0cc1f4bf
RH
1461 QEMU allowed (and old versions of gcc emitted) ASI_P
1462 for LEON, which is incorrect. */
1463 || (asi == ASI_USERDATA
7ec1e5ea 1464 && (dc->def->features & CPU_FEATURE_CASA))) {
f0913be0
RH
1465 switch (asi) {
1466 case ASI_USERDATA: /* User data access */
1467 mem_idx = MMU_USER_IDX;
1468 type = GET_ASI_DIRECT;
1469 break;
1470 case ASI_KERNELDATA: /* Supervisor data access */
1471 mem_idx = MMU_KERNEL_IDX;
1472 type = GET_ASI_DIRECT;
1473 break;
7f87c905
RH
1474 case ASI_M_BYPASS: /* MMU passthrough */
1475 case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1476 mem_idx = MMU_PHYS_IDX;
1477 type = GET_ASI_DIRECT;
1478 break;
34810610
RH
1479 case ASI_M_BCOPY: /* Block copy, sta access */
1480 mem_idx = MMU_KERNEL_IDX;
1481 type = GET_ASI_BCOPY;
1482 break;
1483 case ASI_M_BFILL: /* Block fill, stda access */
1484 mem_idx = MMU_KERNEL_IDX;
1485 type = GET_ASI_BFILL;
1486 break;
f0913be0 1487 }
6e10f37c
KF
1488
1489 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
1490 * permissions check in get_physical_address(..).
1491 */
1492 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1a2fb1c0 1493 } else {
7ec1e5ea
RH
1494 gen_exception(dc, TT_PRIV_INSN);
1495 type = GET_ASI_EXCP;
1496 }
1497#else
811cc0b0 1498 if (asi < 0) {
7ec1e5ea 1499 asi = dc->asi;
1a2fb1c0 1500 }
f0913be0
RH
1501 /* With v9, all asis below 0x80 are privileged. */
1502 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1503 down that bit into DisasContext. For the moment that's ok,
1504 since the direct implementations below doesn't have any ASIs
1505 in the restricted [0x30, 0x7f] range, and the check will be
1506 done properly in the helper. */
1507 if (!supervisor(dc) && asi < 0x80) {
1508 gen_exception(dc, TT_PRIV_ACT);
1509 type = GET_ASI_EXCP;
1510 } else {
1511 switch (asi) {
7f87c905
RH
1512 case ASI_REAL: /* Bypass */
1513 case ASI_REAL_IO: /* Bypass, non-cacheable */
1514 case ASI_REAL_L: /* Bypass LE */
1515 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1516 case ASI_TWINX_REAL: /* Real address, twinx */
1517 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
34a6e13d
RH
1518 case ASI_QUAD_LDD_PHYS:
1519 case ASI_QUAD_LDD_PHYS_L:
7f87c905
RH
1520 mem_idx = MMU_PHYS_IDX;
1521 break;
f0913be0
RH
1522 case ASI_N: /* Nucleus */
1523 case ASI_NL: /* Nucleus LE */
e4dc0052
RH
1524 case ASI_TWINX_N:
1525 case ASI_TWINX_NL:
34a6e13d
RH
1526 case ASI_NUCLEUS_QUAD_LDD:
1527 case ASI_NUCLEUS_QUAD_LDD_L:
9a10756d 1528 if (hypervisor(dc)) {
84f8f587 1529 mem_idx = MMU_PHYS_IDX;
9a10756d
AT
1530 } else {
1531 mem_idx = MMU_NUCLEUS_IDX;
1532 }
f0913be0
RH
1533 break;
1534 case ASI_AIUP: /* As if user primary */
1535 case ASI_AIUPL: /* As if user primary LE */
e4dc0052
RH
1536 case ASI_TWINX_AIUP:
1537 case ASI_TWINX_AIUP_L:
ca5ce572
RH
1538 case ASI_BLK_AIUP_4V:
1539 case ASI_BLK_AIUP_L_4V:
1540 case ASI_BLK_AIUP:
1541 case ASI_BLK_AIUPL:
f0913be0
RH
1542 mem_idx = MMU_USER_IDX;
1543 break;
1544 case ASI_AIUS: /* As if user secondary */
1545 case ASI_AIUSL: /* As if user secondary LE */
e4dc0052
RH
1546 case ASI_TWINX_AIUS:
1547 case ASI_TWINX_AIUS_L:
ca5ce572
RH
1548 case ASI_BLK_AIUS_4V:
1549 case ASI_BLK_AIUS_L_4V:
1550 case ASI_BLK_AIUS:
1551 case ASI_BLK_AIUSL:
f0913be0
RH
1552 mem_idx = MMU_USER_SECONDARY_IDX;
1553 break;
1554 case ASI_S: /* Secondary */
1555 case ASI_SL: /* Secondary LE */
e4dc0052
RH
1556 case ASI_TWINX_S:
1557 case ASI_TWINX_SL:
ca5ce572
RH
1558 case ASI_BLK_COMMIT_S:
1559 case ASI_BLK_S:
1560 case ASI_BLK_SL:
1561 case ASI_FL8_S:
1562 case ASI_FL8_SL:
1563 case ASI_FL16_S:
1564 case ASI_FL16_SL:
f0913be0
RH
1565 if (mem_idx == MMU_USER_IDX) {
1566 mem_idx = MMU_USER_SECONDARY_IDX;
1567 } else if (mem_idx == MMU_KERNEL_IDX) {
1568 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1569 }
1570 break;
1571 case ASI_P: /* Primary */
1572 case ASI_PL: /* Primary LE */
e4dc0052
RH
1573 case ASI_TWINX_P:
1574 case ASI_TWINX_PL:
ca5ce572
RH
1575 case ASI_BLK_COMMIT_P:
1576 case ASI_BLK_P:
1577 case ASI_BLK_PL:
1578 case ASI_FL8_P:
1579 case ASI_FL8_PL:
1580 case ASI_FL16_P:
1581 case ASI_FL16_PL:
f0913be0
RH
1582 break;
1583 }
1584 switch (asi) {
7f87c905
RH
1585 case ASI_REAL:
1586 case ASI_REAL_IO:
1587 case ASI_REAL_L:
1588 case ASI_REAL_IO_L:
f0913be0
RH
1589 case ASI_N:
1590 case ASI_NL:
1591 case ASI_AIUP:
1592 case ASI_AIUPL:
1593 case ASI_AIUS:
1594 case ASI_AIUSL:
1595 case ASI_S:
1596 case ASI_SL:
1597 case ASI_P:
1598 case ASI_PL:
1599 type = GET_ASI_DIRECT;
1600 break;
7f87c905
RH
1601 case ASI_TWINX_REAL:
1602 case ASI_TWINX_REAL_L:
e4dc0052
RH
1603 case ASI_TWINX_N:
1604 case ASI_TWINX_NL:
1605 case ASI_TWINX_AIUP:
1606 case ASI_TWINX_AIUP_L:
1607 case ASI_TWINX_AIUS:
1608 case ASI_TWINX_AIUS_L:
1609 case ASI_TWINX_P:
1610 case ASI_TWINX_PL:
1611 case ASI_TWINX_S:
1612 case ASI_TWINX_SL:
34a6e13d
RH
1613 case ASI_QUAD_LDD_PHYS:
1614 case ASI_QUAD_LDD_PHYS_L:
1615 case ASI_NUCLEUS_QUAD_LDD:
1616 case ASI_NUCLEUS_QUAD_LDD_L:
e4dc0052
RH
1617 type = GET_ASI_DTWINX;
1618 break;
ca5ce572
RH
1619 case ASI_BLK_COMMIT_P:
1620 case ASI_BLK_COMMIT_S:
1621 case ASI_BLK_AIUP_4V:
1622 case ASI_BLK_AIUP_L_4V:
1623 case ASI_BLK_AIUP:
1624 case ASI_BLK_AIUPL:
1625 case ASI_BLK_AIUS_4V:
1626 case ASI_BLK_AIUS_L_4V:
1627 case ASI_BLK_AIUS:
1628 case ASI_BLK_AIUSL:
1629 case ASI_BLK_S:
1630 case ASI_BLK_SL:
1631 case ASI_BLK_P:
1632 case ASI_BLK_PL:
1633 type = GET_ASI_BLOCK;
1634 break;
1635 case ASI_FL8_S:
1636 case ASI_FL8_SL:
1637 case ASI_FL8_P:
1638 case ASI_FL8_PL:
1639 memop = MO_UB;
1640 type = GET_ASI_SHORT;
1641 break;
1642 case ASI_FL16_S:
1643 case ASI_FL16_SL:
1644 case ASI_FL16_P:
1645 case ASI_FL16_PL:
1646 memop = MO_TEUW;
1647 type = GET_ASI_SHORT;
1648 break;
f0913be0
RH
1649 }
1650 /* The little-endian asis all have bit 3 set. */
1651 if (asi & 8) {
1652 memop ^= MO_BSWAP;
1653 }
1654 }
7ec1e5ea
RH
1655#endif
1656
811cc0b0 1657 done:
f0913be0 1658 return (DisasASI){ type, asi, mem_idx, memop };
0425bee5
BS
1659}
1660
a76779ee
RH
1661#if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1662static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1663 TCGv_i32 asi, TCGv_i32 mop)
1664{
1665 g_assert_not_reached();
1666}
1667
1668static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1669 TCGv_i32 asi, TCGv_i32 mop)
1670{
1671 g_assert_not_reached();
1672}
1673#endif
1674
42071fc1 1675static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
0425bee5 1676{
c03a0fd1 1677 switch (da->type) {
7ec1e5ea
RH
1678 case GET_ASI_EXCP:
1679 break;
e4dc0052
RH
1680 case GET_ASI_DTWINX: /* Reserved for ldda. */
1681 gen_exception(dc, TT_ILL_INSN);
1682 break;
f0913be0 1683 case GET_ASI_DIRECT:
c03a0fd1 1684 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
f0913be0 1685 break;
7ec1e5ea
RH
1686 default:
1687 {
c03a0fd1
RH
1688 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1689 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
7ec1e5ea
RH
1690
1691 save_state(dc);
22e70060 1692#ifdef TARGET_SPARC64
ad75a51e 1693 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
22e70060 1694#else
7ec1e5ea
RH
1695 {
1696 TCGv_i64 t64 = tcg_temp_new_i64();
ad75a51e 1697 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
7ec1e5ea 1698 tcg_gen_trunc_i64_tl(dst, t64);
7ec1e5ea 1699 }
22e70060 1700#endif
7ec1e5ea
RH
1701 }
1702 break;
1703 }
1a2fb1c0
BS
1704}
1705
42071fc1 1706static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
c03a0fd1
RH
1707{
1708 switch (da->type) {
7ec1e5ea
RH
1709 case GET_ASI_EXCP:
1710 break;
c03a0fd1 1711
e4dc0052 1712 case GET_ASI_DTWINX: /* Reserved for stda. */
c03a0fd1
RH
1713 if (TARGET_LONG_BITS == 32) {
1714 gen_exception(dc, TT_ILL_INSN);
1715 break;
1716 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
3390537b
AT
1717 /* Pre OpenSPARC CPUs don't have these */
1718 gen_exception(dc, TT_ILL_INSN);
c03a0fd1 1719 break;
3390537b 1720 }
c03a0fd1 1721 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
fc0cd867 1722 /* fall through */
c03a0fd1 1723
f0913be0 1724 case GET_ASI_DIRECT:
c03a0fd1 1725 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
f0913be0 1726 break;
c03a0fd1 1727
34810610 1728 case GET_ASI_BCOPY:
c03a0fd1 1729 assert(TARGET_LONG_BITS == 32);
34810610
RH
1730 /* Copy 32 bytes from the address in SRC to ADDR. */
1731 /* ??? The original qemu code suggests 4-byte alignment, dropping
1732 the low bits, but the only place I can see this used is in the
1733 Linux kernel with 32 byte alignment, which would make more sense
1734 as a cacheline-style operation. */
1735 {
1736 TCGv saddr = tcg_temp_new();
1737 TCGv daddr = tcg_temp_new();
00ab7e61 1738 TCGv four = tcg_constant_tl(4);
34810610
RH
1739 TCGv_i32 tmp = tcg_temp_new_i32();
1740 int i;
1741
1742 tcg_gen_andi_tl(saddr, src, -4);
1743 tcg_gen_andi_tl(daddr, addr, -4);
1744 for (i = 0; i < 32; i += 4) {
1745 /* Since the loads and stores are paired, allow the
1746 copy to happen in the host endianness. */
c03a0fd1
RH
1747 tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL);
1748 tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL);
34810610
RH
1749 tcg_gen_add_tl(saddr, saddr, four);
1750 tcg_gen_add_tl(daddr, daddr, four);
1751 }
34810610
RH
1752 }
1753 break;
c03a0fd1 1754
7ec1e5ea
RH
1755 default:
1756 {
c03a0fd1
RH
1757 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1758 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
7ec1e5ea
RH
1759
1760 save_state(dc);
22e70060 1761#ifdef TARGET_SPARC64
ad75a51e 1762 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
22e70060 1763#else
7ec1e5ea
RH
1764 {
1765 TCGv_i64 t64 = tcg_temp_new_i64();
1766 tcg_gen_extu_tl_i64(t64, src);
ad75a51e 1767 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
7ec1e5ea 1768 }
22e70060 1769#endif
7ec1e5ea
RH
1770
1771 /* A write to a TLB register may alter page maps. End the TB. */
1772 dc->npc = DYNAMIC_PC;
1773 }
1774 break;
1775 }
1a2fb1c0
BS
1776}
1777
dca544b9
RH
1778static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1779 TCGv dst, TCGv src, TCGv addr)
c03a0fd1
RH
1780{
1781 switch (da->type) {
7ec1e5ea
RH
1782 case GET_ASI_EXCP:
1783 break;
4fb554bc 1784 case GET_ASI_DIRECT:
dca544b9
RH
1785 tcg_gen_atomic_xchg_tl(dst, addr, src,
1786 da->mem_idx, da->memop | MO_ALIGN);
4fb554bc 1787 break;
7ec1e5ea 1788 default:
4fb554bc
RH
1789 /* ??? Should be DAE_invalid_asi. */
1790 gen_exception(dc, TT_DATA_ACCESS);
7ec1e5ea
RH
1791 break;
1792 }
1a2fb1c0
BS
1793}
1794
d0a11d25
RH
1795static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1796 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
c03a0fd1
RH
1797{
1798 switch (da->type) {
7268adeb 1799 case GET_ASI_EXCP:
7ec1e5ea 1800 return;
7268adeb 1801 case GET_ASI_DIRECT:
c03a0fd1
RH
1802 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1803 da->mem_idx, da->memop | MO_ALIGN);
7268adeb
RH
1804 break;
1805 default:
1806 /* ??? Should be DAE_invalid_asi. */
1807 gen_exception(dc, TT_DATA_ACCESS);
1808 break;
7ec1e5ea 1809 }
22e70060
RH
1810}
1811
cf07cd1e 1812static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
c03a0fd1
RH
1813{
1814 switch (da->type) {
7ec1e5ea
RH
1815 case GET_ASI_EXCP:
1816 break;
fbb4bbb6 1817 case GET_ASI_DIRECT:
cf07cd1e
RH
1818 tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1819 da->mem_idx, MO_UB);
fbb4bbb6 1820 break;
7ec1e5ea 1821 default:
3db010c3
RH
1822 /* ??? In theory, this should be raise DAE_invalid_asi.
1823 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
af00be49 1824 if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
ad75a51e 1825 gen_helper_exit_atomic(tcg_env);
3db010c3 1826 } else {
c03a0fd1 1827 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
00ab7e61 1828 TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
3db010c3
RH
1829 TCGv_i64 s64, t64;
1830
1831 save_state(dc);
1832 t64 = tcg_temp_new_i64();
ad75a51e 1833 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
3db010c3 1834
00ab7e61 1835 s64 = tcg_constant_i64(0xff);
ad75a51e 1836 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
3db010c3
RH
1837
1838 tcg_gen_trunc_i64_tl(dst, t64);
3db010c3
RH
1839
1840 /* End the TB. */
1841 dc->npc = DYNAMIC_PC;
1842 }
7ec1e5ea
RH
1843 break;
1844 }
22e70060 1845}
22e70060 1846
287b1152
RH
1847static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
1848 TCGv addr, int rd)
1a2fb1c0 1849{
3259b9e2
RH
1850 MemOp memop = da->memop;
1851 MemOp size = memop & MO_SIZE;
7705091c 1852 TCGv_i32 d32;
cb21b4da 1853 TCGv_i64 d64;
287b1152 1854 TCGv addr_tmp;
1a2fb1c0 1855
3259b9e2
RH
1856 /* TODO: Use 128-bit load/store below. */
1857 if (size == MO_128) {
1858 memop = (memop & ~MO_SIZE) | MO_64;
1859 }
1860
1861 switch (da->type) {
7ec1e5ea
RH
1862 case GET_ASI_EXCP:
1863 break;
7705091c
RH
1864
1865 case GET_ASI_DIRECT:
3259b9e2 1866 memop |= MO_ALIGN_4;
7705091c 1867 switch (size) {
3259b9e2 1868 case MO_32:
7705091c 1869 d32 = gen_dest_fpr_F(dc);
3259b9e2 1870 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
7705091c
RH
1871 gen_store_fpr_F(dc, rd, d32);
1872 break;
3259b9e2
RH
1873
1874 case MO_64:
1875 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop);
7705091c 1876 break;
3259b9e2
RH
1877
1878 case MO_128:
cb21b4da 1879 d64 = tcg_temp_new_i64();
3259b9e2 1880 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
287b1152
RH
1881 addr_tmp = tcg_temp_new();
1882 tcg_gen_addi_tl(addr_tmp, addr, 8);
1883 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
cb21b4da 1884 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
7705091c
RH
1885 break;
1886 default:
1887 g_assert_not_reached();
1888 }
1889 break;
1890
ca5ce572
RH
1891 case GET_ASI_BLOCK:
1892 /* Valid for lddfa on aligned registers only. */
3259b9e2 1893 if (orig_size == MO_64 && (rd & 7) == 0) {
80883227 1894 /* The first operation checks required alignment. */
287b1152
RH
1895 addr_tmp = tcg_temp_new();
1896 for (int i = 0; ; ++i) {
3259b9e2
RH
1897 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
1898 memop | (i == 0 ? MO_ALIGN_64 : 0));
ca5ce572
RH
1899 if (i == 7) {
1900 break;
1901 }
287b1152
RH
1902 tcg_gen_addi_tl(addr_tmp, addr, 8);
1903 addr = addr_tmp;
ca5ce572 1904 }
ca5ce572
RH
1905 } else {
1906 gen_exception(dc, TT_ILL_INSN);
1907 }
1908 break;
1909
1910 case GET_ASI_SHORT:
1911 /* Valid for lddfa only. */
3259b9e2
RH
1912 if (orig_size == MO_64) {
1913 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1914 memop | MO_ALIGN);
ca5ce572
RH
1915 } else {
1916 gen_exception(dc, TT_ILL_INSN);
1917 }
1918 break;
1919
7ec1e5ea
RH
1920 default:
1921 {
3259b9e2
RH
1922 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1923 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
7ec1e5ea
RH
1924
1925 save_state(dc);
f2fe396f
RH
1926 /* According to the table in the UA2011 manual, the only
1927 other asis that are valid for ldfa/lddfa/ldqfa are
1928 the NO_FAULT asis. We still need a helper for these,
1929 but we can just use the integer asi helper for them. */
1930 switch (size) {
3259b9e2 1931 case MO_32:
cb21b4da 1932 d64 = tcg_temp_new_i64();
ad75a51e 1933 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
cb21b4da
RH
1934 d32 = gen_dest_fpr_F(dc);
1935 tcg_gen_extrl_i64_i32(d32, d64);
cb21b4da 1936 gen_store_fpr_F(dc, rd, d32);
f2fe396f 1937 break;
3259b9e2
RH
1938 case MO_64:
1939 gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr,
1940 r_asi, r_mop);
f2fe396f 1941 break;
3259b9e2 1942 case MO_128:
cb21b4da 1943 d64 = tcg_temp_new_i64();
ad75a51e 1944 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
287b1152
RH
1945 addr_tmp = tcg_temp_new();
1946 tcg_gen_addi_tl(addr_tmp, addr, 8);
1947 gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp,
3259b9e2 1948 r_asi, r_mop);
cb21b4da 1949 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
f2fe396f
RH
1950 break;
1951 default:
1952 g_assert_not_reached();
1953 }
7ec1e5ea
RH
1954 }
1955 break;
1956 }
1a2fb1c0
BS
1957}
1958
287b1152
RH
1959static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
1960 TCGv addr, int rd)
3259b9e2
RH
1961{
1962 MemOp memop = da->memop;
1963 MemOp size = memop & MO_SIZE;
7705091c 1964 TCGv_i32 d32;
287b1152 1965 TCGv addr_tmp;
1a2fb1c0 1966
3259b9e2
RH
1967 /* TODO: Use 128-bit load/store below. */
1968 if (size == MO_128) {
1969 memop = (memop & ~MO_SIZE) | MO_64;
1970 }
1971
1972 switch (da->type) {
7ec1e5ea
RH
1973 case GET_ASI_EXCP:
1974 break;
7705091c
RH
1975
1976 case GET_ASI_DIRECT:
3259b9e2 1977 memop |= MO_ALIGN_4;
7705091c 1978 switch (size) {
3259b9e2 1979 case MO_32:
7705091c 1980 d32 = gen_load_fpr_F(dc, rd);
3259b9e2 1981 tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
7705091c 1982 break;
3259b9e2
RH
1983 case MO_64:
1984 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1985 memop | MO_ALIGN_4);
7705091c 1986 break;
3259b9e2 1987 case MO_128:
cb21b4da
RH
1988 /* Only 4-byte alignment required. However, it is legal for the
1989 cpu to signal the alignment fault, and the OS trap handler is
1990 required to fix it up. Requiring 16-byte alignment here avoids
1991 having to probe the second page before performing the first
1992 write. */
3259b9e2
RH
1993 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
1994 memop | MO_ALIGN_16);
287b1152
RH
1995 addr_tmp = tcg_temp_new();
1996 tcg_gen_addi_tl(addr_tmp, addr, 8);
1997 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
7705091c
RH
1998 break;
1999 default:
2000 g_assert_not_reached();
2001 }
2002 break;
2003
ca5ce572
RH
2004 case GET_ASI_BLOCK:
2005 /* Valid for stdfa on aligned registers only. */
3259b9e2 2006 if (orig_size == MO_64 && (rd & 7) == 0) {
80883227 2007 /* The first operation checks required alignment. */
287b1152
RH
2008 addr_tmp = tcg_temp_new();
2009 for (int i = 0; ; ++i) {
3259b9e2
RH
2010 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
2011 memop | (i == 0 ? MO_ALIGN_64 : 0));
ca5ce572
RH
2012 if (i == 7) {
2013 break;
2014 }
287b1152
RH
2015 tcg_gen_addi_tl(addr_tmp, addr, 8);
2016 addr = addr_tmp;
ca5ce572 2017 }
ca5ce572
RH
2018 } else {
2019 gen_exception(dc, TT_ILL_INSN);
2020 }
2021 break;
2022
2023 case GET_ASI_SHORT:
2024 /* Valid for stdfa only. */
3259b9e2
RH
2025 if (orig_size == MO_64) {
2026 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
2027 memop | MO_ALIGN);
ca5ce572
RH
2028 } else {
2029 gen_exception(dc, TT_ILL_INSN);
2030 }
2031 break;
2032
7ec1e5ea 2033 default:
f2fe396f
RH
2034 /* According to the table in the UA2011 manual, the only
2035 other asis that are valid for ldfa/lddfa/ldqfa are
2036 the PST* asis, which aren't currently handled. */
2037 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
2038 break;
2039 }
1a2fb1c0
BS
2040}
2041
42071fc1 2042static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1a2fb1c0 2043{
a76779ee
RH
2044 TCGv hi = gen_dest_gpr(dc, rd);
2045 TCGv lo = gen_dest_gpr(dc, rd + 1);
1a2fb1c0 2046
c03a0fd1 2047 switch (da->type) {
7ec1e5ea 2048 case GET_ASI_EXCP:
e4dc0052
RH
2049 return;
2050
2051 case GET_ASI_DTWINX:
ebbbec92
RH
2052#ifdef TARGET_SPARC64
2053 {
2054 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2055 TCGv_i128 t = tcg_temp_new_i128();
2056
2057 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
2058 /*
2059 * Note that LE twinx acts as if each 64-bit register result is
2060 * byte swapped. We perform one 128-bit LE load, so must swap
2061 * the order of the writebacks.
2062 */
2063 if ((mop & MO_BSWAP) == MO_TE) {
2064 tcg_gen_extr_i128_i64(lo, hi, t);
2065 } else {
2066 tcg_gen_extr_i128_i64(hi, lo, t);
2067 }
2068 }
7ec1e5ea 2069 break;
ebbbec92
RH
2070#else
2071 g_assert_not_reached();
2072#endif
e4dc0052
RH
2073
2074 case GET_ASI_DIRECT:
2075 {
2076 TCGv_i64 tmp = tcg_temp_new_i64();
2077
c03a0fd1 2078 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
e4dc0052
RH
2079
2080 /* Note that LE ldda acts as if each 32-bit register
2081 result is byte swapped. Having just performed one
2082 64-bit bswap, we need now to swap the writebacks. */
c03a0fd1 2083 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2084 tcg_gen_extr_i64_tl(lo, hi, tmp);
e4dc0052 2085 } else {
a76779ee 2086 tcg_gen_extr_i64_tl(hi, lo, tmp);
e4dc0052 2087 }
e4dc0052
RH
2088 }
2089 break;
2090
7ec1e5ea 2091 default:
918d9a2c
RH
2092 /* ??? In theory we've handled all of the ASIs that are valid
2093 for ldda, and this should raise DAE_invalid_asi. However,
2094 real hardware allows others. This can be seen with e.g.
2095 FreeBSD 10.3 wrt ASI_IC_TAG. */
7ec1e5ea 2096 {
c03a0fd1
RH
2097 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2098 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
918d9a2c 2099 TCGv_i64 tmp = tcg_temp_new_i64();
7ec1e5ea
RH
2100
2101 save_state(dc);
ad75a51e 2102 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
3f4288eb 2103
918d9a2c 2104 /* See above. */
c03a0fd1 2105 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2106 tcg_gen_extr_i64_tl(lo, hi, tmp);
918d9a2c 2107 } else {
a76779ee 2108 tcg_gen_extr_i64_tl(hi, lo, tmp);
918d9a2c 2109 }
7ec1e5ea
RH
2110 }
2111 break;
2112 }
e4dc0052
RH
2113
2114 gen_store_gpr(dc, rd, hi);
2115 gen_store_gpr(dc, rd + 1, lo);
0425bee5
BS
2116}
2117
42071fc1 2118static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
c03a0fd1
RH
2119{
2120 TCGv hi = gen_load_gpr(dc, rd);
c7785e16 2121 TCGv lo = gen_load_gpr(dc, rd + 1);
a7ec4229 2122
c03a0fd1 2123 switch (da->type) {
7ec1e5ea
RH
2124 case GET_ASI_EXCP:
2125 break;
e4dc0052
RH
2126
2127 case GET_ASI_DTWINX:
ebbbec92
RH
2128#ifdef TARGET_SPARC64
2129 {
2130 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2131 TCGv_i128 t = tcg_temp_new_i128();
2132
2133 /*
2134 * Note that LE twinx acts as if each 64-bit register result is
2135 * byte swapped. We perform one 128-bit LE store, so must swap
2136 * the order of the construction.
2137 */
2138 if ((mop & MO_BSWAP) == MO_TE) {
2139 tcg_gen_concat_i64_i128(t, lo, hi);
2140 } else {
2141 tcg_gen_concat_i64_i128(t, hi, lo);
2142 }
2143 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
2144 }
e4dc0052 2145 break;
ebbbec92
RH
2146#else
2147 g_assert_not_reached();
2148#endif
e4dc0052
RH
2149
2150 case GET_ASI_DIRECT:
2151 {
2152 TCGv_i64 t64 = tcg_temp_new_i64();
2153
2154 /* Note that LE stda acts as if each 32-bit register result is
2155 byte swapped. We will perform one 64-bit LE store, so now
2156 we must swap the order of the construction. */
c03a0fd1 2157 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2158 tcg_gen_concat_tl_i64(t64, lo, hi);
e4dc0052 2159 } else {
a76779ee 2160 tcg_gen_concat_tl_i64(t64, hi, lo);
e4dc0052 2161 }
c03a0fd1 2162 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
e4dc0052
RH
2163 }
2164 break;
2165
a76779ee
RH
2166 case GET_ASI_BFILL:
2167 assert(TARGET_LONG_BITS == 32);
2168 /* Store 32 bytes of T64 to ADDR. */
2169 /* ??? The original qemu code suggests 8-byte alignment, dropping
2170 the low bits, but the only place I can see this used is in the
2171 Linux kernel with 32 byte alignment, which would make more sense
2172 as a cacheline-style operation. */
2173 {
2174 TCGv_i64 t64 = tcg_temp_new_i64();
2175 TCGv d_addr = tcg_temp_new();
2176 TCGv eight = tcg_constant_tl(8);
2177 int i;
2178
2179 tcg_gen_concat_tl_i64(t64, lo, hi);
2180 tcg_gen_andi_tl(d_addr, addr, -8);
2181 for (i = 0; i < 32; i += 8) {
c03a0fd1 2182 tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop);
a76779ee
RH
2183 tcg_gen_add_tl(d_addr, d_addr, eight);
2184 }
2185 }
2186 break;
2187
7ec1e5ea 2188 default:
918d9a2c
RH
2189 /* ??? In theory we've handled all of the ASIs that are valid
2190 for stda, and this should raise DAE_invalid_asi. */
7ec1e5ea 2191 {
c03a0fd1
RH
2192 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2193 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
918d9a2c 2194 TCGv_i64 t64 = tcg_temp_new_i64();
7ec1e5ea 2195
918d9a2c 2196 /* See above. */
c03a0fd1 2197 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2198 tcg_gen_concat_tl_i64(t64, lo, hi);
918d9a2c 2199 } else {
a76779ee 2200 tcg_gen_concat_tl_i64(t64, hi, lo);
918d9a2c 2201 }
7ec1e5ea 2202
918d9a2c 2203 save_state(dc);
ad75a51e 2204 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
7ec1e5ea
RH
2205 }
2206 break;
2207 }
1a2fb1c0
BS
2208}
2209
7e480893
RH
2210static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2211{
f7ec8155 2212#ifdef TARGET_SPARC64
7e480893 2213 TCGv_i32 c32, zero, dst, s1, s2;
dd7dbfcc 2214 TCGv_i64 c64 = tcg_temp_new_i64();
7e480893
RH
2215
2216 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2217 or fold the comparison down to 32 bits and use movcond_i32. Choose
2218 the later. */
2219 c32 = tcg_temp_new_i32();
c8507ebf 2220 tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
dd7dbfcc 2221 tcg_gen_extrl_i64_i32(c32, c64);
7e480893
RH
2222
2223 s1 = gen_load_fpr_F(dc, rs);
2224 s2 = gen_load_fpr_F(dc, rd);
ba5f5179 2225 dst = gen_dest_fpr_F(dc);
00ab7e61 2226 zero = tcg_constant_i32(0);
7e480893
RH
2227
2228 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2229
7e480893 2230 gen_store_fpr_F(dc, rd, dst);
f7ec8155
RH
2231#else
2232 qemu_build_not_reached();
2233#endif
7e480893
RH
2234}
2235
2236static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2237{
f7ec8155 2238#ifdef TARGET_SPARC64
3886b8a3 2239 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
c8507ebf 2240 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
7e480893
RH
2241 gen_load_fpr_D(dc, rs),
2242 gen_load_fpr_D(dc, rd));
2243 gen_store_fpr_D(dc, rd, dst);
f7ec8155
RH
2244#else
2245 qemu_build_not_reached();
2246#endif
7e480893
RH
2247}
2248
2249static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2250{
f7ec8155 2251#ifdef TARGET_SPARC64
7e480893
RH
2252 int qd = QFPREG(rd);
2253 int qs = QFPREG(rs);
c8507ebf 2254 TCGv c2 = tcg_constant_tl(cmp->c2);
7e480893 2255
c8507ebf 2256 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, c2,
7e480893 2257 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
c8507ebf 2258 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, c2,
7e480893
RH
2259 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2260
f9c816c0 2261 gen_update_fprs_dirty(dc, qd);
f7ec8155
RH
2262#else
2263 qemu_build_not_reached();
2264#endif
7e480893
RH
2265}
2266
f7ec8155 2267#ifdef TARGET_SPARC64
5d617bfb 2268static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
8194f35a 2269{
b551ec04 2270 TCGv_i32 r_tl = tcg_temp_new_i32();
8194f35a
IK
2271
2272 /* load env->tl into r_tl */
ad75a51e 2273 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
8194f35a
IK
2274
2275 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
b551ec04 2276 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
8194f35a
IK
2277
2278 /* calculate offset to current trap state from env->ts, reuse r_tl */
b551ec04 2279 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
ad75a51e 2280 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
8194f35a
IK
2281
2282 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
b551ec04
JF
2283 {
2284 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2285 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2286 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
b551ec04 2287 }
8194f35a
IK
2288}
2289#endif
2290
06c060d9
RH
2291static int extract_dfpreg(DisasContext *dc, int x)
2292{
2293 return DFPREG(x);
2294}
2295
2296static int extract_qfpreg(DisasContext *dc, int x)
2297{
2298 return QFPREG(x);
2299}
2300
878cc677
RH
2301/* Include the auto-generated decoder. */
2302#include "decode-insns.c.inc"
2303
2304#define TRANS(NAME, AVAIL, FUNC, ...) \
2305 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2306 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2307
2308#define avail_ALL(C) true
2309#ifdef TARGET_SPARC64
2310# define avail_32(C) false
af25071c 2311# define avail_ASR17(C) false
d0a11d25 2312# define avail_CASA(C) true
c2636853 2313# define avail_DIV(C) true
b5372650 2314# define avail_MUL(C) true
0faef01b 2315# define avail_POWERDOWN(C) false
878cc677 2316# define avail_64(C) true
5d617bfb 2317# define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
af25071c 2318# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
b88ce6f2
RH
2319# define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1)
2320# define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2)
878cc677
RH
2321#else
2322# define avail_32(C) true
af25071c 2323# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
d0a11d25 2324# define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA)
c2636853 2325# define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV)
b5372650 2326# define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL)
0faef01b 2327# define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
878cc677 2328# define avail_64(C) false
5d617bfb 2329# define avail_GL(C) false
af25071c 2330# define avail_HYPV(C) false
b88ce6f2
RH
2331# define avail_VIS1(C) false
2332# define avail_VIS2(C) false
878cc677
RH
2333#endif
2334
2335/* Default case for non jump instructions. */
2336static bool advance_pc(DisasContext *dc)
2337{
4a8d145d
RH
2338 TCGLabel *l1;
2339
89527e3a
RH
2340 finishing_insn(dc);
2341
878cc677
RH
2342 if (dc->npc & 3) {
2343 switch (dc->npc) {
2344 case DYNAMIC_PC:
2345 case DYNAMIC_PC_LOOKUP:
2346 dc->pc = dc->npc;
444d8b30
RH
2347 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2348 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
878cc677 2349 break;
4a8d145d 2350
878cc677
RH
2351 case JUMP_PC:
2352 /* we can do a static jump */
4a8d145d 2353 l1 = gen_new_label();
533f042f 2354 tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
4a8d145d
RH
2355
2356 /* jump not taken */
2357 gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
2358
2359 /* jump taken */
2360 gen_set_label(l1);
2361 gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
2362
878cc677
RH
2363 dc->base.is_jmp = DISAS_NORETURN;
2364 break;
4a8d145d 2365
878cc677
RH
2366 default:
2367 g_assert_not_reached();
2368 }
2369 } else {
2370 dc->pc = dc->npc;
2371 dc->npc = dc->npc + 4;
2372 }
2373 return true;
2374}
2375
6d2a0768
RH
2376/*
2377 * Major opcodes 00 and 01 -- branches, call, and sethi
2378 */
2379
9d4e2bc7 2380static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
3951b7a8 2381 bool annul, int disp)
276567aa 2382{
3951b7a8 2383 target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
c76c8045
RH
2384 target_ulong npc;
2385
89527e3a
RH
2386 finishing_insn(dc);
2387
2d9bb237
RH
2388 if (cmp->cond == TCG_COND_ALWAYS) {
2389 if (annul) {
2390 dc->pc = dest;
2391 dc->npc = dest + 4;
2392 } else {
2393 gen_mov_pc_npc(dc);
2394 dc->npc = dest;
2395 }
2396 return true;
2397 }
2398
2399 if (cmp->cond == TCG_COND_NEVER) {
2400 npc = dc->npc;
2401 if (npc & 3) {
2402 gen_mov_pc_npc(dc);
2403 if (annul) {
2404 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
2405 }
2406 tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
2407 } else {
2408 dc->pc = npc + (annul ? 4 : 0);
2409 dc->npc = dc->pc + 4;
2410 }
2411 return true;
2412 }
2413
c76c8045
RH
2414 flush_cond(dc);
2415 npc = dc->npc;
6b3e4cc6 2416
276567aa 2417 if (annul) {
6b3e4cc6
RH
2418 TCGLabel *l1 = gen_new_label();
2419
c8507ebf 2420 tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
6b3e4cc6
RH
2421 gen_goto_tb(dc, 0, npc, dest);
2422 gen_set_label(l1);
2423 gen_goto_tb(dc, 1, npc + 4, npc + 8);
2424
2425 dc->base.is_jmp = DISAS_NORETURN;
276567aa 2426 } else {
6b3e4cc6
RH
2427 if (npc & 3) {
2428 switch (npc) {
2429 case DYNAMIC_PC:
2430 case DYNAMIC_PC_LOOKUP:
2431 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2432 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
9d4e2bc7 2433 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
c8507ebf 2434 cmp->c1, tcg_constant_tl(cmp->c2),
6b3e4cc6
RH
2435 tcg_constant_tl(dest), cpu_npc);
2436 dc->pc = npc;
2437 break;
2438 default:
2439 g_assert_not_reached();
2440 }
2441 } else {
2442 dc->pc = npc;
533f042f
RH
2443 dc->npc = JUMP_PC;
2444 dc->jump = *cmp;
6b3e4cc6
RH
2445 dc->jump_pc[0] = dest;
2446 dc->jump_pc[1] = npc + 4;
dd7dbfcc
RH
2447
2448 /* The condition for cpu_cond is always NE -- normalize. */
2449 if (cmp->cond == TCG_COND_NE) {
c8507ebf 2450 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
9d4e2bc7 2451 } else {
c8507ebf 2452 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
9d4e2bc7 2453 }
89527e3a 2454 dc->cpu_cond_live = true;
6b3e4cc6 2455 }
276567aa
RH
2456 }
2457 return true;
2458}
2459
af25071c
RH
2460static bool raise_priv(DisasContext *dc)
2461{
2462 gen_exception(dc, TT_PRIV_INSN);
2463 return true;
2464}
2465
06c060d9
RH
2466static bool raise_unimpfpop(DisasContext *dc)
2467{
2468 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
2469 return true;
2470}
2471
2472static bool gen_trap_float128(DisasContext *dc)
2473{
2474 if (dc->def->features & CPU_FEATURE_FLOAT128) {
2475 return false;
2476 }
2477 return raise_unimpfpop(dc);
2478}
2479
276567aa
RH
2480static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2481{
1ea9c62a 2482 DisasCompare cmp;
276567aa 2483
2d9bb237 2484 gen_compare(&cmp, a->cc, a->cond, dc);
3951b7a8 2485 return advance_jump_cond(dc, &cmp, a->a, a->i);
276567aa
RH
2486}
2487
2488TRANS(Bicc, ALL, do_bpcc, a)
2489TRANS(BPcc, 64, do_bpcc, a)
2490
45196ea4
RH
2491static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
2492{
d5471936 2493 DisasCompare cmp;
45196ea4
RH
2494
2495 if (gen_trap_ifnofpu(dc)) {
2496 return true;
2497 }
2d9bb237 2498 gen_fcompare(&cmp, a->cc, a->cond);
3951b7a8 2499 return advance_jump_cond(dc, &cmp, a->a, a->i);
45196ea4
RH
2500}
2501
2502TRANS(FBPfcc, 64, do_fbpfcc, a)
2503TRANS(FBfcc, ALL, do_fbpfcc, a)
2504
ab9ffe98
RH
2505static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2506{
ab9ffe98
RH
2507 DisasCompare cmp;
2508
2509 if (!avail_64(dc)) {
2510 return false;
2511 }
2c4f56c9 2512 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
ab9ffe98
RH
2513 return false;
2514 }
3951b7a8 2515 return advance_jump_cond(dc, &cmp, a->a, a->i);
ab9ffe98
RH
2516}
2517
23ada1b1
RH
2518static bool trans_CALL(DisasContext *dc, arg_CALL *a)
2519{
2520 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
2521
2522 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
2523 gen_mov_pc_npc(dc);
2524 dc->npc = target;
2525 return true;
2526}
2527
45196ea4
RH
2528static bool trans_NCP(DisasContext *dc, arg_NCP *a)
2529{
2530 /*
2531 * For sparc32, always generate the no-coprocessor exception.
2532 * For sparc64, always generate illegal instruction.
2533 */
2534#ifdef TARGET_SPARC64
2535 return false;
2536#else
2537 gen_exception(dc, TT_NCP_INSN);
2538 return true;
2539#endif
2540}
2541
6d2a0768
RH
2542static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
2543{
2544 /* Special-case %g0 because that's the canonical nop. */
2545 if (a->rd) {
2546 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
2547 }
2548 return advance_pc(dc);
2549}
2550
0faef01b
RH
2551/*
2552 * Major Opcode 10 -- integer, floating-point, vis, and system insns.
2553 */
2554
30376636
RH
2555static bool do_tcc(DisasContext *dc, int cond, int cc,
2556 int rs1, bool imm, int rs2_or_imm)
2557{
2558 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
2559 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
2560 DisasCompare cmp;
2561 TCGLabel *lab;
2562 TCGv_i32 trap;
2563
2564 /* Trap never. */
2565 if (cond == 0) {
2566 return advance_pc(dc);
2567 }
2568
2569 /*
2570 * Immediate traps are the most common case. Since this value is
2571 * live across the branch, it really pays to evaluate the constant.
2572 */
2573 if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
2574 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
2575 } else {
2576 trap = tcg_temp_new_i32();
2577 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
2578 if (imm) {
2579 tcg_gen_addi_i32(trap, trap, rs2_or_imm);
2580 } else {
2581 TCGv_i32 t2 = tcg_temp_new_i32();
2582 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
2583 tcg_gen_add_i32(trap, trap, t2);
2584 }
2585 tcg_gen_andi_i32(trap, trap, mask);
2586 tcg_gen_addi_i32(trap, trap, TT_TRAP);
2587 }
2588
89527e3a
RH
2589 finishing_insn(dc);
2590
30376636
RH
2591 /* Trap always. */
2592 if (cond == 8) {
2593 save_state(dc);
2594 gen_helper_raise_exception(tcg_env, trap);
2595 dc->base.is_jmp = DISAS_NORETURN;
2596 return true;
2597 }
2598
2599 /* Conditional trap. */
2600 flush_cond(dc);
2601 lab = delay_exceptionv(dc, trap);
2602 gen_compare(&cmp, cc, cond, dc);
c8507ebf 2603 tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
30376636
RH
2604
2605 return advance_pc(dc);
2606}
2607
2608static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
2609{
2610 if (avail_32(dc) && a->cc) {
2611 return false;
2612 }
2613 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
2614}
2615
2616static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
2617{
2618 if (avail_64(dc)) {
2619 return false;
2620 }
2621 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
2622}
2623
2624static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
2625{
2626 if (avail_32(dc)) {
2627 return false;
2628 }
2629 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
2630}
2631
af25071c
RH
2632static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2633{
2634 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2635 return advance_pc(dc);
2636}
2637
2638static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2639{
2640 if (avail_32(dc)) {
2641 return false;
2642 }
2643 if (a->mmask) {
2644 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2645 tcg_gen_mb(a->mmask | TCG_BAR_SC);
2646 }
2647 if (a->cmask) {
2648 /* For #Sync, etc, end the TB to recognize interrupts. */
2649 dc->base.is_jmp = DISAS_EXIT;
2650 }
2651 return advance_pc(dc);
2652}
2653
2654static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2655 TCGv (*func)(DisasContext *, TCGv))
2656{
2657 if (!priv) {
2658 return raise_priv(dc);
2659 }
2660 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2661 return advance_pc(dc);
2662}
2663
2664static TCGv do_rdy(DisasContext *dc, TCGv dst)
2665{
2666 return cpu_y;
2667}
2668
2669static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2670{
2671 /*
2672 * TODO: Need a feature bit for sparcv8. In the meantime, treat all
2673 * 32-bit cpus like sparcv7, which ignores the rs1 field.
2674 * This matches after all other ASR, so Leon3 Asr17 is handled first.
2675 */
2676 if (avail_64(dc) && a->rs1 != 0) {
2677 return false;
2678 }
2679 return do_rd_special(dc, true, a->rd, do_rdy);
2680}
2681
2682static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2683{
2684 uint32_t val;
2685
2686 /*
2687 * TODO: There are many more fields to be filled,
2688 * some of which are writable.
2689 */
2690 val = dc->def->nwindows - 1; /* [4:0] NWIN */
2691 val |= 1 << 8; /* [8] V8 */
2692
2693 return tcg_constant_tl(val);
2694}
2695
2696TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2697
2698static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2699{
af25071c
RH
2700 gen_helper_rdccr(dst, tcg_env);
2701 return dst;
2702}
2703
2704TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2705
2706static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2707{
2708#ifdef TARGET_SPARC64
2709 return tcg_constant_tl(dc->asi);
2710#else
2711 qemu_build_not_reached();
2712#endif
2713}
2714
2715TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2716
2717static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2718{
2719 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2720
2721 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2722 if (translator_io_start(&dc->base)) {
2723 dc->base.is_jmp = DISAS_EXIT;
2724 }
2725 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2726 tcg_constant_i32(dc->mem_idx));
2727 return dst;
2728}
2729
2730/* TODO: non-priv access only allowed when enabled. */
2731TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2732
2733static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2734{
2735 return tcg_constant_tl(address_mask_i(dc, dc->pc));
2736}
2737
2738TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2739
2740static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2741{
2742 tcg_gen_ext_i32_tl(dst, cpu_fprs);
2743 return dst;
2744}
2745
2746TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2747
2748static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2749{
2750 gen_trap_ifnofpu(dc);
2751 return cpu_gsr;
2752}
2753
2754TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2755
2756static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2757{
2758 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2759 return dst;
2760}
2761
2762TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2763
2764static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2765{
577efa45
RH
2766 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2767 return dst;
af25071c
RH
2768}
2769
2770/* TODO: non-priv access only allowed when enabled. */
2771TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2772
2773static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2774{
2775 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2776
2777 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2778 if (translator_io_start(&dc->base)) {
2779 dc->base.is_jmp = DISAS_EXIT;
2780 }
2781 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2782 tcg_constant_i32(dc->mem_idx));
2783 return dst;
2784}
2785
2786/* TODO: non-priv access only allowed when enabled. */
2787TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2788
2789static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2790{
577efa45
RH
2791 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2792 return dst;
af25071c
RH
2793}
2794
2795/* TODO: supervisor access only allowed when enabled by hypervisor. */
2796TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2797
2798/*
2799 * UltraSPARC-T1 Strand status.
2800 * HYPV check maybe not enough, UA2005 & UA2007 describe
2801 * this ASR as impl. dep
2802 */
2803static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2804{
2805 return tcg_constant_tl(1);
2806}
2807
2808TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2809
668bb9b7
RH
2810static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2811{
668bb9b7
RH
2812 gen_helper_rdpsr(dst, tcg_env);
2813 return dst;
2814}
2815
2816TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2817
2818static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2819{
2820 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2821 return dst;
2822}
2823
2824TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2825
2826static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2827{
2828 TCGv_i32 tl = tcg_temp_new_i32();
2829 TCGv_ptr tp = tcg_temp_new_ptr();
2830
2831 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2832 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2833 tcg_gen_shli_i32(tl, tl, 3);
2834 tcg_gen_ext_i32_ptr(tp, tl);
2835 tcg_gen_add_ptr(tp, tp, tcg_env);
2836
2837 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2838 return dst;
2839}
2840
2841TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2842
2843static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2844{
2da789de
RH
2845 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
2846 return dst;
668bb9b7
RH
2847}
2848
2849TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2850
2851static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2852{
2da789de
RH
2853 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
2854 return dst;
668bb9b7
RH
2855}
2856
2857TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
2858
2859static TCGv do_rdhver(DisasContext *dc, TCGv dst)
2860{
2da789de
RH
2861 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
2862 return dst;
668bb9b7
RH
2863}
2864
2865TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
2866
2867static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
2868{
577efa45
RH
2869 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
2870 return dst;
668bb9b7
RH
2871}
2872
2873TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
2874 do_rdhstick_cmpr)
2875
5d617bfb
RH
2876static TCGv do_rdwim(DisasContext *dc, TCGv dst)
2877{
cd6269f7
RH
2878 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
2879 return dst;
5d617bfb
RH
2880}
2881
2882TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
2883
2884static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
2885{
2886#ifdef TARGET_SPARC64
2887 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2888
2889 gen_load_trap_state_at_tl(r_tsptr);
2890 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
2891 return dst;
2892#else
2893 qemu_build_not_reached();
2894#endif
2895}
2896
2897TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
2898
2899static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
2900{
2901#ifdef TARGET_SPARC64
2902 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2903
2904 gen_load_trap_state_at_tl(r_tsptr);
2905 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
2906 return dst;
2907#else
2908 qemu_build_not_reached();
2909#endif
2910}
2911
2912TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
2913
2914static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
2915{
2916#ifdef TARGET_SPARC64
2917 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2918
2919 gen_load_trap_state_at_tl(r_tsptr);
2920 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
2921 return dst;
2922#else
2923 qemu_build_not_reached();
2924#endif
2925}
2926
2927TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
2928
2929static TCGv do_rdtt(DisasContext *dc, TCGv dst)
2930{
2931#ifdef TARGET_SPARC64
2932 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
2933
2934 gen_load_trap_state_at_tl(r_tsptr);
2935 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
2936 return dst;
2937#else
2938 qemu_build_not_reached();
2939#endif
2940}
2941
2942TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
2943TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
2944
2945static TCGv do_rdtba(DisasContext *dc, TCGv dst)
2946{
2947 return cpu_tbr;
2948}
2949
e8325dc0 2950TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
5d617bfb
RH
2951TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
2952
2953static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
2954{
2955 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
2956 return dst;
2957}
2958
2959TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
2960
2961static TCGv do_rdtl(DisasContext *dc, TCGv dst)
2962{
2963 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
2964 return dst;
2965}
2966
2967TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
2968
2969static TCGv do_rdpil(DisasContext *dc, TCGv dst)
2970{
2971 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
2972 return dst;
2973}
2974
2975TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
2976
2977static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
2978{
2979 gen_helper_rdcwp(dst, tcg_env);
2980 return dst;
2981}
2982
2983TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
2984
2985static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
2986{
2987 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
2988 return dst;
2989}
2990
2991TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
2992
2993static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
2994{
2995 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
2996 return dst;
2997}
2998
2999TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
3000 do_rdcanrestore)
3001
3002static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
3003{
3004 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
3005 return dst;
3006}
3007
3008TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
3009
3010static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
3011{
3012 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
3013 return dst;
3014}
3015
3016TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
3017
3018static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
3019{
3020 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
3021 return dst;
3022}
3023
3024TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
3025
3026static TCGv do_rdgl(DisasContext *dc, TCGv dst)
3027{
3028 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
3029 return dst;
3030}
3031
3032TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
3033
3034/* UA2005 strand status */
3035static TCGv do_rdssr(DisasContext *dc, TCGv dst)
3036{
2da789de
RH
3037 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
3038 return dst;
5d617bfb
RH
3039}
3040
3041TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
3042
3043static TCGv do_rdver(DisasContext *dc, TCGv dst)
3044{
2da789de
RH
3045 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
3046 return dst;
5d617bfb
RH
3047}
3048
3049TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
3050
e8325dc0
RH
3051static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
3052{
3053 if (avail_64(dc)) {
3054 gen_helper_flushw(tcg_env);
3055 return advance_pc(dc);
3056 }
3057 return false;
3058}
3059
0faef01b
RH
3060static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
3061 void (*func)(DisasContext *, TCGv))
3062{
3063 TCGv src;
3064
3065 /* For simplicity, we under-decoded the rs2 form. */
3066 if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
3067 return false;
3068 }
3069 if (!priv) {
3070 return raise_priv(dc);
3071 }
3072
3073 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
3074 src = tcg_constant_tl(a->rs2_or_imm);
3075 } else {
3076 TCGv src1 = gen_load_gpr(dc, a->rs1);
3077 if (a->rs2_or_imm == 0) {
3078 src = src1;
3079 } else {
3080 src = tcg_temp_new();
3081 if (a->imm) {
3082 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
3083 } else {
3084 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
3085 }
3086 }
3087 }
3088 func(dc, src);
3089 return advance_pc(dc);
3090}
3091
3092static void do_wry(DisasContext *dc, TCGv src)
3093{
3094 tcg_gen_ext32u_tl(cpu_y, src);
3095}
3096
3097TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
3098
3099static void do_wrccr(DisasContext *dc, TCGv src)
3100{
3101 gen_helper_wrccr(tcg_env, src);
3102}
3103
3104TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
3105
3106static void do_wrasi(DisasContext *dc, TCGv src)
3107{
3108 TCGv tmp = tcg_temp_new();
3109
3110 tcg_gen_ext8u_tl(tmp, src);
3111 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
3112 /* End TB to notice changed ASI. */
3113 dc->base.is_jmp = DISAS_EXIT;
3114}
3115
3116TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
3117
3118static void do_wrfprs(DisasContext *dc, TCGv src)
3119{
3120#ifdef TARGET_SPARC64
3121 tcg_gen_trunc_tl_i32(cpu_fprs, src);
3122 dc->fprs_dirty = 0;
3123 dc->base.is_jmp = DISAS_EXIT;
3124#else
3125 qemu_build_not_reached();
3126#endif
3127}
3128
3129TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
3130
3131static void do_wrgsr(DisasContext *dc, TCGv src)
3132{
3133 gen_trap_ifnofpu(dc);
3134 tcg_gen_mov_tl(cpu_gsr, src);
3135}
3136
3137TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
3138
3139static void do_wrsoftint_set(DisasContext *dc, TCGv src)
3140{
3141 gen_helper_set_softint(tcg_env, src);
3142}
3143
3144TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
3145
3146static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
3147{
3148 gen_helper_clear_softint(tcg_env, src);
3149}
3150
3151TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
3152
3153static void do_wrsoftint(DisasContext *dc, TCGv src)
3154{
3155 gen_helper_write_softint(tcg_env, src);
3156}
3157
3158TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
3159
3160static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
3161{
0faef01b
RH
3162 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3163
577efa45
RH
3164 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
3165 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
0faef01b 3166 translator_io_start(&dc->base);
577efa45 3167 gen_helper_tick_set_limit(r_tickptr, src);
0faef01b
RH
3168 /* End TB to handle timer interrupt */
3169 dc->base.is_jmp = DISAS_EXIT;
0faef01b
RH
3170}
3171
3172TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
3173
3174static void do_wrstick(DisasContext *dc, TCGv src)
3175{
3176#ifdef TARGET_SPARC64
3177 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3178
3179 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3180 translator_io_start(&dc->base);
3181 gen_helper_tick_set_count(r_tickptr, src);
3182 /* End TB to handle timer interrupt */
3183 dc->base.is_jmp = DISAS_EXIT;
3184#else
3185 qemu_build_not_reached();
3186#endif
3187}
3188
3189TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
3190
3191static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
3192{
0faef01b
RH
3193 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3194
577efa45
RH
3195 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3196 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
0faef01b 3197 translator_io_start(&dc->base);
577efa45 3198 gen_helper_tick_set_limit(r_tickptr, src);
0faef01b
RH
3199 /* End TB to handle timer interrupt */
3200 dc->base.is_jmp = DISAS_EXIT;
0faef01b
RH
3201}
3202
3203TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
3204
3205static void do_wrpowerdown(DisasContext *dc, TCGv src)
3206{
89527e3a 3207 finishing_insn(dc);
0faef01b
RH
3208 save_state(dc);
3209 gen_helper_power_down(tcg_env);
3210}
3211
3212TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
3213
25524734
RH
3214static void do_wrpsr(DisasContext *dc, TCGv src)
3215{
3216 gen_helper_wrpsr(tcg_env, src);
25524734
RH
3217 dc->base.is_jmp = DISAS_EXIT;
3218}
3219
3220TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
3221
9422278e
RH
3222static void do_wrwim(DisasContext *dc, TCGv src)
3223{
3224 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
cd6269f7
RH
3225 TCGv tmp = tcg_temp_new();
3226
3227 tcg_gen_andi_tl(tmp, src, mask);
3228 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
9422278e
RH
3229}
3230
3231TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
3232
3233static void do_wrtpc(DisasContext *dc, TCGv src)
3234{
3235#ifdef TARGET_SPARC64
3236 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3237
3238 gen_load_trap_state_at_tl(r_tsptr);
3239 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
3240#else
3241 qemu_build_not_reached();
3242#endif
3243}
3244
3245TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
3246
3247static void do_wrtnpc(DisasContext *dc, TCGv src)
3248{
3249#ifdef TARGET_SPARC64
3250 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3251
3252 gen_load_trap_state_at_tl(r_tsptr);
3253 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
3254#else
3255 qemu_build_not_reached();
3256#endif
3257}
3258
3259TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
3260
3261static void do_wrtstate(DisasContext *dc, TCGv src)
3262{
3263#ifdef TARGET_SPARC64
3264 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3265
3266 gen_load_trap_state_at_tl(r_tsptr);
3267 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
3268#else
3269 qemu_build_not_reached();
3270#endif
3271}
3272
3273TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
3274
3275static void do_wrtt(DisasContext *dc, TCGv src)
3276{
3277#ifdef TARGET_SPARC64
3278 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3279
3280 gen_load_trap_state_at_tl(r_tsptr);
3281 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
3282#else
3283 qemu_build_not_reached();
3284#endif
3285}
3286
3287TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
3288
3289static void do_wrtick(DisasContext *dc, TCGv src)
3290{
3291 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3292
3293 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3294 translator_io_start(&dc->base);
3295 gen_helper_tick_set_count(r_tickptr, src);
3296 /* End TB to handle timer interrupt */
3297 dc->base.is_jmp = DISAS_EXIT;
3298}
3299
3300TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
3301
3302static void do_wrtba(DisasContext *dc, TCGv src)
3303{
3304 tcg_gen_mov_tl(cpu_tbr, src);
3305}
3306
3307TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
3308
3309static void do_wrpstate(DisasContext *dc, TCGv src)
3310{
3311 save_state(dc);
3312 if (translator_io_start(&dc->base)) {
3313 dc->base.is_jmp = DISAS_EXIT;
3314 }
3315 gen_helper_wrpstate(tcg_env, src);
3316 dc->npc = DYNAMIC_PC;
3317}
3318
3319TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
3320
3321static void do_wrtl(DisasContext *dc, TCGv src)
3322{
3323 save_state(dc);
3324 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
3325 dc->npc = DYNAMIC_PC;
3326}
3327
3328TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
3329
3330static void do_wrpil(DisasContext *dc, TCGv src)
3331{
3332 if (translator_io_start(&dc->base)) {
3333 dc->base.is_jmp = DISAS_EXIT;
3334 }
3335 gen_helper_wrpil(tcg_env, src);
3336}
3337
3338TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
3339
3340static void do_wrcwp(DisasContext *dc, TCGv src)
3341{
3342 gen_helper_wrcwp(tcg_env, src);
3343}
3344
3345TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
3346
3347static void do_wrcansave(DisasContext *dc, TCGv src)
3348{
3349 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
3350}
3351
3352TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
3353
3354static void do_wrcanrestore(DisasContext *dc, TCGv src)
3355{
3356 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
3357}
3358
3359TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
3360
3361static void do_wrcleanwin(DisasContext *dc, TCGv src)
3362{
3363 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
3364}
3365
3366TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
3367
3368static void do_wrotherwin(DisasContext *dc, TCGv src)
3369{
3370 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
3371}
3372
3373TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
3374
3375static void do_wrwstate(DisasContext *dc, TCGv src)
3376{
3377 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
3378}
3379
3380TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
3381
3382static void do_wrgl(DisasContext *dc, TCGv src)
3383{
3384 gen_helper_wrgl(tcg_env, src);
3385}
3386
3387TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
3388
3389/* UA2005 strand status */
3390static void do_wrssr(DisasContext *dc, TCGv src)
3391{
2da789de 3392 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
9422278e
RH
3393}
3394
3395TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
3396
bb97f2f5
RH
3397TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3398
3399static void do_wrhpstate(DisasContext *dc, TCGv src)
3400{
3401 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3402 dc->base.is_jmp = DISAS_EXIT;
3403}
3404
3405TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3406
3407static void do_wrhtstate(DisasContext *dc, TCGv src)
3408{
3409 TCGv_i32 tl = tcg_temp_new_i32();
3410 TCGv_ptr tp = tcg_temp_new_ptr();
3411
3412 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3413 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3414 tcg_gen_shli_i32(tl, tl, 3);
3415 tcg_gen_ext_i32_ptr(tp, tl);
3416 tcg_gen_add_ptr(tp, tp, tcg_env);
3417
3418 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3419}
3420
3421TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3422
3423static void do_wrhintp(DisasContext *dc, TCGv src)
3424{
2da789de 3425 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
bb97f2f5
RH
3426}
3427
3428TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3429
3430static void do_wrhtba(DisasContext *dc, TCGv src)
3431{
2da789de 3432 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
bb97f2f5
RH
3433}
3434
3435TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3436
3437static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3438{
3439 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3440
577efa45 3441 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
bb97f2f5
RH
3442 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3443 translator_io_start(&dc->base);
577efa45 3444 gen_helper_tick_set_limit(r_tickptr, src);
bb97f2f5
RH
3445 /* End TB to handle timer interrupt */
3446 dc->base.is_jmp = DISAS_EXIT;
3447}
3448
3449TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3450 do_wrhstick_cmpr)
3451
25524734
RH
3452static bool do_saved_restored(DisasContext *dc, bool saved)
3453{
3454 if (!supervisor(dc)) {
3455 return raise_priv(dc);
3456 }
3457 if (saved) {
3458 gen_helper_saved(tcg_env);
3459 } else {
3460 gen_helper_restored(tcg_env);
3461 }
3462 return advance_pc(dc);
3463}
3464
3465TRANS(SAVED, 64, do_saved_restored, true)
3466TRANS(RESTORED, 64, do_saved_restored, false)
3467
d3825800
RH
3468static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3469{
3470 return advance_pc(dc);
3471}
3472
5458fd31
RH
3473/*
3474 * TODO: Need a feature bit for sparcv8.
3475 * In the meantime, treat all 32-bit cpus like sparcv7.
3476 */
3477TRANS(NOP_v7, 32, trans_NOP, a)
3478TRANS(NOP_v9, 64, trans_NOP, a)
0faef01b 3479
b597eedc 3480static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
428881de 3481 void (*func)(TCGv, TCGv, TCGv),
2a45b736
RH
3482 void (*funci)(TCGv, TCGv, target_long),
3483 bool logic_cc)
428881de
RH
3484{
3485 TCGv dst, src1;
3486
3487 /* For simplicity, we under-decoded the rs2 form. */
3488 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3489 return false;
3490 }
3491
2a45b736
RH
3492 if (logic_cc) {
3493 dst = cpu_cc_N;
428881de
RH
3494 } else {
3495 dst = gen_dest_gpr(dc, a->rd);
3496 }
3497 src1 = gen_load_gpr(dc, a->rs1);
3498
3499 if (a->imm || a->rs2_or_imm == 0) {
3500 if (funci) {
3501 funci(dst, src1, a->rs2_or_imm);
3502 } else {
3503 func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3504 }
3505 } else {
3506 func(dst, src1, cpu_regs[a->rs2_or_imm]);
3507 }
2a45b736
RH
3508
3509 if (logic_cc) {
3510 if (TARGET_LONG_BITS == 64) {
3511 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
3512 tcg_gen_movi_tl(cpu_icc_C, 0);
3513 }
3514 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
3515 tcg_gen_movi_tl(cpu_cc_C, 0);
3516 tcg_gen_movi_tl(cpu_cc_V, 0);
3517 }
3518
428881de 3519 gen_store_gpr(dc, a->rd, dst);
428881de
RH
3520 return advance_pc(dc);
3521}
3522
b597eedc 3523static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
428881de
RH
3524 void (*func)(TCGv, TCGv, TCGv),
3525 void (*funci)(TCGv, TCGv, target_long),
3526 void (*func_cc)(TCGv, TCGv, TCGv))
3527{
3528 if (a->cc) {
b597eedc 3529 return do_arith_int(dc, a, func_cc, NULL, false);
428881de 3530 }
b597eedc 3531 return do_arith_int(dc, a, func, funci, false);
428881de
RH
3532}
3533
3534static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3535 void (*func)(TCGv, TCGv, TCGv),
3536 void (*funci)(TCGv, TCGv, target_long))
3537{
b597eedc 3538 return do_arith_int(dc, a, func, funci, a->cc);
428881de
RH
3539}
3540
b597eedc
RH
3541TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3542TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3543TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3544TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
428881de 3545
b597eedc
RH
3546TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3547TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3548TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3549TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
a9aba13d 3550
428881de
RH
3551TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3552TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3553TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3554TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3555TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3556
b597eedc 3557TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
b5372650
RH
3558TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3559TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
b597eedc 3560TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
22188d7d 3561
3a6b8de3 3562TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
b597eedc 3563TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
4ee85ea9 3564
9c6ec5bc 3565/* TODO: Should have feature bit -- comes in with UltraSparc T2. */
b597eedc 3566TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
9c6ec5bc 3567
428881de
RH
3568static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3569{
3570 /* OR with %g0 is the canonical alias for MOV. */
3571 if (!a->cc && a->rs1 == 0) {
3572 if (a->imm || a->rs2_or_imm == 0) {
3573 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3574 } else if (a->rs2_or_imm & ~0x1f) {
3575 /* For simplicity, we under-decoded the rs2 form. */
3576 return false;
3577 } else {
3578 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3579 }
3580 return advance_pc(dc);
3581 }
3582 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3583}
3584
3a6b8de3
RH
3585static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
3586{
3587 TCGv_i64 t1, t2;
3588 TCGv dst;
3589
3590 if (!avail_DIV(dc)) {
3591 return false;
3592 }
3593 /* For simplicity, we under-decoded the rs2 form. */
3594 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3595 return false;
3596 }
3597
3598 if (unlikely(a->rs2_or_imm == 0)) {
3599 gen_exception(dc, TT_DIV_ZERO);
3600 return true;
3601 }
3602
3603 if (a->imm) {
3604 t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
3605 } else {
3606 TCGLabel *lab;
3607 TCGv_i32 n2;
3608
3609 finishing_insn(dc);
3610 flush_cond(dc);
3611
3612 n2 = tcg_temp_new_i32();
3613 tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
3614
3615 lab = delay_exception(dc, TT_DIV_ZERO);
3616 tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
3617
3618 t2 = tcg_temp_new_i64();
3619#ifdef TARGET_SPARC64
3620 tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
3621#else
3622 tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
3623#endif
3624 }
3625
3626 t1 = tcg_temp_new_i64();
3627 tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
3628
3629 tcg_gen_divu_i64(t1, t1, t2);
3630 tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
3631
3632 dst = gen_dest_gpr(dc, a->rd);
3633 tcg_gen_trunc_i64_tl(dst, t1);
3634 gen_store_gpr(dc, a->rd, dst);
3635 return advance_pc(dc);
3636}
3637
f3141174
RH
3638static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3639{
3640 TCGv dst, src1, src2;
3641
3642 if (!avail_64(dc)) {
3643 return false;
3644 }
3645 /* For simplicity, we under-decoded the rs2 form. */
3646 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3647 return false;
3648 }
3649
3650 if (unlikely(a->rs2_or_imm == 0)) {
3651 gen_exception(dc, TT_DIV_ZERO);
3652 return true;
3653 }
3654
3655 if (a->imm) {
3656 src2 = tcg_constant_tl(a->rs2_or_imm);
3657 } else {
3658 TCGLabel *lab;
3659
3660 finishing_insn(dc);
3661 flush_cond(dc);
3662
3663 lab = delay_exception(dc, TT_DIV_ZERO);
3664 src2 = cpu_regs[a->rs2_or_imm];
3665 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3666 }
3667
3668 dst = gen_dest_gpr(dc, a->rd);
3669 src1 = gen_load_gpr(dc, a->rs1);
3670
3671 tcg_gen_divu_tl(dst, src1, src2);
3672 gen_store_gpr(dc, a->rd, dst);
3673 return advance_pc(dc);
3674}
3675
3676static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3677{
3678 TCGv dst, src1, src2;
3679
3680 if (!avail_64(dc)) {
3681 return false;
3682 }
3683 /* For simplicity, we under-decoded the rs2 form. */
3684 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3685 return false;
3686 }
3687
3688 if (unlikely(a->rs2_or_imm == 0)) {
3689 gen_exception(dc, TT_DIV_ZERO);
3690 return true;
3691 }
3692
3693 dst = gen_dest_gpr(dc, a->rd);
3694 src1 = gen_load_gpr(dc, a->rs1);
3695
3696 if (a->imm) {
3697 if (unlikely(a->rs2_or_imm == -1)) {
3698 tcg_gen_neg_tl(dst, src1);
3699 gen_store_gpr(dc, a->rd, dst);
3700 return advance_pc(dc);
3701 }
3702 src2 = tcg_constant_tl(a->rs2_or_imm);
3703 } else {
3704 TCGLabel *lab;
3705 TCGv t1, t2;
3706
3707 finishing_insn(dc);
3708 flush_cond(dc);
3709
3710 lab = delay_exception(dc, TT_DIV_ZERO);
3711 src2 = cpu_regs[a->rs2_or_imm];
3712 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3713
3714 /*
3715 * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3716 * Set SRC2 to 1 as a new divisor, to produce the correct result.
3717 */
3718 t1 = tcg_temp_new();
3719 t2 = tcg_temp_new();
3720 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3721 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3722 tcg_gen_and_tl(t1, t1, t2);
3723 tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3724 tcg_constant_tl(1), src2);
3725 src2 = t1;
3726 }
3727
3728 tcg_gen_div_tl(dst, src1, src2);
3729 gen_store_gpr(dc, a->rd, dst);
3730 return advance_pc(dc);
3731}
3732
b88ce6f2
RH
3733static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
3734 int width, bool cc, bool left)
3735{
3736 TCGv dst, s1, s2, lo1, lo2;
3737 uint64_t amask, tabl, tabr;
3738 int shift, imask, omask;
3739
3740 dst = gen_dest_gpr(dc, a->rd);
3741 s1 = gen_load_gpr(dc, a->rs1);
3742 s2 = gen_load_gpr(dc, a->rs2);
3743
3744 if (cc) {
f828df74 3745 gen_op_subcc(cpu_cc_N, s1, s2);
b88ce6f2
RH
3746 }
3747
3748 /*
3749 * Theory of operation: there are two tables, left and right (not to
3750 * be confused with the left and right versions of the opcode). These
3751 * are indexed by the low 3 bits of the inputs. To make things "easy",
3752 * these tables are loaded into two constants, TABL and TABR below.
3753 * The operation index = (input & imask) << shift calculates the index
3754 * into the constant, while val = (table >> index) & omask calculates
3755 * the value we're looking for.
3756 */
3757 switch (width) {
3758 case 8:
3759 imask = 0x7;
3760 shift = 3;
3761 omask = 0xff;
3762 if (left) {
3763 tabl = 0x80c0e0f0f8fcfeffULL;
3764 tabr = 0xff7f3f1f0f070301ULL;
3765 } else {
3766 tabl = 0x0103070f1f3f7fffULL;
3767 tabr = 0xfffefcf8f0e0c080ULL;
3768 }
3769 break;
3770 case 16:
3771 imask = 0x6;
3772 shift = 1;
3773 omask = 0xf;
3774 if (left) {
3775 tabl = 0x8cef;
3776 tabr = 0xf731;
3777 } else {
3778 tabl = 0x137f;
3779 tabr = 0xfec8;
3780 }
3781 break;
3782 case 32:
3783 imask = 0x4;
3784 shift = 0;
3785 omask = 0x3;
3786 if (left) {
3787 tabl = (2 << 2) | 3;
3788 tabr = (3 << 2) | 1;
3789 } else {
3790 tabl = (1 << 2) | 3;
3791 tabr = (3 << 2) | 2;
3792 }
3793 break;
3794 default:
3795 abort();
3796 }
3797
3798 lo1 = tcg_temp_new();
3799 lo2 = tcg_temp_new();
3800 tcg_gen_andi_tl(lo1, s1, imask);
3801 tcg_gen_andi_tl(lo2, s2, imask);
3802 tcg_gen_shli_tl(lo1, lo1, shift);
3803 tcg_gen_shli_tl(lo2, lo2, shift);
3804
3805 tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
3806 tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
3807 tcg_gen_andi_tl(lo1, lo1, omask);
3808 tcg_gen_andi_tl(lo2, lo2, omask);
3809
3810 amask = address_mask_i(dc, -8);
3811 tcg_gen_andi_tl(s1, s1, amask);
3812 tcg_gen_andi_tl(s2, s2, amask);
3813
3814 /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
3815 tcg_gen_and_tl(lo2, lo2, lo1);
3816 tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
3817
3818 gen_store_gpr(dc, a->rd, dst);
3819 return advance_pc(dc);
3820}
3821
3822TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3823TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3824TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3825TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3826TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3827TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3828
3829TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3830TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3831TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3832TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3833TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3834TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3835
45bfed3b
RH
3836static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
3837 void (*func)(TCGv, TCGv, TCGv))
3838{
3839 TCGv dst = gen_dest_gpr(dc, a->rd);
3840 TCGv src1 = gen_load_gpr(dc, a->rs1);
3841 TCGv src2 = gen_load_gpr(dc, a->rs2);
3842
3843 func(dst, src1, src2);
3844 gen_store_gpr(dc, a->rd, dst);
3845 return advance_pc(dc);
3846}
3847
3848TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
3849TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
3850TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
3851
9e20ca94
RH
3852static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
3853{
3854#ifdef TARGET_SPARC64
3855 TCGv tmp = tcg_temp_new();
3856
3857 tcg_gen_add_tl(tmp, s1, s2);
3858 tcg_gen_andi_tl(dst, tmp, -8);
3859 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
3860#else
3861 g_assert_not_reached();
3862#endif
3863}
3864
3865static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
3866{
3867#ifdef TARGET_SPARC64
3868 TCGv tmp = tcg_temp_new();
3869
3870 tcg_gen_add_tl(tmp, s1, s2);
3871 tcg_gen_andi_tl(dst, tmp, -8);
3872 tcg_gen_neg_tl(tmp, tmp);
3873 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
3874#else
3875 g_assert_not_reached();
3876#endif
3877}
3878
3879TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
3880TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
3881
39ca3490
RH
3882static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
3883{
3884#ifdef TARGET_SPARC64
3885 tcg_gen_add_tl(dst, s1, s2);
3886 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
3887#else
3888 g_assert_not_reached();
3889#endif
3890}
3891
3892TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
3893
5fc546ee
RH
3894static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
3895{
3896 TCGv dst, src1, src2;
3897
3898 /* Reject 64-bit shifts for sparc32. */
3899 if (avail_32(dc) && a->x) {
3900 return false;
3901 }
3902
3903 src2 = tcg_temp_new();
3904 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
3905 src1 = gen_load_gpr(dc, a->rs1);
3906 dst = gen_dest_gpr(dc, a->rd);
3907
3908 if (l) {
3909 tcg_gen_shl_tl(dst, src1, src2);
3910 if (!a->x) {
3911 tcg_gen_ext32u_tl(dst, dst);
3912 }
3913 } else if (u) {
3914 if (!a->x) {
3915 tcg_gen_ext32u_tl(dst, src1);
3916 src1 = dst;
3917 }
3918 tcg_gen_shr_tl(dst, src1, src2);
3919 } else {
3920 if (!a->x) {
3921 tcg_gen_ext32s_tl(dst, src1);
3922 src1 = dst;
3923 }
3924 tcg_gen_sar_tl(dst, src1, src2);
3925 }
3926 gen_store_gpr(dc, a->rd, dst);
3927 return advance_pc(dc);
3928}
3929
3930TRANS(SLL_r, ALL, do_shift_r, a, true, true)
3931TRANS(SRL_r, ALL, do_shift_r, a, false, true)
3932TRANS(SRA_r, ALL, do_shift_r, a, false, false)
3933
3934static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
3935{
3936 TCGv dst, src1;
3937
3938 /* Reject 64-bit shifts for sparc32. */
3939 if (avail_32(dc) && (a->x || a->i >= 32)) {
3940 return false;
3941 }
3942
3943 src1 = gen_load_gpr(dc, a->rs1);
3944 dst = gen_dest_gpr(dc, a->rd);
3945
3946 if (avail_32(dc) || a->x) {
3947 if (l) {
3948 tcg_gen_shli_tl(dst, src1, a->i);
3949 } else if (u) {
3950 tcg_gen_shri_tl(dst, src1, a->i);
3951 } else {
3952 tcg_gen_sari_tl(dst, src1, a->i);
3953 }
3954 } else {
3955 if (l) {
3956 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
3957 } else if (u) {
3958 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
3959 } else {
3960 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
3961 }
3962 }
3963 gen_store_gpr(dc, a->rd, dst);
3964 return advance_pc(dc);
3965}
3966
3967TRANS(SLL_i, ALL, do_shift_i, a, true, true)
3968TRANS(SRL_i, ALL, do_shift_i, a, false, true)
3969TRANS(SRA_i, ALL, do_shift_i, a, false, false)
3970
fb4ed7aa
RH
3971static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
3972{
3973 /* For simplicity, we under-decoded the rs2 form. */
3974 if (!imm && rs2_or_imm & ~0x1f) {
3975 return NULL;
3976 }
3977 if (imm || rs2_or_imm == 0) {
3978 return tcg_constant_tl(rs2_or_imm);
3979 } else {
3980 return cpu_regs[rs2_or_imm];
3981 }
3982}
3983
3984static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
3985{
3986 TCGv dst = gen_load_gpr(dc, rd);
c8507ebf 3987 TCGv c2 = tcg_constant_tl(cmp->c2);
fb4ed7aa 3988
c8507ebf 3989 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
fb4ed7aa
RH
3990 gen_store_gpr(dc, rd, dst);
3991 return advance_pc(dc);
3992}
3993
3994static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
3995{
3996 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3997 DisasCompare cmp;
3998
3999 if (src2 == NULL) {
4000 return false;
4001 }
4002 gen_compare(&cmp, a->cc, a->cond, dc);
4003 return do_mov_cond(dc, &cmp, a->rd, src2);
4004}
4005
4006static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
4007{
4008 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4009 DisasCompare cmp;
4010
4011 if (src2 == NULL) {
4012 return false;
4013 }
4014 gen_fcompare(&cmp, a->cc, a->cond);
4015 return do_mov_cond(dc, &cmp, a->rd, src2);
4016}
4017
4018static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
4019{
4020 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4021 DisasCompare cmp;
4022
4023 if (src2 == NULL) {
4024 return false;
4025 }
2c4f56c9
RH
4026 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
4027 return false;
4028 }
fb4ed7aa
RH
4029 return do_mov_cond(dc, &cmp, a->rd, src2);
4030}
4031
86b82fe0
RH
4032static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
4033 bool (*func)(DisasContext *dc, int rd, TCGv src))
4034{
4035 TCGv src1, sum;
4036
4037 /* For simplicity, we under-decoded the rs2 form. */
4038 if (!a->imm && a->rs2_or_imm & ~0x1f) {
4039 return false;
4040 }
4041
4042 /*
4043 * Always load the sum into a new temporary.
4044 * This is required to capture the value across a window change,
4045 * e.g. SAVE and RESTORE, and may be optimized away otherwise.
4046 */
4047 sum = tcg_temp_new();
4048 src1 = gen_load_gpr(dc, a->rs1);
4049 if (a->imm || a->rs2_or_imm == 0) {
4050 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
4051 } else {
4052 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
4053 }
4054 return func(dc, a->rd, sum);
4055}
4056
4057static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
4058{
4059 /*
4060 * Preserve pc across advance, so that we can delay
4061 * the writeback to rd until after src is consumed.
4062 */
4063 target_ulong cur_pc = dc->pc;
4064
4065 gen_check_align(dc, src, 3);
4066
4067 gen_mov_pc_npc(dc);
4068 tcg_gen_mov_tl(cpu_npc, src);
4069 gen_address_mask(dc, cpu_npc);
4070 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
4071
4072 dc->npc = DYNAMIC_PC_LOOKUP;
4073 return true;
4074}
4075
4076TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
4077
4078static bool do_rett(DisasContext *dc, int rd, TCGv src)
4079{
4080 if (!supervisor(dc)) {
4081 return raise_priv(dc);
4082 }
4083
4084 gen_check_align(dc, src, 3);
4085
4086 gen_mov_pc_npc(dc);
4087 tcg_gen_mov_tl(cpu_npc, src);
4088 gen_helper_rett(tcg_env);
4089
4090 dc->npc = DYNAMIC_PC;
4091 return true;
4092}
4093
4094TRANS(RETT, 32, do_add_special, a, do_rett)
4095
4096static bool do_return(DisasContext *dc, int rd, TCGv src)
4097{
4098 gen_check_align(dc, src, 3);
0dfae4f9 4099 gen_helper_restore(tcg_env);
86b82fe0
RH
4100
4101 gen_mov_pc_npc(dc);
4102 tcg_gen_mov_tl(cpu_npc, src);
4103 gen_address_mask(dc, cpu_npc);
4104
86b82fe0
RH
4105 dc->npc = DYNAMIC_PC_LOOKUP;
4106 return true;
4107}
4108
4109TRANS(RETURN, 64, do_add_special, a, do_return)
4110
d3825800
RH
4111static bool do_save(DisasContext *dc, int rd, TCGv src)
4112{
4113 gen_helper_save(tcg_env);
4114 gen_store_gpr(dc, rd, src);
4115 return advance_pc(dc);
4116}
4117
4118TRANS(SAVE, ALL, do_add_special, a, do_save)
4119
4120static bool do_restore(DisasContext *dc, int rd, TCGv src)
4121{
4122 gen_helper_restore(tcg_env);
4123 gen_store_gpr(dc, rd, src);
4124 return advance_pc(dc);
4125}
4126
4127TRANS(RESTORE, ALL, do_add_special, a, do_restore)
4128
8f75b8a4
RH
4129static bool do_done_retry(DisasContext *dc, bool done)
4130{
4131 if (!supervisor(dc)) {
4132 return raise_priv(dc);
4133 }
4134 dc->npc = DYNAMIC_PC;
4135 dc->pc = DYNAMIC_PC;
4136 translator_io_start(&dc->base);
4137 if (done) {
4138 gen_helper_done(tcg_env);
4139 } else {
4140 gen_helper_retry(tcg_env);
4141 }
4142 return true;
4143}
4144
4145TRANS(DONE, 64, do_done_retry, true)
4146TRANS(RETRY, 64, do_done_retry, false)
4147
0880d20b
RH
4148/*
4149 * Major opcode 11 -- load and store instructions
4150 */
4151
4152static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
4153{
4154 TCGv addr, tmp = NULL;
4155
4156 /* For simplicity, we under-decoded the rs2 form. */
4157 if (!imm && rs2_or_imm & ~0x1f) {
4158 return NULL;
4159 }
4160
4161 addr = gen_load_gpr(dc, rs1);
4162 if (rs2_or_imm) {
4163 tmp = tcg_temp_new();
4164 if (imm) {
4165 tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
4166 } else {
4167 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
4168 }
4169 addr = tmp;
4170 }
4171 if (AM_CHECK(dc)) {
4172 if (!tmp) {
4173 tmp = tcg_temp_new();
4174 }
4175 tcg_gen_ext32u_tl(tmp, addr);
4176 addr = tmp;
4177 }
4178 return addr;
4179}
4180
4181static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4182{
4183 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4184 DisasASI da;
4185
4186 if (addr == NULL) {
4187 return false;
4188 }
4189 da = resolve_asi(dc, a->asi, mop);
4190
4191 reg = gen_dest_gpr(dc, a->rd);
42071fc1 4192 gen_ld_asi(dc, &da, reg, addr);
0880d20b
RH
4193 gen_store_gpr(dc, a->rd, reg);
4194 return advance_pc(dc);
4195}
4196
4197TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
4198TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
4199TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
4200TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
4201TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
4202TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
4203TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
4204
4205static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4206{
4207 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4208 DisasASI da;
4209
4210 if (addr == NULL) {
4211 return false;
4212 }
4213 da = resolve_asi(dc, a->asi, mop);
4214
4215 reg = gen_load_gpr(dc, a->rd);
42071fc1 4216 gen_st_asi(dc, &da, reg, addr);
0880d20b
RH
4217 return advance_pc(dc);
4218}
4219
4220TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
4221TRANS(STB, ALL, do_st_gpr, a, MO_UB)
4222TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
4223TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
4224
4225static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
4226{
4227 TCGv addr;
4228 DisasASI da;
4229
4230 if (a->rd & 1) {
4231 return false;
4232 }
4233 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4234 if (addr == NULL) {
4235 return false;
4236 }
4237 da = resolve_asi(dc, a->asi, MO_TEUQ);
42071fc1 4238 gen_ldda_asi(dc, &da, addr, a->rd);
0880d20b
RH
4239 return advance_pc(dc);
4240}
4241
4242static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
4243{
4244 TCGv addr;
4245 DisasASI da;
4246
4247 if (a->rd & 1) {
4248 return false;
4249 }
4250 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4251 if (addr == NULL) {
4252 return false;
4253 }
4254 da = resolve_asi(dc, a->asi, MO_TEUQ);
42071fc1 4255 gen_stda_asi(dc, &da, addr, a->rd);
0880d20b
RH
4256 return advance_pc(dc);
4257}
4258
cf07cd1e
RH
4259static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4260{
4261 TCGv addr, reg;
4262 DisasASI da;
4263
4264 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4265 if (addr == NULL) {
4266 return false;
4267 }
4268 da = resolve_asi(dc, a->asi, MO_UB);
4269
4270 reg = gen_dest_gpr(dc, a->rd);
4271 gen_ldstub_asi(dc, &da, reg, addr);
4272 gen_store_gpr(dc, a->rd, reg);
4273 return advance_pc(dc);
4274}
4275
dca544b9
RH
4276static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4277{
4278 TCGv addr, dst, src;
4279 DisasASI da;
4280
4281 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4282 if (addr == NULL) {
4283 return false;
4284 }
4285 da = resolve_asi(dc, a->asi, MO_TEUL);
4286
4287 dst = gen_dest_gpr(dc, a->rd);
4288 src = gen_load_gpr(dc, a->rd);
4289 gen_swap_asi(dc, &da, dst, src, addr);
4290 gen_store_gpr(dc, a->rd, dst);
4291 return advance_pc(dc);
4292}
4293
d0a11d25
RH
4294static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4295{
4296 TCGv addr, o, n, c;
4297 DisasASI da;
4298
4299 addr = gen_ldst_addr(dc, a->rs1, true, 0);
4300 if (addr == NULL) {
4301 return false;
4302 }
4303 da = resolve_asi(dc, a->asi, mop);
4304
4305 o = gen_dest_gpr(dc, a->rd);
4306 n = gen_load_gpr(dc, a->rd);
4307 c = gen_load_gpr(dc, a->rs2_or_imm);
4308 gen_cas_asi(dc, &da, o, n, c, addr);
4309 gen_store_gpr(dc, a->rd, o);
4310 return advance_pc(dc);
4311}
4312
4313TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4314TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4315
06c060d9
RH
4316static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4317{
4318 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4319 DisasASI da;
4320
4321 if (addr == NULL) {
4322 return false;
4323 }
4324 if (gen_trap_ifnofpu(dc)) {
4325 return true;
4326 }
4327 if (sz == MO_128 && gen_trap_float128(dc)) {
4328 return true;
4329 }
4330 da = resolve_asi(dc, a->asi, MO_TE | sz);
287b1152 4331 gen_ldf_asi(dc, &da, sz, addr, a->rd);
06c060d9
RH
4332 gen_update_fprs_dirty(dc, a->rd);
4333 return advance_pc(dc);
4334}
4335
4336TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
4337TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
4338TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
4339
287b1152
RH
4340TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4341TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4342TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4343
06c060d9
RH
4344static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4345{
4346 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4347 DisasASI da;
4348
4349 if (addr == NULL) {
4350 return false;
4351 }
4352 if (gen_trap_ifnofpu(dc)) {
4353 return true;
4354 }
4355 if (sz == MO_128 && gen_trap_float128(dc)) {
4356 return true;
4357 }
4358 da = resolve_asi(dc, a->asi, MO_TE | sz);
287b1152 4359 gen_stf_asi(dc, &da, sz, addr, a->rd);
06c060d9
RH
4360 return advance_pc(dc);
4361}
4362
4363TRANS(STF, ALL, do_st_fpr, a, MO_32)
4364TRANS(STDF, ALL, do_st_fpr, a, MO_64)
4365TRANS(STQF, ALL, do_st_fpr, a, MO_128)
4366
287b1152
RH
4367TRANS(STFA, 64, do_st_fpr, a, MO_32)
4368TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4369TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4370
06c060d9
RH
4371static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
4372{
4373 if (!avail_32(dc)) {
4374 return false;
4375 }
4376 if (!supervisor(dc)) {
4377 return raise_priv(dc);
4378 }
4379 if (gen_trap_ifnofpu(dc)) {
4380 return true;
4381 }
4382 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
4383 return true;
4384}
4385
da681406
RH
4386static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop,
4387 target_ulong new_mask, target_ulong old_mask)
3d3c0673 4388{
da681406 4389 TCGv tmp, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
3d3c0673
RH
4390 if (addr == NULL) {
4391 return false;
4392 }
4393 if (gen_trap_ifnofpu(dc)) {
4394 return true;
4395 }
da681406
RH
4396 tmp = tcg_temp_new();
4397 tcg_gen_qemu_ld_tl(tmp, addr, dc->mem_idx, mop | MO_ALIGN);
4398 tcg_gen_andi_tl(tmp, tmp, new_mask);
4399 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, old_mask);
4400 tcg_gen_or_tl(cpu_fsr, cpu_fsr, tmp);
4401 gen_helper_set_fsr(tcg_env, cpu_fsr);
3d3c0673
RH
4402 return advance_pc(dc);
4403}
4404
da681406
RH
4405TRANS(LDFSR, ALL, do_ldfsr, a, MO_TEUL, FSR_LDFSR_MASK, FSR_LDFSR_OLDMASK)
4406TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK)
3d3c0673
RH
4407
4408static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
4409{
4410 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4411 if (addr == NULL) {
4412 return false;
4413 }
4414 if (gen_trap_ifnofpu(dc)) {
4415 return true;
4416 }
4417 tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN);
4418 return advance_pc(dc);
4419}
4420
4421TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
4422TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
4423
3a38260e
RH
4424static bool do_fc(DisasContext *dc, int rd, bool c)
4425{
4426 uint64_t mask;
4427
4428 if (gen_trap_ifnofpu(dc)) {
4429 return true;
4430 }
4431
4432 if (rd & 1) {
4433 mask = MAKE_64BIT_MASK(0, 32);
4434 } else {
4435 mask = MAKE_64BIT_MASK(32, 32);
4436 }
4437 if (c) {
4438 tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask);
4439 } else {
4440 tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask);
4441 }
4442 gen_update_fprs_dirty(dc, rd);
4443 return advance_pc(dc);
4444}
4445
4446TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
4447TRANS(FONEs, VIS1, do_fc, a->rd, 1)
4448
4449static bool do_dc(DisasContext *dc, int rd, int64_t c)
4450{
4451 if (gen_trap_ifnofpu(dc)) {
4452 return true;
4453 }
4454
4455 tcg_gen_movi_i64(cpu_fpr[rd / 2], c);
4456 gen_update_fprs_dirty(dc, rd);
4457 return advance_pc(dc);
4458}
4459
4460TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
4461TRANS(FONEd, VIS1, do_dc, a->rd, -1)
4462
baf3dbf2
RH
4463static bool do_ff(DisasContext *dc, arg_r_r *a,
4464 void (*func)(TCGv_i32, TCGv_i32))
4465{
4466 TCGv_i32 tmp;
4467
4468 if (gen_trap_ifnofpu(dc)) {
4469 return true;
4470 }
4471
4472 tmp = gen_load_fpr_F(dc, a->rs);
4473 func(tmp, tmp);
4474 gen_store_fpr_F(dc, a->rd, tmp);
4475 return advance_pc(dc);
4476}
4477
4478TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4479TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4480TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4481TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4482TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4483
2f722641
RH
4484static bool do_fd(DisasContext *dc, arg_r_r *a,
4485 void (*func)(TCGv_i32, TCGv_i64))
4486{
4487 TCGv_i32 dst;
4488 TCGv_i64 src;
4489
4490 if (gen_trap_ifnofpu(dc)) {
4491 return true;
4492 }
4493
4494 dst = gen_dest_fpr_F(dc);
4495 src = gen_load_fpr_D(dc, a->rs);
4496 func(dst, src);
4497 gen_store_fpr_F(dc, a->rd, dst);
4498 return advance_pc(dc);
4499}
4500
4501TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
4502TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
4503
119cb94f
RH
4504static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4505 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4506{
4507 TCGv_i32 tmp;
4508
4509 if (gen_trap_ifnofpu(dc)) {
4510 return true;
4511 }
4512
4513 gen_op_clear_ieee_excp_and_FTT();
4514 tmp = gen_load_fpr_F(dc, a->rs);
4515 func(tmp, tcg_env, tmp);
4516 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4517 gen_store_fpr_F(dc, a->rd, tmp);
4518 return advance_pc(dc);
4519}
4520
4521TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4522TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4523TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4524
8c94bcd8
RH
4525static bool do_env_fd(DisasContext *dc, arg_r_r *a,
4526 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
4527{
4528 TCGv_i32 dst;
4529 TCGv_i64 src;
4530
4531 if (gen_trap_ifnofpu(dc)) {
4532 return true;
4533 }
4534
4535 gen_op_clear_ieee_excp_and_FTT();
4536 dst = gen_dest_fpr_F(dc);
4537 src = gen_load_fpr_D(dc, a->rs);
4538 func(dst, tcg_env, src);
4539 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4540 gen_store_fpr_F(dc, a->rd, dst);
4541 return advance_pc(dc);
4542}
4543
4544TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
4545TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
4546TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
4547
c6d83e4f
RH
4548static bool do_dd(DisasContext *dc, arg_r_r *a,
4549 void (*func)(TCGv_i64, TCGv_i64))
4550{
4551 TCGv_i64 dst, src;
4552
4553 if (gen_trap_ifnofpu(dc)) {
4554 return true;
4555 }
4556
4557 dst = gen_dest_fpr_D(dc, a->rd);
4558 src = gen_load_fpr_D(dc, a->rs);
4559 func(dst, src);
4560 gen_store_fpr_D(dc, a->rd, dst);
4561 return advance_pc(dc);
4562}
4563
4564TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4565TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4566TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4567TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4568TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4569
8aa418b3
RH
4570static bool do_env_dd(DisasContext *dc, arg_r_r *a,
4571 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
4572{
4573 TCGv_i64 dst, src;
4574
4575 if (gen_trap_ifnofpu(dc)) {
4576 return true;
4577 }
4578
4579 gen_op_clear_ieee_excp_and_FTT();
4580 dst = gen_dest_fpr_D(dc, a->rd);
4581 src = gen_load_fpr_D(dc, a->rs);
4582 func(dst, tcg_env, src);
4583 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4584 gen_store_fpr_D(dc, a->rd, dst);
4585 return advance_pc(dc);
4586}
4587
4588TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
4589TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
4590TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
4591
199d43ef
RH
4592static bool do_env_df(DisasContext *dc, arg_r_r *a,
4593 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4594{
4595 TCGv_i64 dst;
4596 TCGv_i32 src;
4597
4598 if (gen_trap_ifnofpu(dc)) {
4599 return true;
4600 }
4601
4602 gen_op_clear_ieee_excp_and_FTT();
4603 dst = gen_dest_fpr_D(dc, a->rd);
4604 src = gen_load_fpr_F(dc, a->rs);
4605 func(dst, tcg_env, src);
4606 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4607 gen_store_fpr_D(dc, a->rd, dst);
4608 return advance_pc(dc);
4609}
4610
4611TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4612TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4613TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4614
f4e18df5
RH
4615static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a)
4616{
4617 int rd, rs;
4618
4619 if (!avail_64(dc)) {
4620 return false;
4621 }
4622 if (gen_trap_ifnofpu(dc)) {
4623 return true;
4624 }
4625 if (gen_trap_float128(dc)) {
4626 return true;
4627 }
4628
4629 gen_op_clear_ieee_excp_and_FTT();
4630 rd = QFPREG(a->rd);
4631 rs = QFPREG(a->rs);
4632 tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
4633 tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
4634 gen_update_fprs_dirty(dc, rd);
4635 return advance_pc(dc);
4636}
4637
4638static bool do_qq(DisasContext *dc, arg_r_r *a,
4639 void (*func)(TCGv_env))
4640{
4641 if (gen_trap_ifnofpu(dc)) {
4642 return true;
4643 }
4644 if (gen_trap_float128(dc)) {
4645 return true;
4646 }
4647
4648 gen_op_clear_ieee_excp_and_FTT();
4649 gen_op_load_fpr_QT1(QFPREG(a->rs));
4650 func(tcg_env);
4651 gen_op_store_QT0_fpr(QFPREG(a->rd));
4652 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4653 return advance_pc(dc);
4654}
4655
4656TRANS(FNEGq, 64, do_qq, a, gen_helper_fnegq)
4657TRANS(FABSq, 64, do_qq, a, gen_helper_fabsq)
4658
c995216b
RH
4659static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4660 void (*func)(TCGv_env))
4661{
4662 if (gen_trap_ifnofpu(dc)) {
4663 return true;
4664 }
4665 if (gen_trap_float128(dc)) {
4666 return true;
4667 }
4668
4669 gen_op_clear_ieee_excp_and_FTT();
4670 gen_op_load_fpr_QT1(QFPREG(a->rs));
4671 func(tcg_env);
4672 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4673 gen_op_store_QT0_fpr(QFPREG(a->rd));
4674 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4675 return advance_pc(dc);
4676}
4677
4678TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4679
bd9c5c42
RH
4680static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4681 void (*func)(TCGv_i32, TCGv_env))
4682{
4683 TCGv_i32 dst;
4684
4685 if (gen_trap_ifnofpu(dc)) {
4686 return true;
4687 }
4688 if (gen_trap_float128(dc)) {
4689 return true;
4690 }
4691
4692 gen_op_clear_ieee_excp_and_FTT();
4693 gen_op_load_fpr_QT1(QFPREG(a->rs));
4694 dst = gen_dest_fpr_F(dc);
4695 func(dst, tcg_env);
4696 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4697 gen_store_fpr_F(dc, a->rd, dst);
4698 return advance_pc(dc);
4699}
4700
4701TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4702TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4703
1617586f
RH
4704static bool do_env_dq(DisasContext *dc, arg_r_r *a,
4705 void (*func)(TCGv_i64, TCGv_env))
4706{
4707 TCGv_i64 dst;
4708
4709 if (gen_trap_ifnofpu(dc)) {
4710 return true;
4711 }
4712 if (gen_trap_float128(dc)) {
4713 return true;
4714 }
4715
4716 gen_op_clear_ieee_excp_and_FTT();
4717 gen_op_load_fpr_QT1(QFPREG(a->rs));
4718 dst = gen_dest_fpr_D(dc, a->rd);
4719 func(dst, tcg_env);
4720 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4721 gen_store_fpr_D(dc, a->rd, dst);
4722 return advance_pc(dc);
4723}
4724
4725TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
4726TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
4727
13ebcc77
RH
4728static bool do_env_qf(DisasContext *dc, arg_r_r *a,
4729 void (*func)(TCGv_env, TCGv_i32))
4730{
4731 TCGv_i32 src;
4732
4733 if (gen_trap_ifnofpu(dc)) {
4734 return true;
4735 }
4736 if (gen_trap_float128(dc)) {
4737 return true;
4738 }
4739
4740 gen_op_clear_ieee_excp_and_FTT();
4741 src = gen_load_fpr_F(dc, a->rs);
4742 func(tcg_env, src);
4743 gen_op_store_QT0_fpr(QFPREG(a->rd));
4744 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4745 return advance_pc(dc);
4746}
4747
4748TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
4749TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
4750
7b8e3e1a
RH
4751static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4752 void (*func)(TCGv_env, TCGv_i64))
4753{
4754 TCGv_i64 src;
4755
4756 if (gen_trap_ifnofpu(dc)) {
4757 return true;
4758 }
4759 if (gen_trap_float128(dc)) {
4760 return true;
4761 }
4762
4763 gen_op_clear_ieee_excp_and_FTT();
4764 src = gen_load_fpr_D(dc, a->rs);
4765 func(tcg_env, src);
4766 gen_op_store_QT0_fpr(QFPREG(a->rd));
4767 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4768 return advance_pc(dc);
4769}
4770
4771TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
4772TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
4773
7f10b52f
RH
4774static bool do_fff(DisasContext *dc, arg_r_r_r *a,
4775 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
4776{
4777 TCGv_i32 src1, src2;
4778
4779 if (gen_trap_ifnofpu(dc)) {
4780 return true;
4781 }
4782
4783 src1 = gen_load_fpr_F(dc, a->rs1);
4784 src2 = gen_load_fpr_F(dc, a->rs2);
4785 func(src1, src1, src2);
4786 gen_store_fpr_F(dc, a->rd, src1);
4787 return advance_pc(dc);
4788}
4789
4790TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
4791TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
4792TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
4793TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
4794TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
4795TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
4796TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
4797TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
4798TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
4799TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
4800TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
4801TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
4802
c1514961
RH
4803static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
4804 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
4805{
4806 TCGv_i32 src1, src2;
4807
4808 if (gen_trap_ifnofpu(dc)) {
4809 return true;
4810 }
4811
4812 gen_op_clear_ieee_excp_and_FTT();
4813 src1 = gen_load_fpr_F(dc, a->rs1);
4814 src2 = gen_load_fpr_F(dc, a->rs2);
4815 func(src1, tcg_env, src1, src2);
4816 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4817 gen_store_fpr_F(dc, a->rd, src1);
4818 return advance_pc(dc);
4819}
4820
4821TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
4822TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
4823TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
4824TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
4825
e06c9f83
RH
4826static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
4827 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
4828{
4829 TCGv_i64 dst, src1, src2;
4830
4831 if (gen_trap_ifnofpu(dc)) {
4832 return true;
4833 }
4834
4835 dst = gen_dest_fpr_D(dc, a->rd);
4836 src1 = gen_load_fpr_D(dc, a->rs1);
4837 src2 = gen_load_fpr_D(dc, a->rs2);
4838 func(dst, src1, src2);
4839 gen_store_fpr_D(dc, a->rd, dst);
4840 return advance_pc(dc);
4841}
4842
4843TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16)
4844TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au)
4845TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al)
4846TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
4847TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
4848TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16)
4849TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16)
4850TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge)
4851TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand)
4852
4853TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64)
4854TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64)
4855TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64)
4856TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64)
4857TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
4858TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
4859TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
4860TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
4861TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
4862TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
4863TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
4864TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
4865
4b6edc0a
RH
4866TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
4867TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata)
4868TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
4869
e2fa6bd1
RH
4870static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
4871 void (*func)(TCGv, TCGv_i64, TCGv_i64))
4872{
4873 TCGv_i64 src1, src2;
4874 TCGv dst;
4875
4876 if (gen_trap_ifnofpu(dc)) {
4877 return true;
4878 }
4879
4880 dst = gen_dest_gpr(dc, a->rd);
4881 src1 = gen_load_fpr_D(dc, a->rs1);
4882 src2 = gen_load_fpr_D(dc, a->rs2);
4883 func(dst, src1, src2);
4884 gen_store_gpr(dc, a->rd, dst);
4885 return advance_pc(dc);
4886}
4887
4888TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
4889TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
4890TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
4891TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
4892
4893TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
4894TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
4895TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
4896TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
4897
f2a59b0a
RH
4898static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
4899 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
4900{
4901 TCGv_i64 dst, src1, src2;
4902
4903 if (gen_trap_ifnofpu(dc)) {
4904 return true;
4905 }
4906
4907 gen_op_clear_ieee_excp_and_FTT();
4908 dst = gen_dest_fpr_D(dc, a->rd);
4909 src1 = gen_load_fpr_D(dc, a->rs1);
4910 src2 = gen_load_fpr_D(dc, a->rs2);
4911 func(dst, tcg_env, src1, src2);
4912 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4913 gen_store_fpr_D(dc, a->rd, dst);
4914 return advance_pc(dc);
4915}
4916
4917TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
4918TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
4919TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
4920TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
4921
ff4c711b
RH
4922static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
4923{
4924 TCGv_i64 dst;
4925 TCGv_i32 src1, src2;
4926
4927 if (gen_trap_ifnofpu(dc)) {
4928 return true;
4929 }
4930 if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
4931 return raise_unimpfpop(dc);
4932 }
4933
4934 gen_op_clear_ieee_excp_and_FTT();
4935 dst = gen_dest_fpr_D(dc, a->rd);
4936 src1 = gen_load_fpr_F(dc, a->rs1);
4937 src2 = gen_load_fpr_F(dc, a->rs2);
4938 gen_helper_fsmuld(dst, tcg_env, src1, src2);
4939 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4940 gen_store_fpr_D(dc, a->rd, dst);
4941 return advance_pc(dc);
4942}
4943
afb04344
RH
4944static bool do_dddd(DisasContext *dc, arg_r_r_r *a,
4945 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
4946{
4947 TCGv_i64 dst, src0, src1, src2;
4948
4949 if (gen_trap_ifnofpu(dc)) {
4950 return true;
4951 }
4952
4953 dst = gen_dest_fpr_D(dc, a->rd);
4954 src0 = gen_load_fpr_D(dc, a->rd);
4955 src1 = gen_load_fpr_D(dc, a->rs1);
4956 src2 = gen_load_fpr_D(dc, a->rs2);
4957 func(dst, src0, src1, src2);
4958 gen_store_fpr_D(dc, a->rd, dst);
4959 return advance_pc(dc);
4960}
4961
4962TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
4963
a4056239
RH
4964static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
4965 void (*func)(TCGv_env))
4966{
4967 if (gen_trap_ifnofpu(dc)) {
4968 return true;
4969 }
4970 if (gen_trap_float128(dc)) {
4971 return true;
4972 }
4973
4974 gen_op_clear_ieee_excp_and_FTT();
4975 gen_op_load_fpr_QT0(QFPREG(a->rs1));
4976 gen_op_load_fpr_QT1(QFPREG(a->rs2));
4977 func(tcg_env);
4978 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
4979 gen_op_store_QT0_fpr(QFPREG(a->rd));
4980 gen_update_fprs_dirty(dc, QFPREG(a->rd));
4981 return advance_pc(dc);
4982}
4983
4984TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
4985TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
4986TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
4987TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
4988
5e3b17bb
RH
4989static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
4990{
4991 TCGv_i64 src1, src2;
4992
4993 if (gen_trap_ifnofpu(dc)) {
4994 return true;
4995 }
4996 if (gen_trap_float128(dc)) {
4997 return true;
4998 }
4999
5000 gen_op_clear_ieee_excp_and_FTT();
5001 src1 = gen_load_fpr_D(dc, a->rs1);
5002 src2 = gen_load_fpr_D(dc, a->rs2);
5003 gen_helper_fdmulq(tcg_env, src1, src2);
5004 gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env);
5005 gen_op_store_QT0_fpr(QFPREG(a->rd));
5006 gen_update_fprs_dirty(dc, QFPREG(a->rd));
5007 return advance_pc(dc);
5008}
5009
f7ec8155
RH
5010static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
5011 void (*func)(DisasContext *, DisasCompare *, int, int))
5012{
5013 DisasCompare cmp;
5014
2c4f56c9
RH
5015 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
5016 return false;
5017 }
f7ec8155
RH
5018 if (gen_trap_ifnofpu(dc)) {
5019 return true;
5020 }
5021 if (is_128 && gen_trap_float128(dc)) {
5022 return true;
5023 }
5024
5025 gen_op_clear_ieee_excp_and_FTT();
f7ec8155
RH
5026 func(dc, &cmp, a->rd, a->rs2);
5027 return advance_pc(dc);
5028}
5029
5030TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
5031TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
5032TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
5033
5034static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
5035 void (*func)(DisasContext *, DisasCompare *, int, int))
5036{
5037 DisasCompare cmp;
5038
5039 if (gen_trap_ifnofpu(dc)) {
5040 return true;
5041 }
5042 if (is_128 && gen_trap_float128(dc)) {
5043 return true;
5044 }
5045
5046 gen_op_clear_ieee_excp_and_FTT();
5047 gen_compare(&cmp, a->cc, a->cond, dc);
5048 func(dc, &cmp, a->rd, a->rs2);
5049 return advance_pc(dc);
5050}
5051
5052TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
5053TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
5054TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
5055
5056static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
5057 void (*func)(DisasContext *, DisasCompare *, int, int))
5058{
5059 DisasCompare cmp;
5060
5061 if (gen_trap_ifnofpu(dc)) {
5062 return true;
5063 }
5064 if (is_128 && gen_trap_float128(dc)) {
5065 return true;
5066 }
5067
5068 gen_op_clear_ieee_excp_and_FTT();
5069 gen_fcompare(&cmp, a->cc, a->cond);
5070 func(dc, &cmp, a->rd, a->rs2);
5071 return advance_pc(dc);
5072}
5073
5074TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
5075TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
5076TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
5077
40f9ad21
RH
5078static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
5079{
5080 TCGv_i32 src1, src2;
5081
5082 if (avail_32(dc) && a->cc != 0) {
5083 return false;
5084 }
5085 if (gen_trap_ifnofpu(dc)) {
5086 return true;
5087 }
5088
5089 gen_op_clear_ieee_excp_and_FTT();
5090 src1 = gen_load_fpr_F(dc, a->rs1);
5091 src2 = gen_load_fpr_F(dc, a->rs2);
5092 if (e) {
5093 gen_op_fcmpes(a->cc, src1, src2);
5094 } else {
5095 gen_op_fcmps(a->cc, src1, src2);
5096 }
5097 return advance_pc(dc);
5098}
5099
5100TRANS(FCMPs, ALL, do_fcmps, a, false)
5101TRANS(FCMPEs, ALL, do_fcmps, a, true)
5102
5103static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
5104{
5105 TCGv_i64 src1, src2;
5106
5107 if (avail_32(dc) && a->cc != 0) {
5108 return false;
5109 }
5110 if (gen_trap_ifnofpu(dc)) {
5111 return true;
5112 }
5113
5114 gen_op_clear_ieee_excp_and_FTT();
5115 src1 = gen_load_fpr_D(dc, a->rs1);
5116 src2 = gen_load_fpr_D(dc, a->rs2);
5117 if (e) {
5118 gen_op_fcmped(a->cc, src1, src2);
5119 } else {
5120 gen_op_fcmpd(a->cc, src1, src2);
5121 }
5122 return advance_pc(dc);
5123}
5124
5125TRANS(FCMPd, ALL, do_fcmpd, a, false)
5126TRANS(FCMPEd, ALL, do_fcmpd, a, true)
5127
5128static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
5129{
5130 if (avail_32(dc) && a->cc != 0) {
5131 return false;
5132 }
5133 if (gen_trap_ifnofpu(dc)) {
5134 return true;
5135 }
5136 if (gen_trap_float128(dc)) {
5137 return true;
5138 }
5139
5140 gen_op_clear_ieee_excp_and_FTT();
5141 gen_op_load_fpr_QT0(QFPREG(a->rs1));
5142 gen_op_load_fpr_QT1(QFPREG(a->rs2));
5143 if (e) {
5144 gen_op_fcmpeq(a->cc);
5145 } else {
5146 gen_op_fcmpq(a->cc);
5147 }
5148 return advance_pc(dc);
5149}
5150
5151TRANS(FCMPq, ALL, do_fcmpq, a, false)
5152TRANS(FCMPEq, ALL, do_fcmpq, a, true)
5153
6e61bc94 5154static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
7a3f1944 5155{
6e61bc94 5156 DisasContext *dc = container_of(dcbase, DisasContext, base);
b77af26e 5157 CPUSPARCState *env = cpu_env(cs);
6e61bc94 5158 int bound;
af00be49
EC
5159
5160 dc->pc = dc->base.pc_first;
6e61bc94 5161 dc->npc = (target_ulong)dc->base.tb->cs_base;
6e61bc94 5162 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
576e1c4c 5163 dc->def = &env->def;
6e61bc94
EC
5164 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
5165 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
c9b459aa 5166#ifndef CONFIG_USER_ONLY
6e61bc94 5167 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
c9b459aa 5168#endif
a6d567e5 5169#ifdef TARGET_SPARC64
f9c816c0 5170 dc->fprs_dirty = 0;
6e61bc94 5171 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
c9b459aa 5172#ifndef CONFIG_USER_ONLY
6e61bc94 5173 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
c9b459aa 5174#endif
a6d567e5 5175#endif
6e61bc94
EC
5176 /*
5177 * if we reach a page boundary, we stop generation so that the
5178 * PC of a TT_TFAULT exception is always in the right page
5179 */
5180 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
5181 dc->base.max_insns = MIN(dc->base.max_insns, bound);
5182}
cf495bcf 5183
6e61bc94
EC
5184static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
5185{
5186}
190ce7fb 5187
6e61bc94
EC
5188static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
5189{
5190 DisasContext *dc = container_of(dcbase, DisasContext, base);
633c4283 5191 target_ulong npc = dc->npc;
667b8e29 5192
633c4283
RH
5193 if (npc & 3) {
5194 switch (npc) {
5195 case JUMP_PC:
5196 assert(dc->jump_pc[1] == dc->pc + 4);
5197 npc = dc->jump_pc[0] | JUMP_PC;
5198 break;
5199 case DYNAMIC_PC:
5200 case DYNAMIC_PC_LOOKUP:
5201 npc = DYNAMIC_PC;
5202 break;
5203 default:
5204 g_assert_not_reached();
5205 }
6e61bc94 5206 }
633c4283 5207 tcg_gen_insn_start(dc->pc, npc);
6e61bc94 5208}
b933066a 5209
6e61bc94
EC
5210static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
5211{
5212 DisasContext *dc = container_of(dcbase, DisasContext, base);
b77af26e 5213 CPUSPARCState *env = cpu_env(cs);
6e61bc94 5214 unsigned int insn;
0f8a249a 5215
4e116893 5216 insn = translator_ldl(env, &dc->base, dc->pc);
6e61bc94 5217 dc->base.pc_next += 4;
878cc677
RH
5218
5219 if (!decode(dc, insn)) {
ba9c09b4 5220 gen_exception(dc, TT_ILL_INSN);
878cc677 5221 }
e80cfcfc 5222
6e61bc94
EC
5223 if (dc->base.is_jmp == DISAS_NORETURN) {
5224 return;
5225 }
5226 if (dc->pc != dc->base.pc_next) {
5227 dc->base.is_jmp = DISAS_TOO_MANY;
b09b2fd3 5228 }
6e61bc94
EC
5229}
5230
5231static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
5232{
5233 DisasContext *dc = container_of(dcbase, DisasContext, base);
186e7890 5234 DisasDelayException *e, *e_next;
633c4283 5235 bool may_lookup;
6e61bc94 5236
89527e3a
RH
5237 finishing_insn(dc);
5238
46bb0137
MCA
5239 switch (dc->base.is_jmp) {
5240 case DISAS_NEXT:
5241 case DISAS_TOO_MANY:
633c4283 5242 if (((dc->pc | dc->npc) & 3) == 0) {
72cbca10 5243 /* static PC and NPC: we can use direct chaining */
2f5680ee 5244 gen_goto_tb(dc, 0, dc->pc, dc->npc);
633c4283
RH
5245 break;
5246 }
5247
930f1865 5248 may_lookup = true;
633c4283
RH
5249 if (dc->pc & 3) {
5250 switch (dc->pc) {
5251 case DYNAMIC_PC_LOOKUP:
633c4283
RH
5252 break;
5253 case DYNAMIC_PC:
5254 may_lookup = false;
5255 break;
5256 default:
5257 g_assert_not_reached();
b09b2fd3 5258 }
633c4283
RH
5259 } else {
5260 tcg_gen_movi_tl(cpu_pc, dc->pc);
633c4283
RH
5261 }
5262
930f1865
RH
5263 if (dc->npc & 3) {
5264 switch (dc->npc) {
5265 case JUMP_PC:
5266 gen_generic_branch(dc);
5267 break;
5268 case DYNAMIC_PC:
5269 may_lookup = false;
5270 break;
5271 case DYNAMIC_PC_LOOKUP:
5272 break;
5273 default:
5274 g_assert_not_reached();
5275 }
5276 } else {
5277 tcg_gen_movi_tl(cpu_npc, dc->npc);
5278 }
633c4283
RH
5279 if (may_lookup) {
5280 tcg_gen_lookup_and_goto_ptr();
5281 } else {
07ea28b4 5282 tcg_gen_exit_tb(NULL, 0);
72cbca10 5283 }
46bb0137
MCA
5284 break;
5285
5286 case DISAS_NORETURN:
5287 break;
5288
5289 case DISAS_EXIT:
5290 /* Exit TB */
5291 save_state(dc);
5292 tcg_gen_exit_tb(NULL, 0);
5293 break;
5294
5295 default:
5296 g_assert_not_reached();
72cbca10 5297 }
186e7890
RH
5298
5299 for (e = dc->delay_excp_list; e ; e = e_next) {
5300 gen_set_label(e->lab);
5301
5302 tcg_gen_movi_tl(cpu_pc, e->pc);
5303 if (e->npc % 4 == 0) {
5304 tcg_gen_movi_tl(cpu_npc, e->npc);
5305 }
5306 gen_helper_raise_exception(tcg_env, e->excp);
5307
5308 e_next = e->next;
5309 g_free(e);
5310 }
6e61bc94
EC
5311}
5312
8eb806a7
RH
5313static void sparc_tr_disas_log(const DisasContextBase *dcbase,
5314 CPUState *cpu, FILE *logfile)
6e61bc94 5315{
8eb806a7
RH
5316 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
5317 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
6e61bc94
EC
5318}
5319
5320static const TranslatorOps sparc_tr_ops = {
5321 .init_disas_context = sparc_tr_init_disas_context,
5322 .tb_start = sparc_tr_tb_start,
5323 .insn_start = sparc_tr_insn_start,
6e61bc94
EC
5324 .translate_insn = sparc_tr_translate_insn,
5325 .tb_stop = sparc_tr_tb_stop,
5326 .disas_log = sparc_tr_disas_log,
5327};
5328
597f9b2d 5329void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
32f0c394 5330 vaddr pc, void *host_pc)
6e61bc94
EC
5331{
5332 DisasContext dc = {};
5333
306c8721 5334 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
7a3f1944
FB
5335}
5336
55c3ceef 5337void sparc_tcg_init(void)
e80cfcfc 5338{
d2dc4069 5339 static const char gregnames[32][4] = {
0ea63844 5340 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
d2dc4069
RH
5341 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5342 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5343 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
f5069b26 5344 };
0ea63844 5345 static const char fregnames[32][4] = {
30038fd8
RH
5346 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5347 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5348 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5349 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5350 };
aaed909a 5351
0ea63844
RH
5352 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5353#ifdef TARGET_SPARC64
5354 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
2a1905c7
RH
5355 { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
5356 { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
1a2fb1c0 5357#endif
2a1905c7
RH
5358 { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
5359 { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
5360 { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
5361 { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
0ea63844 5362 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
0ea63844
RH
5363 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
5364 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5365 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5366 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
0ea63844 5367 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
0ea63844
RH
5368 };
5369
5370 unsigned int i;
5371
ad75a51e 5372 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
0ea63844
RH
5373 offsetof(CPUSPARCState, regwptr),
5374 "regwptr");
5375
0ea63844 5376 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
ad75a51e 5377 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
0ea63844
RH
5378 }
5379
f764718d 5380 cpu_regs[0] = NULL;
0ea63844 5381 for (i = 1; i < 8; ++i) {
ad75a51e 5382 cpu_regs[i] = tcg_global_mem_new(tcg_env,
d2dc4069
RH
5383 offsetof(CPUSPARCState, gregs[i]),
5384 gregnames[i]);
5385 }
5386
5387 for (i = 8; i < 32; ++i) {
5388 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5389 (i - 8) * sizeof(target_ulong),
5390 gregnames[i]);
0ea63844
RH
5391 }
5392
5393 for (i = 0; i < TARGET_DPREGS; i++) {
ad75a51e 5394 cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
0ea63844
RH
5395 offsetof(CPUSPARCState, fpr[i]),
5396 fregnames[i]);
1a2fb1c0 5397 }
b597eedc
RH
5398
5399#ifdef TARGET_SPARC64
5400 cpu_fprs = tcg_global_mem_new_i32(tcg_env,
5401 offsetof(CPUSPARCState, fprs), "fprs");
5402#endif
658138bc 5403}
d2856f1a 5404
f36aaa53
RH
5405void sparc_restore_state_to_opc(CPUState *cs,
5406 const TranslationBlock *tb,
5407 const uint64_t *data)
d2856f1a 5408{
f36aaa53
RH
5409 SPARCCPU *cpu = SPARC_CPU(cs);
5410 CPUSPARCState *env = &cpu->env;
bad729e2
RH
5411 target_ulong pc = data[0];
5412 target_ulong npc = data[1];
5413
5414 env->pc = pc;
6c42444f 5415 if (npc == DYNAMIC_PC) {
d2856f1a 5416 /* dynamic NPC: already stored */
6c42444f 5417 } else if (npc & JUMP_PC) {
d7da2a10
BS
5418 /* jump PC: use 'cond' and the jump targets of the translation */
5419 if (env->cond) {
6c42444f 5420 env->npc = npc & ~3;
d7da2a10 5421 } else {
6c42444f 5422 env->npc = pc + 4;
d7da2a10 5423 }
d2856f1a
AJ
5424 } else {
5425 env->npc = npc;
5426 }
5427}