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