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