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