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