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