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