]> git.ipfire.org Git - thirdparty/qemu.git/blame - target/sparc/translate.c
target/sparc: Move simple integer load/store 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 */
7ec1e5ea
RH
1903typedef enum {
1904 GET_ASI_HELPER,
1905 GET_ASI_EXCP,
f0913be0 1906 GET_ASI_DIRECT,
e4dc0052 1907 GET_ASI_DTWINX,
ca5ce572
RH
1908 GET_ASI_BLOCK,
1909 GET_ASI_SHORT,
34810610
RH
1910 GET_ASI_BCOPY,
1911 GET_ASI_BFILL,
7ec1e5ea
RH
1912} ASIType;
1913
1914typedef struct {
1915 ASIType type;
a6d567e5 1916 int asi;
f0913be0 1917 int mem_idx;
14776ab5 1918 MemOp memop;
7ec1e5ea 1919} DisasASI;
1a2fb1c0 1920
811cc0b0
RH
1921/*
1922 * Build DisasASI.
1923 * For asi == -1, treat as non-asi.
1924 * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1925 */
1926static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
7ec1e5ea 1927{
7ec1e5ea 1928 ASIType type = GET_ASI_HELPER;
f0913be0 1929 int mem_idx = dc->mem_idx;
7ec1e5ea 1930
811cc0b0
RH
1931 if (asi == -1) {
1932 /* Artificial "non-asi" case. */
1933 type = GET_ASI_DIRECT;
1934 goto done;
1935 }
1936
7ec1e5ea
RH
1937#ifndef TARGET_SPARC64
1938 /* Before v9, all asis are immediate and privileged. */
811cc0b0 1939 if (asi < 0) {
22e70060 1940 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
1941 type = GET_ASI_EXCP;
1942 } else if (supervisor(dc)
1943 /* Note that LEON accepts ASI_USERDATA in user mode, for
1944 use with CASA. Also note that previous versions of
0cc1f4bf
RH
1945 QEMU allowed (and old versions of gcc emitted) ASI_P
1946 for LEON, which is incorrect. */
1947 || (asi == ASI_USERDATA
7ec1e5ea 1948 && (dc->def->features & CPU_FEATURE_CASA))) {
f0913be0
RH
1949 switch (asi) {
1950 case ASI_USERDATA: /* User data access */
1951 mem_idx = MMU_USER_IDX;
1952 type = GET_ASI_DIRECT;
1953 break;
1954 case ASI_KERNELDATA: /* Supervisor data access */
1955 mem_idx = MMU_KERNEL_IDX;
1956 type = GET_ASI_DIRECT;
1957 break;
7f87c905
RH
1958 case ASI_M_BYPASS: /* MMU passthrough */
1959 case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1960 mem_idx = MMU_PHYS_IDX;
1961 type = GET_ASI_DIRECT;
1962 break;
34810610
RH
1963 case ASI_M_BCOPY: /* Block copy, sta access */
1964 mem_idx = MMU_KERNEL_IDX;
1965 type = GET_ASI_BCOPY;
1966 break;
1967 case ASI_M_BFILL: /* Block fill, stda access */
1968 mem_idx = MMU_KERNEL_IDX;
1969 type = GET_ASI_BFILL;
1970 break;
f0913be0 1971 }
6e10f37c
KF
1972
1973 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
1974 * permissions check in get_physical_address(..).
1975 */
1976 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1a2fb1c0 1977 } else {
7ec1e5ea
RH
1978 gen_exception(dc, TT_PRIV_INSN);
1979 type = GET_ASI_EXCP;
1980 }
1981#else
811cc0b0 1982 if (asi < 0) {
7ec1e5ea 1983 asi = dc->asi;
1a2fb1c0 1984 }
f0913be0
RH
1985 /* With v9, all asis below 0x80 are privileged. */
1986 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1987 down that bit into DisasContext. For the moment that's ok,
1988 since the direct implementations below doesn't have any ASIs
1989 in the restricted [0x30, 0x7f] range, and the check will be
1990 done properly in the helper. */
1991 if (!supervisor(dc) && asi < 0x80) {
1992 gen_exception(dc, TT_PRIV_ACT);
1993 type = GET_ASI_EXCP;
1994 } else {
1995 switch (asi) {
7f87c905
RH
1996 case ASI_REAL: /* Bypass */
1997 case ASI_REAL_IO: /* Bypass, non-cacheable */
1998 case ASI_REAL_L: /* Bypass LE */
1999 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
2000 case ASI_TWINX_REAL: /* Real address, twinx */
2001 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
34a6e13d
RH
2002 case ASI_QUAD_LDD_PHYS:
2003 case ASI_QUAD_LDD_PHYS_L:
7f87c905
RH
2004 mem_idx = MMU_PHYS_IDX;
2005 break;
f0913be0
RH
2006 case ASI_N: /* Nucleus */
2007 case ASI_NL: /* Nucleus LE */
e4dc0052
RH
2008 case ASI_TWINX_N:
2009 case ASI_TWINX_NL:
34a6e13d
RH
2010 case ASI_NUCLEUS_QUAD_LDD:
2011 case ASI_NUCLEUS_QUAD_LDD_L:
9a10756d 2012 if (hypervisor(dc)) {
84f8f587 2013 mem_idx = MMU_PHYS_IDX;
9a10756d
AT
2014 } else {
2015 mem_idx = MMU_NUCLEUS_IDX;
2016 }
f0913be0
RH
2017 break;
2018 case ASI_AIUP: /* As if user primary */
2019 case ASI_AIUPL: /* As if user primary LE */
e4dc0052
RH
2020 case ASI_TWINX_AIUP:
2021 case ASI_TWINX_AIUP_L:
ca5ce572
RH
2022 case ASI_BLK_AIUP_4V:
2023 case ASI_BLK_AIUP_L_4V:
2024 case ASI_BLK_AIUP:
2025 case ASI_BLK_AIUPL:
f0913be0
RH
2026 mem_idx = MMU_USER_IDX;
2027 break;
2028 case ASI_AIUS: /* As if user secondary */
2029 case ASI_AIUSL: /* As if user secondary LE */
e4dc0052
RH
2030 case ASI_TWINX_AIUS:
2031 case ASI_TWINX_AIUS_L:
ca5ce572
RH
2032 case ASI_BLK_AIUS_4V:
2033 case ASI_BLK_AIUS_L_4V:
2034 case ASI_BLK_AIUS:
2035 case ASI_BLK_AIUSL:
f0913be0
RH
2036 mem_idx = MMU_USER_SECONDARY_IDX;
2037 break;
2038 case ASI_S: /* Secondary */
2039 case ASI_SL: /* Secondary LE */
e4dc0052
RH
2040 case ASI_TWINX_S:
2041 case ASI_TWINX_SL:
ca5ce572
RH
2042 case ASI_BLK_COMMIT_S:
2043 case ASI_BLK_S:
2044 case ASI_BLK_SL:
2045 case ASI_FL8_S:
2046 case ASI_FL8_SL:
2047 case ASI_FL16_S:
2048 case ASI_FL16_SL:
f0913be0
RH
2049 if (mem_idx == MMU_USER_IDX) {
2050 mem_idx = MMU_USER_SECONDARY_IDX;
2051 } else if (mem_idx == MMU_KERNEL_IDX) {
2052 mem_idx = MMU_KERNEL_SECONDARY_IDX;
2053 }
2054 break;
2055 case ASI_P: /* Primary */
2056 case ASI_PL: /* Primary LE */
e4dc0052
RH
2057 case ASI_TWINX_P:
2058 case ASI_TWINX_PL:
ca5ce572
RH
2059 case ASI_BLK_COMMIT_P:
2060 case ASI_BLK_P:
2061 case ASI_BLK_PL:
2062 case ASI_FL8_P:
2063 case ASI_FL8_PL:
2064 case ASI_FL16_P:
2065 case ASI_FL16_PL:
f0913be0
RH
2066 break;
2067 }
2068 switch (asi) {
7f87c905
RH
2069 case ASI_REAL:
2070 case ASI_REAL_IO:
2071 case ASI_REAL_L:
2072 case ASI_REAL_IO_L:
f0913be0
RH
2073 case ASI_N:
2074 case ASI_NL:
2075 case ASI_AIUP:
2076 case ASI_AIUPL:
2077 case ASI_AIUS:
2078 case ASI_AIUSL:
2079 case ASI_S:
2080 case ASI_SL:
2081 case ASI_P:
2082 case ASI_PL:
2083 type = GET_ASI_DIRECT;
2084 break;
7f87c905
RH
2085 case ASI_TWINX_REAL:
2086 case ASI_TWINX_REAL_L:
e4dc0052
RH
2087 case ASI_TWINX_N:
2088 case ASI_TWINX_NL:
2089 case ASI_TWINX_AIUP:
2090 case ASI_TWINX_AIUP_L:
2091 case ASI_TWINX_AIUS:
2092 case ASI_TWINX_AIUS_L:
2093 case ASI_TWINX_P:
2094 case ASI_TWINX_PL:
2095 case ASI_TWINX_S:
2096 case ASI_TWINX_SL:
34a6e13d
RH
2097 case ASI_QUAD_LDD_PHYS:
2098 case ASI_QUAD_LDD_PHYS_L:
2099 case ASI_NUCLEUS_QUAD_LDD:
2100 case ASI_NUCLEUS_QUAD_LDD_L:
e4dc0052
RH
2101 type = GET_ASI_DTWINX;
2102 break;
ca5ce572
RH
2103 case ASI_BLK_COMMIT_P:
2104 case ASI_BLK_COMMIT_S:
2105 case ASI_BLK_AIUP_4V:
2106 case ASI_BLK_AIUP_L_4V:
2107 case ASI_BLK_AIUP:
2108 case ASI_BLK_AIUPL:
2109 case ASI_BLK_AIUS_4V:
2110 case ASI_BLK_AIUS_L_4V:
2111 case ASI_BLK_AIUS:
2112 case ASI_BLK_AIUSL:
2113 case ASI_BLK_S:
2114 case ASI_BLK_SL:
2115 case ASI_BLK_P:
2116 case ASI_BLK_PL:
2117 type = GET_ASI_BLOCK;
2118 break;
2119 case ASI_FL8_S:
2120 case ASI_FL8_SL:
2121 case ASI_FL8_P:
2122 case ASI_FL8_PL:
2123 memop = MO_UB;
2124 type = GET_ASI_SHORT;
2125 break;
2126 case ASI_FL16_S:
2127 case ASI_FL16_SL:
2128 case ASI_FL16_P:
2129 case ASI_FL16_PL:
2130 memop = MO_TEUW;
2131 type = GET_ASI_SHORT;
2132 break;
f0913be0
RH
2133 }
2134 /* The little-endian asis all have bit 3 set. */
2135 if (asi & 8) {
2136 memop ^= MO_BSWAP;
2137 }
2138 }
7ec1e5ea
RH
2139#endif
2140
811cc0b0 2141 done:
f0913be0 2142 return (DisasASI){ type, asi, mem_idx, memop };
0425bee5
BS
2143}
2144
811cc0b0
RH
2145static DisasASI get_asi(DisasContext *dc, int insn, MemOp memop)
2146{
2147 int asi = IS_IMM ? -2 : GET_FIELD(insn, 19, 26);
2148 return resolve_asi(dc, asi, memop);
2149}
2150
a76779ee
RH
2151#if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2152static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
2153 TCGv_i32 asi, TCGv_i32 mop)
2154{
2155 g_assert_not_reached();
2156}
2157
2158static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
2159 TCGv_i32 asi, TCGv_i32 mop)
2160{
2161 g_assert_not_reached();
2162}
2163#endif
2164
c03a0fd1 2165static void gen_ld_asi0(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
0425bee5 2166{
c03a0fd1 2167 switch (da->type) {
7ec1e5ea
RH
2168 case GET_ASI_EXCP:
2169 break;
e4dc0052
RH
2170 case GET_ASI_DTWINX: /* Reserved for ldda. */
2171 gen_exception(dc, TT_ILL_INSN);
2172 break;
f0913be0 2173 case GET_ASI_DIRECT:
c03a0fd1 2174 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
f0913be0 2175 break;
7ec1e5ea
RH
2176 default:
2177 {
c03a0fd1
RH
2178 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2179 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
7ec1e5ea
RH
2180
2181 save_state(dc);
22e70060 2182#ifdef TARGET_SPARC64
ad75a51e 2183 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
22e70060 2184#else
7ec1e5ea
RH
2185 {
2186 TCGv_i64 t64 = tcg_temp_new_i64();
ad75a51e 2187 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
7ec1e5ea 2188 tcg_gen_trunc_i64_tl(dst, t64);
7ec1e5ea 2189 }
22e70060 2190#endif
7ec1e5ea
RH
2191 }
2192 break;
2193 }
1a2fb1c0
BS
2194}
2195
a76779ee 2196static void __attribute__((unused))
c03a0fd1 2197gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn, MemOp memop)
1a2fb1c0 2198{
f0913be0 2199 DisasASI da = get_asi(dc, insn, memop);
1a2fb1c0 2200
c03a0fd1
RH
2201 gen_address_mask(dc, addr);
2202 gen_ld_asi0(dc, &da, dst, addr);
2203}
2204
2205static void gen_st_asi0(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
2206{
2207 switch (da->type) {
7ec1e5ea
RH
2208 case GET_ASI_EXCP:
2209 break;
c03a0fd1 2210
e4dc0052 2211 case GET_ASI_DTWINX: /* Reserved for stda. */
c03a0fd1
RH
2212 if (TARGET_LONG_BITS == 32) {
2213 gen_exception(dc, TT_ILL_INSN);
2214 break;
2215 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
3390537b
AT
2216 /* Pre OpenSPARC CPUs don't have these */
2217 gen_exception(dc, TT_ILL_INSN);
c03a0fd1 2218 break;
3390537b 2219 }
c03a0fd1 2220 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
fc0cd867 2221 /* fall through */
c03a0fd1 2222
f0913be0 2223 case GET_ASI_DIRECT:
c03a0fd1 2224 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
f0913be0 2225 break;
c03a0fd1 2226
34810610 2227 case GET_ASI_BCOPY:
c03a0fd1 2228 assert(TARGET_LONG_BITS == 32);
34810610
RH
2229 /* Copy 32 bytes from the address in SRC to ADDR. */
2230 /* ??? The original qemu code suggests 4-byte alignment, dropping
2231 the low bits, but the only place I can see this used is in the
2232 Linux kernel with 32 byte alignment, which would make more sense
2233 as a cacheline-style operation. */
2234 {
2235 TCGv saddr = tcg_temp_new();
2236 TCGv daddr = tcg_temp_new();
00ab7e61 2237 TCGv four = tcg_constant_tl(4);
34810610
RH
2238 TCGv_i32 tmp = tcg_temp_new_i32();
2239 int i;
2240
2241 tcg_gen_andi_tl(saddr, src, -4);
2242 tcg_gen_andi_tl(daddr, addr, -4);
2243 for (i = 0; i < 32; i += 4) {
2244 /* Since the loads and stores are paired, allow the
2245 copy to happen in the host endianness. */
c03a0fd1
RH
2246 tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL);
2247 tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL);
34810610
RH
2248 tcg_gen_add_tl(saddr, saddr, four);
2249 tcg_gen_add_tl(daddr, daddr, four);
2250 }
34810610
RH
2251 }
2252 break;
c03a0fd1 2253
7ec1e5ea
RH
2254 default:
2255 {
c03a0fd1
RH
2256 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2257 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
7ec1e5ea
RH
2258
2259 save_state(dc);
22e70060 2260#ifdef TARGET_SPARC64
ad75a51e 2261 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
22e70060 2262#else
7ec1e5ea
RH
2263 {
2264 TCGv_i64 t64 = tcg_temp_new_i64();
2265 tcg_gen_extu_tl_i64(t64, src);
ad75a51e 2266 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
7ec1e5ea 2267 }
22e70060 2268#endif
7ec1e5ea
RH
2269
2270 /* A write to a TLB register may alter page maps. End the TB. */
2271 dc->npc = DYNAMIC_PC;
2272 }
2273 break;
2274 }
1a2fb1c0
BS
2275}
2276
a76779ee 2277static void __attribute__((unused))
c03a0fd1 2278gen_st_asi(DisasContext *dc, TCGv src, TCGv addr, int insn, MemOp memop)
1a2fb1c0 2279{
c03a0fd1 2280 DisasASI da = get_asi(dc, insn, memop);
22e70060 2281
c03a0fd1
RH
2282 gen_address_mask(dc, addr);
2283 gen_st_asi0(dc, &da, src, addr);
2284}
2285
2286static void gen_swap_asi0(DisasContext *dc, DisasASI *da,
2287 TCGv dst, TCGv src, TCGv addr)
2288{
2289 switch (da->type) {
7ec1e5ea
RH
2290 case GET_ASI_EXCP:
2291 break;
4fb554bc 2292 case GET_ASI_DIRECT:
c03a0fd1 2293 gen_swap(dc, dst, src, addr, da->mem_idx, da->memop);
4fb554bc 2294 break;
7ec1e5ea 2295 default:
4fb554bc
RH
2296 /* ??? Should be DAE_invalid_asi. */
2297 gen_exception(dc, TT_DATA_ACCESS);
7ec1e5ea
RH
2298 break;
2299 }
1a2fb1c0
BS
2300}
2301
a76779ee 2302static void __attribute__((unused))
c03a0fd1 2303gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src, TCGv addr, int insn)
22e70060 2304{
f0913be0 2305 DisasASI da = get_asi(dc, insn, MO_TEUL);
22e70060 2306
c03a0fd1
RH
2307 gen_address_mask(dc, addr);
2308 gen_swap_asi0(dc, &da, dst, src, addr);
2309}
2310
2311static void gen_cas_asi0(DisasContext *dc, DisasASI *da,
2312 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
2313{
2314 switch (da->type) {
7268adeb 2315 case GET_ASI_EXCP:
7ec1e5ea 2316 return;
7268adeb 2317 case GET_ASI_DIRECT:
c03a0fd1
RH
2318 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
2319 da->mem_idx, da->memop | MO_ALIGN);
7268adeb
RH
2320 break;
2321 default:
2322 /* ??? Should be DAE_invalid_asi. */
2323 gen_exception(dc, TT_DATA_ACCESS);
2324 break;
7ec1e5ea 2325 }
22e70060
RH
2326}
2327
a76779ee 2328static void __attribute__((unused))
c03a0fd1 2329gen_cas_asi(DisasContext *dc, TCGv addr, TCGv cmpv, int insn, int rd)
22e70060 2330{
c03a0fd1
RH
2331 DisasASI da = get_asi(dc, insn, MO_TEUL);
2332 TCGv oldv = gen_dest_gpr(dc, rd);
2333 TCGv newv = gen_load_gpr(dc, rd);
22e70060 2334
c03a0fd1
RH
2335 gen_address_mask(dc, addr);
2336 gen_cas_asi0(dc, &da, oldv, newv, cmpv, addr);
2337 gen_store_gpr(dc, rd, oldv);
2338}
2339
2340static void __attribute__((unused))
2341gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv, int insn, int rd)
2342{
2343 DisasASI da = get_asi(dc, insn, MO_TEUQ);
2344 TCGv oldv = gen_dest_gpr(dc, rd);
2345 TCGv newv = gen_load_gpr(dc, rd);
2346
2347 gen_address_mask(dc, addr);
2348 gen_cas_asi0(dc, &da, oldv, newv, cmpv, addr);
2349 gen_store_gpr(dc, rd, oldv);
2350}
2351
2352static void gen_ldstub_asi0(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
2353{
2354 switch (da->type) {
7ec1e5ea
RH
2355 case GET_ASI_EXCP:
2356 break;
fbb4bbb6 2357 case GET_ASI_DIRECT:
c03a0fd1 2358 gen_ldstub(dc, dst, addr, da->mem_idx);
fbb4bbb6 2359 break;
7ec1e5ea 2360 default:
3db010c3
RH
2361 /* ??? In theory, this should be raise DAE_invalid_asi.
2362 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
af00be49 2363 if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
ad75a51e 2364 gen_helper_exit_atomic(tcg_env);
3db010c3 2365 } else {
c03a0fd1 2366 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
00ab7e61 2367 TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
3db010c3
RH
2368 TCGv_i64 s64, t64;
2369
2370 save_state(dc);
2371 t64 = tcg_temp_new_i64();
ad75a51e 2372 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
3db010c3 2373
00ab7e61 2374 s64 = tcg_constant_i64(0xff);
ad75a51e 2375 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
3db010c3
RH
2376
2377 tcg_gen_trunc_i64_tl(dst, t64);
3db010c3
RH
2378
2379 /* End the TB. */
2380 dc->npc = DYNAMIC_PC;
2381 }
7ec1e5ea
RH
2382 break;
2383 }
22e70060 2384}
22e70060 2385
c03a0fd1
RH
2386static void __attribute__((unused))
2387gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
2388{
2389 DisasASI da = get_asi(dc, insn, MO_UB);
2390
2391 gen_address_mask(dc, addr);
2392 gen_ldstub_asi0(dc, &da, dst, addr);
2393}
2394
a76779ee
RH
2395static void __attribute__((unused))
2396gen_ldf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd)
1a2fb1c0 2397{
fc313c64 2398 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ));
7705091c 2399 TCGv_i32 d32;
cb21b4da 2400 TCGv_i64 d64;
1a2fb1c0 2401
7ec1e5ea
RH
2402 switch (da.type) {
2403 case GET_ASI_EXCP:
2404 break;
7705091c
RH
2405
2406 case GET_ASI_DIRECT:
2407 gen_address_mask(dc, addr);
2408 switch (size) {
2409 case 4:
2410 d32 = gen_dest_fpr_F(dc);
316b6783 2411 tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN);
7705091c
RH
2412 gen_store_fpr_F(dc, rd, d32);
2413 break;
2414 case 8:
cb21b4da
RH
2415 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2416 da.memop | MO_ALIGN_4);
7705091c
RH
2417 break;
2418 case 16:
cb21b4da
RH
2419 d64 = tcg_temp_new_i64();
2420 tcg_gen_qemu_ld_i64(d64, addr, da.mem_idx, da.memop | MO_ALIGN_4);
7705091c 2421 tcg_gen_addi_tl(addr, addr, 8);
cb21b4da
RH
2422 tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx,
2423 da.memop | MO_ALIGN_4);
2424 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
7705091c
RH
2425 break;
2426 default:
2427 g_assert_not_reached();
2428 }
2429 break;
2430
ca5ce572
RH
2431 case GET_ASI_BLOCK:
2432 /* Valid for lddfa on aligned registers only. */
2433 if (size == 8 && (rd & 7) == 0) {
14776ab5 2434 MemOp memop;
ca5ce572
RH
2435 TCGv eight;
2436 int i;
2437
ca5ce572
RH
2438 gen_address_mask(dc, addr);
2439
80883227
RH
2440 /* The first operation checks required alignment. */
2441 memop = da.memop | MO_ALIGN_64;
00ab7e61 2442 eight = tcg_constant_tl(8);
ca5ce572
RH
2443 for (i = 0; ; ++i) {
2444 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr,
80883227 2445 da.mem_idx, memop);
ca5ce572
RH
2446 if (i == 7) {
2447 break;
2448 }
2449 tcg_gen_add_tl(addr, addr, eight);
80883227 2450 memop = da.memop;
ca5ce572 2451 }
ca5ce572
RH
2452 } else {
2453 gen_exception(dc, TT_ILL_INSN);
2454 }
2455 break;
2456
2457 case GET_ASI_SHORT:
2458 /* Valid for lddfa only. */
2459 if (size == 8) {
2460 gen_address_mask(dc, addr);
316b6783
RH
2461 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2462 da.memop | MO_ALIGN);
ca5ce572
RH
2463 } else {
2464 gen_exception(dc, TT_ILL_INSN);
2465 }
2466 break;
2467
7ec1e5ea
RH
2468 default:
2469 {
00ab7e61 2470 TCGv_i32 r_asi = tcg_constant_i32(da.asi);
316b6783 2471 TCGv_i32 r_mop = tcg_constant_i32(da.memop | MO_ALIGN);
7ec1e5ea
RH
2472
2473 save_state(dc);
f2fe396f
RH
2474 /* According to the table in the UA2011 manual, the only
2475 other asis that are valid for ldfa/lddfa/ldqfa are
2476 the NO_FAULT asis. We still need a helper for these,
2477 but we can just use the integer asi helper for them. */
2478 switch (size) {
2479 case 4:
cb21b4da 2480 d64 = tcg_temp_new_i64();
ad75a51e 2481 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
cb21b4da
RH
2482 d32 = gen_dest_fpr_F(dc);
2483 tcg_gen_extrl_i64_i32(d32, d64);
cb21b4da 2484 gen_store_fpr_F(dc, rd, d32);
f2fe396f
RH
2485 break;
2486 case 8:
ad75a51e 2487 gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr, r_asi, r_mop);
f2fe396f
RH
2488 break;
2489 case 16:
cb21b4da 2490 d64 = tcg_temp_new_i64();
ad75a51e 2491 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
f2fe396f 2492 tcg_gen_addi_tl(addr, addr, 8);
ad75a51e 2493 gen_helper_ld_asi(cpu_fpr[rd/2+1], tcg_env, addr, r_asi, r_mop);
cb21b4da 2494 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
f2fe396f
RH
2495 break;
2496 default:
2497 g_assert_not_reached();
2498 }
7ec1e5ea
RH
2499 }
2500 break;
2501 }
1a2fb1c0
BS
2502}
2503
a76779ee
RH
2504static void __attribute__((unused))
2505gen_stf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd)
1a2fb1c0 2506{
fc313c64 2507 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ));
7705091c 2508 TCGv_i32 d32;
1a2fb1c0 2509
7ec1e5ea
RH
2510 switch (da.type) {
2511 case GET_ASI_EXCP:
2512 break;
7705091c
RH
2513
2514 case GET_ASI_DIRECT:
2515 gen_address_mask(dc, addr);
2516 switch (size) {
2517 case 4:
2518 d32 = gen_load_fpr_F(dc, rd);
316b6783 2519 tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN);
7705091c
RH
2520 break;
2521 case 8:
cb21b4da
RH
2522 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2523 da.memop | MO_ALIGN_4);
7705091c
RH
2524 break;
2525 case 16:
cb21b4da
RH
2526 /* Only 4-byte alignment required. However, it is legal for the
2527 cpu to signal the alignment fault, and the OS trap handler is
2528 required to fix it up. Requiring 16-byte alignment here avoids
2529 having to probe the second page before performing the first
2530 write. */
f939ffe5
RH
2531 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2532 da.memop | MO_ALIGN_16);
7705091c
RH
2533 tcg_gen_addi_tl(addr, addr, 8);
2534 tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
2535 break;
2536 default:
2537 g_assert_not_reached();
2538 }
2539 break;
2540
ca5ce572
RH
2541 case GET_ASI_BLOCK:
2542 /* Valid for stdfa on aligned registers only. */
2543 if (size == 8 && (rd & 7) == 0) {
14776ab5 2544 MemOp memop;
ca5ce572
RH
2545 TCGv eight;
2546 int i;
2547
ca5ce572
RH
2548 gen_address_mask(dc, addr);
2549
80883227
RH
2550 /* The first operation checks required alignment. */
2551 memop = da.memop | MO_ALIGN_64;
00ab7e61 2552 eight = tcg_constant_tl(8);
ca5ce572
RH
2553 for (i = 0; ; ++i) {
2554 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr,
80883227 2555 da.mem_idx, memop);
ca5ce572
RH
2556 if (i == 7) {
2557 break;
2558 }
2559 tcg_gen_add_tl(addr, addr, eight);
80883227 2560 memop = da.memop;
ca5ce572 2561 }
ca5ce572
RH
2562 } else {
2563 gen_exception(dc, TT_ILL_INSN);
2564 }
2565 break;
2566
2567 case GET_ASI_SHORT:
2568 /* Valid for stdfa only. */
2569 if (size == 8) {
2570 gen_address_mask(dc, addr);
316b6783
RH
2571 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2572 da.memop | MO_ALIGN);
ca5ce572
RH
2573 } else {
2574 gen_exception(dc, TT_ILL_INSN);
2575 }
2576 break;
2577
7ec1e5ea 2578 default:
f2fe396f
RH
2579 /* According to the table in the UA2011 manual, the only
2580 other asis that are valid for ldfa/lddfa/ldqfa are
2581 the PST* asis, which aren't currently handled. */
2582 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
2583 break;
2584 }
1a2fb1c0
BS
2585}
2586
c03a0fd1 2587static void gen_ldda_asi0(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1a2fb1c0 2588{
a76779ee
RH
2589 TCGv hi = gen_dest_gpr(dc, rd);
2590 TCGv lo = gen_dest_gpr(dc, rd + 1);
1a2fb1c0 2591
c03a0fd1 2592 switch (da->type) {
7ec1e5ea 2593 case GET_ASI_EXCP:
e4dc0052
RH
2594 return;
2595
2596 case GET_ASI_DTWINX:
ebbbec92
RH
2597#ifdef TARGET_SPARC64
2598 {
2599 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2600 TCGv_i128 t = tcg_temp_new_i128();
2601
2602 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
2603 /*
2604 * Note that LE twinx acts as if each 64-bit register result is
2605 * byte swapped. We perform one 128-bit LE load, so must swap
2606 * the order of the writebacks.
2607 */
2608 if ((mop & MO_BSWAP) == MO_TE) {
2609 tcg_gen_extr_i128_i64(lo, hi, t);
2610 } else {
2611 tcg_gen_extr_i128_i64(hi, lo, t);
2612 }
2613 }
7ec1e5ea 2614 break;
ebbbec92
RH
2615#else
2616 g_assert_not_reached();
2617#endif
e4dc0052
RH
2618
2619 case GET_ASI_DIRECT:
2620 {
2621 TCGv_i64 tmp = tcg_temp_new_i64();
2622
c03a0fd1 2623 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
e4dc0052
RH
2624
2625 /* Note that LE ldda acts as if each 32-bit register
2626 result is byte swapped. Having just performed one
2627 64-bit bswap, we need now to swap the writebacks. */
c03a0fd1 2628 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2629 tcg_gen_extr_i64_tl(lo, hi, tmp);
e4dc0052 2630 } else {
a76779ee 2631 tcg_gen_extr_i64_tl(hi, lo, tmp);
e4dc0052 2632 }
e4dc0052
RH
2633 }
2634 break;
2635
7ec1e5ea 2636 default:
918d9a2c
RH
2637 /* ??? In theory we've handled all of the ASIs that are valid
2638 for ldda, and this should raise DAE_invalid_asi. However,
2639 real hardware allows others. This can be seen with e.g.
2640 FreeBSD 10.3 wrt ASI_IC_TAG. */
7ec1e5ea 2641 {
c03a0fd1
RH
2642 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2643 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
918d9a2c 2644 TCGv_i64 tmp = tcg_temp_new_i64();
7ec1e5ea
RH
2645
2646 save_state(dc);
ad75a51e 2647 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
3f4288eb 2648
918d9a2c 2649 /* See above. */
c03a0fd1 2650 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2651 tcg_gen_extr_i64_tl(lo, hi, tmp);
918d9a2c 2652 } else {
a76779ee 2653 tcg_gen_extr_i64_tl(hi, lo, tmp);
918d9a2c 2654 }
7ec1e5ea
RH
2655 }
2656 break;
2657 }
e4dc0052
RH
2658
2659 gen_store_gpr(dc, rd, hi);
2660 gen_store_gpr(dc, rd + 1, lo);
0425bee5
BS
2661}
2662
a76779ee 2663static void __attribute__((unused))
c03a0fd1 2664gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
0425bee5 2665{
fc313c64 2666 DisasASI da = get_asi(dc, insn, MO_TEUQ);
c03a0fd1
RH
2667
2668 gen_address_mask(dc, addr);
2669 gen_ldda_asi0(dc, &da, addr, rd);
2670}
2671
2672static void gen_stda_asi0(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2673{
2674 TCGv hi = gen_load_gpr(dc, rd);
c7785e16 2675 TCGv lo = gen_load_gpr(dc, rd + 1);
a7ec4229 2676
c03a0fd1 2677 switch (da->type) {
7ec1e5ea
RH
2678 case GET_ASI_EXCP:
2679 break;
e4dc0052
RH
2680
2681 case GET_ASI_DTWINX:
ebbbec92
RH
2682#ifdef TARGET_SPARC64
2683 {
2684 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2685 TCGv_i128 t = tcg_temp_new_i128();
2686
2687 /*
2688 * Note that LE twinx acts as if each 64-bit register result is
2689 * byte swapped. We perform one 128-bit LE store, so must swap
2690 * the order of the construction.
2691 */
2692 if ((mop & MO_BSWAP) == MO_TE) {
2693 tcg_gen_concat_i64_i128(t, lo, hi);
2694 } else {
2695 tcg_gen_concat_i64_i128(t, hi, lo);
2696 }
2697 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
2698 }
e4dc0052 2699 break;
ebbbec92
RH
2700#else
2701 g_assert_not_reached();
2702#endif
e4dc0052
RH
2703
2704 case GET_ASI_DIRECT:
2705 {
2706 TCGv_i64 t64 = tcg_temp_new_i64();
2707
2708 /* Note that LE stda acts as if each 32-bit register result is
2709 byte swapped. We will perform one 64-bit LE store, so now
2710 we must swap the order of the construction. */
c03a0fd1 2711 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2712 tcg_gen_concat_tl_i64(t64, lo, hi);
e4dc0052 2713 } else {
a76779ee 2714 tcg_gen_concat_tl_i64(t64, hi, lo);
e4dc0052 2715 }
c03a0fd1 2716 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
e4dc0052
RH
2717 }
2718 break;
2719
a76779ee
RH
2720 case GET_ASI_BFILL:
2721 assert(TARGET_LONG_BITS == 32);
2722 /* Store 32 bytes of T64 to ADDR. */
2723 /* ??? The original qemu code suggests 8-byte alignment, dropping
2724 the low bits, but the only place I can see this used is in the
2725 Linux kernel with 32 byte alignment, which would make more sense
2726 as a cacheline-style operation. */
2727 {
2728 TCGv_i64 t64 = tcg_temp_new_i64();
2729 TCGv d_addr = tcg_temp_new();
2730 TCGv eight = tcg_constant_tl(8);
2731 int i;
2732
2733 tcg_gen_concat_tl_i64(t64, lo, hi);
2734 tcg_gen_andi_tl(d_addr, addr, -8);
2735 for (i = 0; i < 32; i += 8) {
c03a0fd1 2736 tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop);
a76779ee
RH
2737 tcg_gen_add_tl(d_addr, d_addr, eight);
2738 }
2739 }
2740 break;
2741
7ec1e5ea 2742 default:
918d9a2c
RH
2743 /* ??? In theory we've handled all of the ASIs that are valid
2744 for stda, and this should raise DAE_invalid_asi. */
7ec1e5ea 2745 {
c03a0fd1
RH
2746 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2747 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
918d9a2c 2748 TCGv_i64 t64 = tcg_temp_new_i64();
7ec1e5ea 2749
918d9a2c 2750 /* See above. */
c03a0fd1 2751 if ((da->memop & MO_BSWAP) == MO_TE) {
a76779ee 2752 tcg_gen_concat_tl_i64(t64, lo, hi);
918d9a2c 2753 } else {
a76779ee 2754 tcg_gen_concat_tl_i64(t64, hi, lo);
918d9a2c 2755 }
7ec1e5ea 2756
918d9a2c 2757 save_state(dc);
ad75a51e 2758 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
7ec1e5ea
RH
2759 }
2760 break;
2761 }
1a2fb1c0
BS
2762}
2763
a76779ee 2764static void __attribute__((unused))
c03a0fd1 2765gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, int insn, int rd)
1a2fb1c0 2766{
fc313c64 2767 DisasASI da = get_asi(dc, insn, MO_TEUQ);
1a2fb1c0 2768
c03a0fd1
RH
2769 gen_address_mask(dc, addr);
2770 gen_stda_asi0(dc, &da, addr, rd);
1a2fb1c0
BS
2771}
2772
9d1d4e34 2773static TCGv get_src1(DisasContext *dc, unsigned int insn)
9322a4bf 2774{
9d1d4e34
RH
2775 unsigned int rs1 = GET_FIELD(insn, 13, 17);
2776 return gen_load_gpr(dc, rs1);
9322a4bf
BS
2777}
2778
8194f35a 2779#ifdef TARGET_SPARC64
7e480893
RH
2780static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2781{
2782 TCGv_i32 c32, zero, dst, s1, s2;
2783
2784 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2785 or fold the comparison down to 32 bits and use movcond_i32. Choose
2786 the later. */
2787 c32 = tcg_temp_new_i32();
2788 if (cmp->is_bool) {
ecc7b3aa 2789 tcg_gen_extrl_i64_i32(c32, cmp->c1);
7e480893
RH
2790 } else {
2791 TCGv_i64 c64 = tcg_temp_new_i64();
2792 tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
ecc7b3aa 2793 tcg_gen_extrl_i64_i32(c32, c64);
7e480893
RH
2794 }
2795
2796 s1 = gen_load_fpr_F(dc, rs);
2797 s2 = gen_load_fpr_F(dc, rd);
ba5f5179 2798 dst = gen_dest_fpr_F(dc);
00ab7e61 2799 zero = tcg_constant_i32(0);
7e480893
RH
2800
2801 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2802
7e480893
RH
2803 gen_store_fpr_F(dc, rd, dst);
2804}
2805
2806static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2807{
3886b8a3 2808 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
7e480893
RH
2809 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
2810 gen_load_fpr_D(dc, rs),
2811 gen_load_fpr_D(dc, rd));
2812 gen_store_fpr_D(dc, rd, dst);
2813}
2814
2815static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2816{
2817 int qd = QFPREG(rd);
2818 int qs = QFPREG(rs);
2819
2820 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
2821 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2822 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
2823 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2824
f9c816c0 2825 gen_update_fprs_dirty(dc, qd);
7e480893
RH
2826}
2827
5d617bfb 2828static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
8194f35a 2829{
b551ec04 2830 TCGv_i32 r_tl = tcg_temp_new_i32();
8194f35a
IK
2831
2832 /* load env->tl into r_tl */
ad75a51e 2833 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
8194f35a
IK
2834
2835 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
b551ec04 2836 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
8194f35a
IK
2837
2838 /* calculate offset to current trap state from env->ts, reuse r_tl */
b551ec04 2839 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
ad75a51e 2840 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
8194f35a
IK
2841
2842 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
b551ec04
JF
2843 {
2844 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2845 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2846 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
b551ec04 2847 }
8194f35a 2848}
6c073553
RH
2849
2850static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2851 int width, bool cc, bool left)
2852{
905a83de 2853 TCGv lo1, lo2;
6c073553
RH
2854 uint64_t amask, tabl, tabr;
2855 int shift, imask, omask;
2856
2857 if (cc) {
2858 tcg_gen_mov_tl(cpu_cc_src, s1);
2859 tcg_gen_mov_tl(cpu_cc_src2, s2);
2860 tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2861 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2862 dc->cc_op = CC_OP_SUB;
2863 }
2864
2865 /* Theory of operation: there are two tables, left and right (not to
2866 be confused with the left and right versions of the opcode). These
2867 are indexed by the low 3 bits of the inputs. To make things "easy",
2868 these tables are loaded into two constants, TABL and TABR below.
2869 The operation index = (input & imask) << shift calculates the index
2870 into the constant, while val = (table >> index) & omask calculates
2871 the value we're looking for. */
2872 switch (width) {
2873 case 8:
2874 imask = 0x7;
2875 shift = 3;
2876 omask = 0xff;
2877 if (left) {
2878 tabl = 0x80c0e0f0f8fcfeffULL;
2879 tabr = 0xff7f3f1f0f070301ULL;
2880 } else {
2881 tabl = 0x0103070f1f3f7fffULL;
2882 tabr = 0xfffefcf8f0e0c080ULL;
2883 }
2884 break;
2885 case 16:
2886 imask = 0x6;
2887 shift = 1;
2888 omask = 0xf;
2889 if (left) {
2890 tabl = 0x8cef;
2891 tabr = 0xf731;
2892 } else {
2893 tabl = 0x137f;
2894 tabr = 0xfec8;
2895 }
2896 break;
2897 case 32:
2898 imask = 0x4;
2899 shift = 0;
2900 omask = 0x3;
2901 if (left) {
2902 tabl = (2 << 2) | 3;
2903 tabr = (3 << 2) | 1;
2904 } else {
2905 tabl = (1 << 2) | 3;
2906 tabr = (3 << 2) | 2;
2907 }
2908 break;
2909 default:
2910 abort();
2911 }
2912
2913 lo1 = tcg_temp_new();
2914 lo2 = tcg_temp_new();
2915 tcg_gen_andi_tl(lo1, s1, imask);
2916 tcg_gen_andi_tl(lo2, s2, imask);
2917 tcg_gen_shli_tl(lo1, lo1, shift);
2918 tcg_gen_shli_tl(lo2, lo2, shift);
2919
905a83de
RH
2920 tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
2921 tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
e3ebbade 2922 tcg_gen_andi_tl(lo1, lo1, omask);
6c073553
RH
2923 tcg_gen_andi_tl(lo2, lo2, omask);
2924
2925 amask = -8;
2926 if (AM_CHECK(dc)) {
2927 amask &= 0xffffffffULL;
2928 }
2929 tcg_gen_andi_tl(s1, s1, amask);
2930 tcg_gen_andi_tl(s2, s2, amask);
2931
e3ebbade
RH
2932 /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
2933 tcg_gen_and_tl(lo2, lo2, lo1);
2934 tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
6c073553 2935}
add545ab
RH
2936
2937static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
2938{
2939 TCGv tmp = tcg_temp_new();
2940
2941 tcg_gen_add_tl(tmp, s1, s2);
2942 tcg_gen_andi_tl(dst, tmp, -8);
2943 if (left) {
2944 tcg_gen_neg_tl(tmp, tmp);
2945 }
2946 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
add545ab 2947}
50c796f9
RH
2948
2949static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
2950{
2951 TCGv t1, t2, shift;
2952
2953 t1 = tcg_temp_new();
2954 t2 = tcg_temp_new();
2955 shift = tcg_temp_new();
2956
2957 tcg_gen_andi_tl(shift, gsr, 7);
2958 tcg_gen_shli_tl(shift, shift, 3);
2959 tcg_gen_shl_tl(t1, s1, shift);
2960
2961 /* A shift of 64 does not produce 0 in TCG. Divide this into a
2962 shift of (up to 63) followed by a constant shift of 1. */
2963 tcg_gen_xori_tl(shift, shift, 63);
2964 tcg_gen_shr_tl(t2, s2, shift);
2965 tcg_gen_shri_tl(t2, t2, 1);
2966
2967 tcg_gen_or_tl(dst, t1, t2);
50c796f9 2968}
8194f35a
IK
2969#endif
2970
878cc677
RH
2971/* Include the auto-generated decoder. */
2972#include "decode-insns.c.inc"
2973
2974#define TRANS(NAME, AVAIL, FUNC, ...) \
2975 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2976 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2977
2978#define avail_ALL(C) true
2979#ifdef TARGET_SPARC64
2980# define avail_32(C) false
af25071c 2981# define avail_ASR17(C) false
c2636853 2982# define avail_DIV(C) true
b5372650 2983# define avail_MUL(C) true
0faef01b 2984# define avail_POWERDOWN(C) false
878cc677 2985# define avail_64(C) true
5d617bfb 2986# define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
af25071c 2987# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
878cc677
RH
2988#else
2989# define avail_32(C) true
af25071c 2990# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
c2636853 2991# define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV)
b5372650 2992# define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL)
0faef01b 2993# define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
878cc677 2994# define avail_64(C) false
5d617bfb 2995# define avail_GL(C) false
af25071c 2996# define avail_HYPV(C) false
878cc677
RH
2997#endif
2998
2999/* Default case for non jump instructions. */
3000static bool advance_pc(DisasContext *dc)
3001{
3002 if (dc->npc & 3) {
3003 switch (dc->npc) {
3004 case DYNAMIC_PC:
3005 case DYNAMIC_PC_LOOKUP:
3006 dc->pc = dc->npc;
3007 gen_op_next_insn();
3008 break;
3009 case JUMP_PC:
3010 /* we can do a static jump */
3011 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
3012 dc->base.is_jmp = DISAS_NORETURN;
3013 break;
3014 default:
3015 g_assert_not_reached();
3016 }
3017 } else {
3018 dc->pc = dc->npc;
3019 dc->npc = dc->npc + 4;
3020 }
3021 return true;
3022}
3023
6d2a0768
RH
3024/*
3025 * Major opcodes 00 and 01 -- branches, call, and sethi
3026 */
3027
276567aa
RH
3028static bool advance_jump_uncond_never(DisasContext *dc, bool annul)
3029{
3030 if (annul) {
3031 dc->pc = dc->npc + 4;
3032 dc->npc = dc->pc + 4;
3033 } else {
3034 dc->pc = dc->npc;
3035 dc->npc = dc->pc + 4;
3036 }
3037 return true;
3038}
3039
3040static bool advance_jump_uncond_always(DisasContext *dc, bool annul,
3041 target_ulong dest)
3042{
3043 if (annul) {
3044 dc->pc = dest;
3045 dc->npc = dest + 4;
3046 } else {
3047 dc->pc = dc->npc;
3048 dc->npc = dest;
3049 tcg_gen_mov_tl(cpu_pc, cpu_npc);
3050 }
3051 return true;
3052}
3053
9d4e2bc7
RH
3054static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
3055 bool annul, target_ulong dest)
276567aa 3056{
6b3e4cc6
RH
3057 target_ulong npc = dc->npc;
3058
276567aa 3059 if (annul) {
6b3e4cc6
RH
3060 TCGLabel *l1 = gen_new_label();
3061
9d4e2bc7 3062 tcg_gen_brcond_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
6b3e4cc6
RH
3063 gen_goto_tb(dc, 0, npc, dest);
3064 gen_set_label(l1);
3065 gen_goto_tb(dc, 1, npc + 4, npc + 8);
3066
3067 dc->base.is_jmp = DISAS_NORETURN;
276567aa 3068 } else {
6b3e4cc6
RH
3069 if (npc & 3) {
3070 switch (npc) {
3071 case DYNAMIC_PC:
3072 case DYNAMIC_PC_LOOKUP:
3073 tcg_gen_mov_tl(cpu_pc, cpu_npc);
3074 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
9d4e2bc7
RH
3075 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
3076 cmp->c1, cmp->c2,
6b3e4cc6
RH
3077 tcg_constant_tl(dest), cpu_npc);
3078 dc->pc = npc;
3079 break;
3080 default:
3081 g_assert_not_reached();
3082 }
3083 } else {
3084 dc->pc = npc;
3085 dc->jump_pc[0] = dest;
3086 dc->jump_pc[1] = npc + 4;
3087 dc->npc = JUMP_PC;
9d4e2bc7
RH
3088 if (cmp->is_bool) {
3089 tcg_gen_mov_tl(cpu_cond, cmp->c1);
3090 } else {
3091 tcg_gen_setcond_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
3092 }
6b3e4cc6 3093 }
276567aa
RH
3094 }
3095 return true;
3096}
3097
af25071c
RH
3098static bool raise_priv(DisasContext *dc)
3099{
3100 gen_exception(dc, TT_PRIV_INSN);
3101 return true;
3102}
3103
276567aa
RH
3104static bool do_bpcc(DisasContext *dc, arg_bcc *a)
3105{
3106 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
1ea9c62a 3107 DisasCompare cmp;
276567aa
RH
3108
3109 switch (a->cond) {
3110 case 0x0:
3111 return advance_jump_uncond_never(dc, a->a);
3112 case 0x8:
3113 return advance_jump_uncond_always(dc, a->a, target);
3114 default:
3115 flush_cond(dc);
1ea9c62a
RH
3116
3117 gen_compare(&cmp, a->cc, a->cond, dc);
9d4e2bc7 3118 return advance_jump_cond(dc, &cmp, a->a, target);
276567aa
RH
3119 }
3120}
3121
3122TRANS(Bicc, ALL, do_bpcc, a)
3123TRANS(BPcc, 64, do_bpcc, a)
3124
45196ea4
RH
3125static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
3126{
3127 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
d5471936 3128 DisasCompare cmp;
45196ea4
RH
3129
3130 if (gen_trap_ifnofpu(dc)) {
3131 return true;
3132 }
3133 switch (a->cond) {
3134 case 0x0:
3135 return advance_jump_uncond_never(dc, a->a);
3136 case 0x8:
3137 return advance_jump_uncond_always(dc, a->a, target);
3138 default:
3139 flush_cond(dc);
d5471936
RH
3140
3141 gen_fcompare(&cmp, a->cc, a->cond);
9d4e2bc7 3142 return advance_jump_cond(dc, &cmp, a->a, target);
45196ea4
RH
3143 }
3144}
3145
3146TRANS(FBPfcc, 64, do_fbpfcc, a)
3147TRANS(FBfcc, ALL, do_fbpfcc, a)
3148
ab9ffe98
RH
3149static bool trans_BPr(DisasContext *dc, arg_BPr *a)
3150{
3151 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
3152 DisasCompare cmp;
3153
3154 if (!avail_64(dc)) {
3155 return false;
3156 }
3157 if (gen_tcg_cond_reg[a->cond] == TCG_COND_NEVER) {
3158 return false;
3159 }
3160
3161 flush_cond(dc);
3162 gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1));
9d4e2bc7 3163 return advance_jump_cond(dc, &cmp, a->a, target);
ab9ffe98
RH
3164}
3165
23ada1b1
RH
3166static bool trans_CALL(DisasContext *dc, arg_CALL *a)
3167{
3168 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
3169
3170 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
3171 gen_mov_pc_npc(dc);
3172 dc->npc = target;
3173 return true;
3174}
3175
45196ea4
RH
3176static bool trans_NCP(DisasContext *dc, arg_NCP *a)
3177{
3178 /*
3179 * For sparc32, always generate the no-coprocessor exception.
3180 * For sparc64, always generate illegal instruction.
3181 */
3182#ifdef TARGET_SPARC64
3183 return false;
3184#else
3185 gen_exception(dc, TT_NCP_INSN);
3186 return true;
3187#endif
3188}
3189
6d2a0768
RH
3190static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
3191{
3192 /* Special-case %g0 because that's the canonical nop. */
3193 if (a->rd) {
3194 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
3195 }
3196 return advance_pc(dc);
3197}
3198
0faef01b
RH
3199/*
3200 * Major Opcode 10 -- integer, floating-point, vis, and system insns.
3201 */
3202
30376636
RH
3203static bool do_tcc(DisasContext *dc, int cond, int cc,
3204 int rs1, bool imm, int rs2_or_imm)
3205{
3206 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
3207 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
3208 DisasCompare cmp;
3209 TCGLabel *lab;
3210 TCGv_i32 trap;
3211
3212 /* Trap never. */
3213 if (cond == 0) {
3214 return advance_pc(dc);
3215 }
3216
3217 /*
3218 * Immediate traps are the most common case. Since this value is
3219 * live across the branch, it really pays to evaluate the constant.
3220 */
3221 if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
3222 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
3223 } else {
3224 trap = tcg_temp_new_i32();
3225 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
3226 if (imm) {
3227 tcg_gen_addi_i32(trap, trap, rs2_or_imm);
3228 } else {
3229 TCGv_i32 t2 = tcg_temp_new_i32();
3230 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
3231 tcg_gen_add_i32(trap, trap, t2);
3232 }
3233 tcg_gen_andi_i32(trap, trap, mask);
3234 tcg_gen_addi_i32(trap, trap, TT_TRAP);
3235 }
3236
3237 /* Trap always. */
3238 if (cond == 8) {
3239 save_state(dc);
3240 gen_helper_raise_exception(tcg_env, trap);
3241 dc->base.is_jmp = DISAS_NORETURN;
3242 return true;
3243 }
3244
3245 /* Conditional trap. */
3246 flush_cond(dc);
3247 lab = delay_exceptionv(dc, trap);
3248 gen_compare(&cmp, cc, cond, dc);
3249 tcg_gen_brcond_tl(cmp.cond, cmp.c1, cmp.c2, lab);
3250
3251 return advance_pc(dc);
3252}
3253
3254static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
3255{
3256 if (avail_32(dc) && a->cc) {
3257 return false;
3258 }
3259 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
3260}
3261
3262static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
3263{
3264 if (avail_64(dc)) {
3265 return false;
3266 }
3267 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
3268}
3269
3270static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
3271{
3272 if (avail_32(dc)) {
3273 return false;
3274 }
3275 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
3276}
3277
af25071c
RH
3278static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
3279{
3280 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
3281 return advance_pc(dc);
3282}
3283
3284static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
3285{
3286 if (avail_32(dc)) {
3287 return false;
3288 }
3289 if (a->mmask) {
3290 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
3291 tcg_gen_mb(a->mmask | TCG_BAR_SC);
3292 }
3293 if (a->cmask) {
3294 /* For #Sync, etc, end the TB to recognize interrupts. */
3295 dc->base.is_jmp = DISAS_EXIT;
3296 }
3297 return advance_pc(dc);
3298}
3299
3300static bool do_rd_special(DisasContext *dc, bool priv, int rd,
3301 TCGv (*func)(DisasContext *, TCGv))
3302{
3303 if (!priv) {
3304 return raise_priv(dc);
3305 }
3306 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
3307 return advance_pc(dc);
3308}
3309
3310static TCGv do_rdy(DisasContext *dc, TCGv dst)
3311{
3312 return cpu_y;
3313}
3314
3315static bool trans_RDY(DisasContext *dc, arg_RDY *a)
3316{
3317 /*
3318 * TODO: Need a feature bit for sparcv8. In the meantime, treat all
3319 * 32-bit cpus like sparcv7, which ignores the rs1 field.
3320 * This matches after all other ASR, so Leon3 Asr17 is handled first.
3321 */
3322 if (avail_64(dc) && a->rs1 != 0) {
3323 return false;
3324 }
3325 return do_rd_special(dc, true, a->rd, do_rdy);
3326}
3327
3328static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
3329{
3330 uint32_t val;
3331
3332 /*
3333 * TODO: There are many more fields to be filled,
3334 * some of which are writable.
3335 */
3336 val = dc->def->nwindows - 1; /* [4:0] NWIN */
3337 val |= 1 << 8; /* [8] V8 */
3338
3339 return tcg_constant_tl(val);
3340}
3341
3342TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
3343
3344static TCGv do_rdccr(DisasContext *dc, TCGv dst)
3345{
3346 update_psr(dc);
3347 gen_helper_rdccr(dst, tcg_env);
3348 return dst;
3349}
3350
3351TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
3352
3353static TCGv do_rdasi(DisasContext *dc, TCGv dst)
3354{
3355#ifdef TARGET_SPARC64
3356 return tcg_constant_tl(dc->asi);
3357#else
3358 qemu_build_not_reached();
3359#endif
3360}
3361
3362TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
3363
3364static TCGv do_rdtick(DisasContext *dc, TCGv dst)
3365{
3366 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3367
3368 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3369 if (translator_io_start(&dc->base)) {
3370 dc->base.is_jmp = DISAS_EXIT;
3371 }
3372 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
3373 tcg_constant_i32(dc->mem_idx));
3374 return dst;
3375}
3376
3377/* TODO: non-priv access only allowed when enabled. */
3378TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
3379
3380static TCGv do_rdpc(DisasContext *dc, TCGv dst)
3381{
3382 return tcg_constant_tl(address_mask_i(dc, dc->pc));
3383}
3384
3385TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
3386
3387static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
3388{
3389 tcg_gen_ext_i32_tl(dst, cpu_fprs);
3390 return dst;
3391}
3392
3393TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
3394
3395static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
3396{
3397 gen_trap_ifnofpu(dc);
3398 return cpu_gsr;
3399}
3400
3401TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
3402
3403static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
3404{
3405 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
3406 return dst;
3407}
3408
3409TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
3410
3411static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
3412{
577efa45
RH
3413 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
3414 return dst;
af25071c
RH
3415}
3416
3417/* TODO: non-priv access only allowed when enabled. */
3418TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
3419
3420static TCGv do_rdstick(DisasContext *dc, TCGv dst)
3421{
3422 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3423
3424 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
3425 if (translator_io_start(&dc->base)) {
3426 dc->base.is_jmp = DISAS_EXIT;
3427 }
3428 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
3429 tcg_constant_i32(dc->mem_idx));
3430 return dst;
3431}
3432
3433/* TODO: non-priv access only allowed when enabled. */
3434TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
3435
3436static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
3437{
577efa45
RH
3438 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
3439 return dst;
af25071c
RH
3440}
3441
3442/* TODO: supervisor access only allowed when enabled by hypervisor. */
3443TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
3444
3445/*
3446 * UltraSPARC-T1 Strand status.
3447 * HYPV check maybe not enough, UA2005 & UA2007 describe
3448 * this ASR as impl. dep
3449 */
3450static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
3451{
3452 return tcg_constant_tl(1);
3453}
3454
3455TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
3456
668bb9b7
RH
3457static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
3458{
3459 update_psr(dc);
3460 gen_helper_rdpsr(dst, tcg_env);
3461 return dst;
3462}
3463
3464TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
3465
3466static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
3467{
3468 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
3469 return dst;
3470}
3471
3472TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
3473
3474static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
3475{
3476 TCGv_i32 tl = tcg_temp_new_i32();
3477 TCGv_ptr tp = tcg_temp_new_ptr();
3478
3479 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3480 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3481 tcg_gen_shli_i32(tl, tl, 3);
3482 tcg_gen_ext_i32_ptr(tp, tl);
3483 tcg_gen_add_ptr(tp, tp, tcg_env);
3484
3485 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
3486 return dst;
3487}
3488
3489TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
3490
3491static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
3492{
2da789de
RH
3493 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
3494 return dst;
668bb9b7
RH
3495}
3496
3497TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
3498
3499static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
3500{
2da789de
RH
3501 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
3502 return dst;
668bb9b7
RH
3503}
3504
3505TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
3506
3507static TCGv do_rdhver(DisasContext *dc, TCGv dst)
3508{
2da789de
RH
3509 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
3510 return dst;
668bb9b7
RH
3511}
3512
3513TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
3514
3515static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
3516{
577efa45
RH
3517 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
3518 return dst;
668bb9b7
RH
3519}
3520
3521TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
3522 do_rdhstick_cmpr)
3523
5d617bfb
RH
3524static TCGv do_rdwim(DisasContext *dc, TCGv dst)
3525{
cd6269f7
RH
3526 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
3527 return dst;
5d617bfb
RH
3528}
3529
3530TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
3531
3532static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
3533{
3534#ifdef TARGET_SPARC64
3535 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3536
3537 gen_load_trap_state_at_tl(r_tsptr);
3538 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
3539 return dst;
3540#else
3541 qemu_build_not_reached();
3542#endif
3543}
3544
3545TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
3546
3547static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
3548{
3549#ifdef TARGET_SPARC64
3550 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3551
3552 gen_load_trap_state_at_tl(r_tsptr);
3553 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
3554 return dst;
3555#else
3556 qemu_build_not_reached();
3557#endif
3558}
3559
3560TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
3561
3562static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
3563{
3564#ifdef TARGET_SPARC64
3565 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3566
3567 gen_load_trap_state_at_tl(r_tsptr);
3568 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
3569 return dst;
3570#else
3571 qemu_build_not_reached();
3572#endif
3573}
3574
3575TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
3576
3577static TCGv do_rdtt(DisasContext *dc, TCGv dst)
3578{
3579#ifdef TARGET_SPARC64
3580 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3581
3582 gen_load_trap_state_at_tl(r_tsptr);
3583 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
3584 return dst;
3585#else
3586 qemu_build_not_reached();
3587#endif
3588}
3589
3590TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
3591TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
3592
3593static TCGv do_rdtba(DisasContext *dc, TCGv dst)
3594{
3595 return cpu_tbr;
3596}
3597
e8325dc0 3598TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
5d617bfb
RH
3599TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
3600
3601static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
3602{
3603 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
3604 return dst;
3605}
3606
3607TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
3608
3609static TCGv do_rdtl(DisasContext *dc, TCGv dst)
3610{
3611 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
3612 return dst;
3613}
3614
3615TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
3616
3617static TCGv do_rdpil(DisasContext *dc, TCGv dst)
3618{
3619 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
3620 return dst;
3621}
3622
3623TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
3624
3625static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
3626{
3627 gen_helper_rdcwp(dst, tcg_env);
3628 return dst;
3629}
3630
3631TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
3632
3633static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
3634{
3635 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
3636 return dst;
3637}
3638
3639TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
3640
3641static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
3642{
3643 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
3644 return dst;
3645}
3646
3647TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
3648 do_rdcanrestore)
3649
3650static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
3651{
3652 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
3653 return dst;
3654}
3655
3656TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
3657
3658static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
3659{
3660 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
3661 return dst;
3662}
3663
3664TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
3665
3666static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
3667{
3668 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
3669 return dst;
3670}
3671
3672TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
3673
3674static TCGv do_rdgl(DisasContext *dc, TCGv dst)
3675{
3676 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
3677 return dst;
3678}
3679
3680TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
3681
3682/* UA2005 strand status */
3683static TCGv do_rdssr(DisasContext *dc, TCGv dst)
3684{
2da789de
RH
3685 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
3686 return dst;
5d617bfb
RH
3687}
3688
3689TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
3690
3691static TCGv do_rdver(DisasContext *dc, TCGv dst)
3692{
2da789de
RH
3693 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
3694 return dst;
5d617bfb
RH
3695}
3696
3697TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
3698
e8325dc0
RH
3699static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
3700{
3701 if (avail_64(dc)) {
3702 gen_helper_flushw(tcg_env);
3703 return advance_pc(dc);
3704 }
3705 return false;
3706}
3707
0faef01b
RH
3708static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
3709 void (*func)(DisasContext *, TCGv))
3710{
3711 TCGv src;
3712
3713 /* For simplicity, we under-decoded the rs2 form. */
3714 if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
3715 return false;
3716 }
3717 if (!priv) {
3718 return raise_priv(dc);
3719 }
3720
3721 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
3722 src = tcg_constant_tl(a->rs2_or_imm);
3723 } else {
3724 TCGv src1 = gen_load_gpr(dc, a->rs1);
3725 if (a->rs2_or_imm == 0) {
3726 src = src1;
3727 } else {
3728 src = tcg_temp_new();
3729 if (a->imm) {
3730 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
3731 } else {
3732 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
3733 }
3734 }
3735 }
3736 func(dc, src);
3737 return advance_pc(dc);
3738}
3739
3740static void do_wry(DisasContext *dc, TCGv src)
3741{
3742 tcg_gen_ext32u_tl(cpu_y, src);
3743}
3744
3745TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
3746
3747static void do_wrccr(DisasContext *dc, TCGv src)
3748{
3749 gen_helper_wrccr(tcg_env, src);
3750}
3751
3752TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
3753
3754static void do_wrasi(DisasContext *dc, TCGv src)
3755{
3756 TCGv tmp = tcg_temp_new();
3757
3758 tcg_gen_ext8u_tl(tmp, src);
3759 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
3760 /* End TB to notice changed ASI. */
3761 dc->base.is_jmp = DISAS_EXIT;
3762}
3763
3764TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
3765
3766static void do_wrfprs(DisasContext *dc, TCGv src)
3767{
3768#ifdef TARGET_SPARC64
3769 tcg_gen_trunc_tl_i32(cpu_fprs, src);
3770 dc->fprs_dirty = 0;
3771 dc->base.is_jmp = DISAS_EXIT;
3772#else
3773 qemu_build_not_reached();
3774#endif
3775}
3776
3777TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
3778
3779static void do_wrgsr(DisasContext *dc, TCGv src)
3780{
3781 gen_trap_ifnofpu(dc);
3782 tcg_gen_mov_tl(cpu_gsr, src);
3783}
3784
3785TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
3786
3787static void do_wrsoftint_set(DisasContext *dc, TCGv src)
3788{
3789 gen_helper_set_softint(tcg_env, src);
3790}
3791
3792TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
3793
3794static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
3795{
3796 gen_helper_clear_softint(tcg_env, src);
3797}
3798
3799TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
3800
3801static void do_wrsoftint(DisasContext *dc, TCGv src)
3802{
3803 gen_helper_write_softint(tcg_env, src);
3804}
3805
3806TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
3807
3808static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
3809{
0faef01b
RH
3810 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3811
577efa45
RH
3812 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
3813 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
0faef01b 3814 translator_io_start(&dc->base);
577efa45 3815 gen_helper_tick_set_limit(r_tickptr, src);
0faef01b
RH
3816 /* End TB to handle timer interrupt */
3817 dc->base.is_jmp = DISAS_EXIT;
0faef01b
RH
3818}
3819
3820TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
3821
3822static void do_wrstick(DisasContext *dc, TCGv src)
3823{
3824#ifdef TARGET_SPARC64
3825 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3826
3827 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3828 translator_io_start(&dc->base);
3829 gen_helper_tick_set_count(r_tickptr, src);
3830 /* End TB to handle timer interrupt */
3831 dc->base.is_jmp = DISAS_EXIT;
3832#else
3833 qemu_build_not_reached();
3834#endif
3835}
3836
3837TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
3838
3839static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
3840{
0faef01b
RH
3841 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3842
577efa45
RH
3843 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3844 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
0faef01b 3845 translator_io_start(&dc->base);
577efa45 3846 gen_helper_tick_set_limit(r_tickptr, src);
0faef01b
RH
3847 /* End TB to handle timer interrupt */
3848 dc->base.is_jmp = DISAS_EXIT;
0faef01b
RH
3849}
3850
3851TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
3852
3853static void do_wrpowerdown(DisasContext *dc, TCGv src)
3854{
3855 save_state(dc);
3856 gen_helper_power_down(tcg_env);
3857}
3858
3859TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
3860
25524734
RH
3861static void do_wrpsr(DisasContext *dc, TCGv src)
3862{
3863 gen_helper_wrpsr(tcg_env, src);
3864 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3865 dc->cc_op = CC_OP_FLAGS;
3866 dc->base.is_jmp = DISAS_EXIT;
3867}
3868
3869TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
3870
9422278e
RH
3871static void do_wrwim(DisasContext *dc, TCGv src)
3872{
3873 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
cd6269f7
RH
3874 TCGv tmp = tcg_temp_new();
3875
3876 tcg_gen_andi_tl(tmp, src, mask);
3877 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
9422278e
RH
3878}
3879
3880TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
3881
3882static void do_wrtpc(DisasContext *dc, TCGv src)
3883{
3884#ifdef TARGET_SPARC64
3885 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3886
3887 gen_load_trap_state_at_tl(r_tsptr);
3888 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
3889#else
3890 qemu_build_not_reached();
3891#endif
3892}
3893
3894TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
3895
3896static void do_wrtnpc(DisasContext *dc, TCGv src)
3897{
3898#ifdef TARGET_SPARC64
3899 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3900
3901 gen_load_trap_state_at_tl(r_tsptr);
3902 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
3903#else
3904 qemu_build_not_reached();
3905#endif
3906}
3907
3908TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
3909
3910static void do_wrtstate(DisasContext *dc, TCGv src)
3911{
3912#ifdef TARGET_SPARC64
3913 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3914
3915 gen_load_trap_state_at_tl(r_tsptr);
3916 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
3917#else
3918 qemu_build_not_reached();
3919#endif
3920}
3921
3922TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
3923
3924static void do_wrtt(DisasContext *dc, TCGv src)
3925{
3926#ifdef TARGET_SPARC64
3927 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3928
3929 gen_load_trap_state_at_tl(r_tsptr);
3930 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
3931#else
3932 qemu_build_not_reached();
3933#endif
3934}
3935
3936TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
3937
3938static void do_wrtick(DisasContext *dc, TCGv src)
3939{
3940 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3941
3942 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3943 translator_io_start(&dc->base);
3944 gen_helper_tick_set_count(r_tickptr, src);
3945 /* End TB to handle timer interrupt */
3946 dc->base.is_jmp = DISAS_EXIT;
3947}
3948
3949TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
3950
3951static void do_wrtba(DisasContext *dc, TCGv src)
3952{
3953 tcg_gen_mov_tl(cpu_tbr, src);
3954}
3955
3956TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
3957
3958static void do_wrpstate(DisasContext *dc, TCGv src)
3959{
3960 save_state(dc);
3961 if (translator_io_start(&dc->base)) {
3962 dc->base.is_jmp = DISAS_EXIT;
3963 }
3964 gen_helper_wrpstate(tcg_env, src);
3965 dc->npc = DYNAMIC_PC;
3966}
3967
3968TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
3969
3970static void do_wrtl(DisasContext *dc, TCGv src)
3971{
3972 save_state(dc);
3973 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
3974 dc->npc = DYNAMIC_PC;
3975}
3976
3977TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
3978
3979static void do_wrpil(DisasContext *dc, TCGv src)
3980{
3981 if (translator_io_start(&dc->base)) {
3982 dc->base.is_jmp = DISAS_EXIT;
3983 }
3984 gen_helper_wrpil(tcg_env, src);
3985}
3986
3987TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
3988
3989static void do_wrcwp(DisasContext *dc, TCGv src)
3990{
3991 gen_helper_wrcwp(tcg_env, src);
3992}
3993
3994TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
3995
3996static void do_wrcansave(DisasContext *dc, TCGv src)
3997{
3998 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
3999}
4000
4001TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
4002
4003static void do_wrcanrestore(DisasContext *dc, TCGv src)
4004{
4005 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
4006}
4007
4008TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
4009
4010static void do_wrcleanwin(DisasContext *dc, TCGv src)
4011{
4012 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
4013}
4014
4015TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
4016
4017static void do_wrotherwin(DisasContext *dc, TCGv src)
4018{
4019 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
4020}
4021
4022TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
4023
4024static void do_wrwstate(DisasContext *dc, TCGv src)
4025{
4026 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
4027}
4028
4029TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
4030
4031static void do_wrgl(DisasContext *dc, TCGv src)
4032{
4033 gen_helper_wrgl(tcg_env, src);
4034}
4035
4036TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
4037
4038/* UA2005 strand status */
4039static void do_wrssr(DisasContext *dc, TCGv src)
4040{
2da789de 4041 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
9422278e
RH
4042}
4043
4044TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
4045
bb97f2f5
RH
4046TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
4047
4048static void do_wrhpstate(DisasContext *dc, TCGv src)
4049{
4050 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
4051 dc->base.is_jmp = DISAS_EXIT;
4052}
4053
4054TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
4055
4056static void do_wrhtstate(DisasContext *dc, TCGv src)
4057{
4058 TCGv_i32 tl = tcg_temp_new_i32();
4059 TCGv_ptr tp = tcg_temp_new_ptr();
4060
4061 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
4062 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
4063 tcg_gen_shli_i32(tl, tl, 3);
4064 tcg_gen_ext_i32_ptr(tp, tl);
4065 tcg_gen_add_ptr(tp, tp, tcg_env);
4066
4067 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
4068}
4069
4070TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
4071
4072static void do_wrhintp(DisasContext *dc, TCGv src)
4073{
2da789de 4074 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
bb97f2f5
RH
4075}
4076
4077TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
4078
4079static void do_wrhtba(DisasContext *dc, TCGv src)
4080{
2da789de 4081 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
bb97f2f5
RH
4082}
4083
4084TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
4085
4086static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
4087{
4088 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
4089
577efa45 4090 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
bb97f2f5
RH
4091 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
4092 translator_io_start(&dc->base);
577efa45 4093 gen_helper_tick_set_limit(r_tickptr, src);
bb97f2f5
RH
4094 /* End TB to handle timer interrupt */
4095 dc->base.is_jmp = DISAS_EXIT;
4096}
4097
4098TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
4099 do_wrhstick_cmpr)
4100
25524734
RH
4101static bool do_saved_restored(DisasContext *dc, bool saved)
4102{
4103 if (!supervisor(dc)) {
4104 return raise_priv(dc);
4105 }
4106 if (saved) {
4107 gen_helper_saved(tcg_env);
4108 } else {
4109 gen_helper_restored(tcg_env);
4110 }
4111 return advance_pc(dc);
4112}
4113
4114TRANS(SAVED, 64, do_saved_restored, true)
4115TRANS(RESTORED, 64, do_saved_restored, false)
4116
d3825800
RH
4117static bool trans_NOP(DisasContext *dc, arg_NOP *a)
4118{
4119 return advance_pc(dc);
4120}
4121
0faef01b
RH
4122static bool trans_NOP_v7(DisasContext *dc, arg_NOP_v7 *a)
4123{
4124 /*
4125 * TODO: Need a feature bit for sparcv8.
4126 * In the meantime, treat all 32-bit cpus like sparcv7.
4127 */
4128 if (avail_32(dc)) {
4129 return advance_pc(dc);
4130 }
4131 return false;
4132}
4133
428881de
RH
4134static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op,
4135 void (*func)(TCGv, TCGv, TCGv),
4136 void (*funci)(TCGv, TCGv, target_long))
4137{
4138 TCGv dst, src1;
4139
4140 /* For simplicity, we under-decoded the rs2 form. */
4141 if (!a->imm && a->rs2_or_imm & ~0x1f) {
4142 return false;
4143 }
4144
4145 if (a->cc) {
4146 dst = cpu_cc_dst;
4147 } else {
4148 dst = gen_dest_gpr(dc, a->rd);
4149 }
4150 src1 = gen_load_gpr(dc, a->rs1);
4151
4152 if (a->imm || a->rs2_or_imm == 0) {
4153 if (funci) {
4154 funci(dst, src1, a->rs2_or_imm);
4155 } else {
4156 func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
4157 }
4158 } else {
4159 func(dst, src1, cpu_regs[a->rs2_or_imm]);
4160 }
4161 gen_store_gpr(dc, a->rd, dst);
4162
4163 if (a->cc) {
4164 tcg_gen_movi_i32(cpu_cc_op, cc_op);
4165 dc->cc_op = cc_op;
4166 }
4167 return advance_pc(dc);
4168}
4169
4170static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op,
4171 void (*func)(TCGv, TCGv, TCGv),
4172 void (*funci)(TCGv, TCGv, target_long),
4173 void (*func_cc)(TCGv, TCGv, TCGv))
4174{
4175 if (a->cc) {
22188d7d 4176 assert(cc_op >= 0);
428881de
RH
4177 return do_arith_int(dc, a, cc_op, func_cc, NULL);
4178 }
4179 return do_arith_int(dc, a, cc_op, func, funci);
4180}
4181
4182static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
4183 void (*func)(TCGv, TCGv, TCGv),
4184 void (*funci)(TCGv, TCGv, target_long))
4185{
4186 return do_arith_int(dc, a, CC_OP_LOGIC, func, funci);
4187}
4188
4189TRANS(ADD, ALL, do_arith, a, CC_OP_ADD,
4190 tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc)
4191TRANS(SUB, ALL, do_arith, a, CC_OP_SUB,
4192 tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc)
4193
a9aba13d
RH
4194TRANS(TADDcc, ALL, do_arith, a, CC_OP_TADD, NULL, NULL, gen_op_add_cc)
4195TRANS(TSUBcc, ALL, do_arith, a, CC_OP_TSUB, NULL, NULL, gen_op_sub_cc)
4196TRANS(TADDccTV, ALL, do_arith, a, CC_OP_TADDTV, NULL, NULL, gen_op_taddcctv)
4197TRANS(TSUBccTV, ALL, do_arith, a, CC_OP_TSUBTV, NULL, NULL, gen_op_tsubcctv)
4198
428881de
RH
4199TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
4200TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
4201TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
4202TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
4203TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
4204
22188d7d 4205TRANS(MULX, 64, do_arith, a, -1, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
b5372650
RH
4206TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
4207TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
22188d7d 4208
4ee85ea9
RH
4209TRANS(UDIVX, 64, do_arith, a, -1, gen_op_udivx, NULL, NULL)
4210TRANS(SDIVX, 64, do_arith, a, -1, gen_op_sdivx, NULL, NULL)
c2636853
RH
4211TRANS(UDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_udiv, NULL, gen_op_udivcc)
4212TRANS(SDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_sdiv, NULL, gen_op_sdivcc)
4ee85ea9 4213
9c6ec5bc
RH
4214/* TODO: Should have feature bit -- comes in with UltraSparc T2. */
4215TRANS(POPC, 64, do_arith, a, -1, gen_op_popc, NULL, NULL)
4216
428881de
RH
4217static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
4218{
4219 /* OR with %g0 is the canonical alias for MOV. */
4220 if (!a->cc && a->rs1 == 0) {
4221 if (a->imm || a->rs2_or_imm == 0) {
4222 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
4223 } else if (a->rs2_or_imm & ~0x1f) {
4224 /* For simplicity, we under-decoded the rs2 form. */
4225 return false;
4226 } else {
4227 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
4228 }
4229 return advance_pc(dc);
4230 }
4231 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
4232}
4233
420a187d
RH
4234static bool trans_ADDC(DisasContext *dc, arg_r_r_ri_cc *a)
4235{
4236 switch (dc->cc_op) {
4237 case CC_OP_DIV:
4238 case CC_OP_LOGIC:
4239 /* Carry is known to be zero. Fall back to plain ADD. */
4240 return do_arith(dc, a, CC_OP_ADD,
4241 tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc);
4242 case CC_OP_ADD:
4243 case CC_OP_TADD:
4244 case CC_OP_TADDTV:
4245 return do_arith(dc, a, CC_OP_ADDX,
4246 gen_op_addc_add, NULL, gen_op_addccc_add);
4247 case CC_OP_SUB:
4248 case CC_OP_TSUB:
4249 case CC_OP_TSUBTV:
4250 return do_arith(dc, a, CC_OP_ADDX,
4251 gen_op_addc_sub, NULL, gen_op_addccc_sub);
4252 default:
4253 return do_arith(dc, a, CC_OP_ADDX,
4254 gen_op_addc_generic, NULL, gen_op_addccc_generic);
4255 }
4256}
4257
dfebb950
RH
4258static bool trans_SUBC(DisasContext *dc, arg_r_r_ri_cc *a)
4259{
4260 switch (dc->cc_op) {
4261 case CC_OP_DIV:
4262 case CC_OP_LOGIC:
4263 /* Carry is known to be zero. Fall back to plain SUB. */
4264 return do_arith(dc, a, CC_OP_SUB,
4265 tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc);
4266 case CC_OP_ADD:
4267 case CC_OP_TADD:
4268 case CC_OP_TADDTV:
4269 return do_arith(dc, a, CC_OP_SUBX,
4270 gen_op_subc_add, NULL, gen_op_subccc_add);
4271 case CC_OP_SUB:
4272 case CC_OP_TSUB:
4273 case CC_OP_TSUBTV:
4274 return do_arith(dc, a, CC_OP_SUBX,
4275 gen_op_subc_sub, NULL, gen_op_subccc_sub);
4276 default:
4277 return do_arith(dc, a, CC_OP_SUBX,
4278 gen_op_subc_generic, NULL, gen_op_subccc_generic);
4279 }
4280}
4281
a9aba13d
RH
4282static bool trans_MULScc(DisasContext *dc, arg_r_r_ri_cc *a)
4283{
4284 update_psr(dc);
4285 return do_arith(dc, a, CC_OP_ADD, NULL, NULL, gen_op_mulscc);
4286}
4287
5fc546ee
RH
4288static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
4289{
4290 TCGv dst, src1, src2;
4291
4292 /* Reject 64-bit shifts for sparc32. */
4293 if (avail_32(dc) && a->x) {
4294 return false;
4295 }
4296
4297 src2 = tcg_temp_new();
4298 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
4299 src1 = gen_load_gpr(dc, a->rs1);
4300 dst = gen_dest_gpr(dc, a->rd);
4301
4302 if (l) {
4303 tcg_gen_shl_tl(dst, src1, src2);
4304 if (!a->x) {
4305 tcg_gen_ext32u_tl(dst, dst);
4306 }
4307 } else if (u) {
4308 if (!a->x) {
4309 tcg_gen_ext32u_tl(dst, src1);
4310 src1 = dst;
4311 }
4312 tcg_gen_shr_tl(dst, src1, src2);
4313 } else {
4314 if (!a->x) {
4315 tcg_gen_ext32s_tl(dst, src1);
4316 src1 = dst;
4317 }
4318 tcg_gen_sar_tl(dst, src1, src2);
4319 }
4320 gen_store_gpr(dc, a->rd, dst);
4321 return advance_pc(dc);
4322}
4323
4324TRANS(SLL_r, ALL, do_shift_r, a, true, true)
4325TRANS(SRL_r, ALL, do_shift_r, a, false, true)
4326TRANS(SRA_r, ALL, do_shift_r, a, false, false)
4327
4328static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
4329{
4330 TCGv dst, src1;
4331
4332 /* Reject 64-bit shifts for sparc32. */
4333 if (avail_32(dc) && (a->x || a->i >= 32)) {
4334 return false;
4335 }
4336
4337 src1 = gen_load_gpr(dc, a->rs1);
4338 dst = gen_dest_gpr(dc, a->rd);
4339
4340 if (avail_32(dc) || a->x) {
4341 if (l) {
4342 tcg_gen_shli_tl(dst, src1, a->i);
4343 } else if (u) {
4344 tcg_gen_shri_tl(dst, src1, a->i);
4345 } else {
4346 tcg_gen_sari_tl(dst, src1, a->i);
4347 }
4348 } else {
4349 if (l) {
4350 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
4351 } else if (u) {
4352 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
4353 } else {
4354 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
4355 }
4356 }
4357 gen_store_gpr(dc, a->rd, dst);
4358 return advance_pc(dc);
4359}
4360
4361TRANS(SLL_i, ALL, do_shift_i, a, true, true)
4362TRANS(SRL_i, ALL, do_shift_i, a, false, true)
4363TRANS(SRA_i, ALL, do_shift_i, a, false, false)
4364
fb4ed7aa
RH
4365static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
4366{
4367 /* For simplicity, we under-decoded the rs2 form. */
4368 if (!imm && rs2_or_imm & ~0x1f) {
4369 return NULL;
4370 }
4371 if (imm || rs2_or_imm == 0) {
4372 return tcg_constant_tl(rs2_or_imm);
4373 } else {
4374 return cpu_regs[rs2_or_imm];
4375 }
4376}
4377
4378static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
4379{
4380 TCGv dst = gen_load_gpr(dc, rd);
4381
4382 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, cmp->c2, src2, dst);
4383 gen_store_gpr(dc, rd, dst);
4384 return advance_pc(dc);
4385}
4386
4387static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
4388{
4389 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4390 DisasCompare cmp;
4391
4392 if (src2 == NULL) {
4393 return false;
4394 }
4395 gen_compare(&cmp, a->cc, a->cond, dc);
4396 return do_mov_cond(dc, &cmp, a->rd, src2);
4397}
4398
4399static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
4400{
4401 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4402 DisasCompare cmp;
4403
4404 if (src2 == NULL) {
4405 return false;
4406 }
4407 gen_fcompare(&cmp, a->cc, a->cond);
4408 return do_mov_cond(dc, &cmp, a->rd, src2);
4409}
4410
4411static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
4412{
4413 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4414 DisasCompare cmp;
4415
4416 if (src2 == NULL) {
4417 return false;
4418 }
4419 gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1));
4420 return do_mov_cond(dc, &cmp, a->rd, src2);
4421}
4422
86b82fe0
RH
4423static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
4424 bool (*func)(DisasContext *dc, int rd, TCGv src))
4425{
4426 TCGv src1, sum;
4427
4428 /* For simplicity, we under-decoded the rs2 form. */
4429 if (!a->imm && a->rs2_or_imm & ~0x1f) {
4430 return false;
4431 }
4432
4433 /*
4434 * Always load the sum into a new temporary.
4435 * This is required to capture the value across a window change,
4436 * e.g. SAVE and RESTORE, and may be optimized away otherwise.
4437 */
4438 sum = tcg_temp_new();
4439 src1 = gen_load_gpr(dc, a->rs1);
4440 if (a->imm || a->rs2_or_imm == 0) {
4441 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
4442 } else {
4443 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
4444 }
4445 return func(dc, a->rd, sum);
4446}
4447
4448static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
4449{
4450 /*
4451 * Preserve pc across advance, so that we can delay
4452 * the writeback to rd until after src is consumed.
4453 */
4454 target_ulong cur_pc = dc->pc;
4455
4456 gen_check_align(dc, src, 3);
4457
4458 gen_mov_pc_npc(dc);
4459 tcg_gen_mov_tl(cpu_npc, src);
4460 gen_address_mask(dc, cpu_npc);
4461 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
4462
4463 dc->npc = DYNAMIC_PC_LOOKUP;
4464 return true;
4465}
4466
4467TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
4468
4469static bool do_rett(DisasContext *dc, int rd, TCGv src)
4470{
4471 if (!supervisor(dc)) {
4472 return raise_priv(dc);
4473 }
4474
4475 gen_check_align(dc, src, 3);
4476
4477 gen_mov_pc_npc(dc);
4478 tcg_gen_mov_tl(cpu_npc, src);
4479 gen_helper_rett(tcg_env);
4480
4481 dc->npc = DYNAMIC_PC;
4482 return true;
4483}
4484
4485TRANS(RETT, 32, do_add_special, a, do_rett)
4486
4487static bool do_return(DisasContext *dc, int rd, TCGv src)
4488{
4489 gen_check_align(dc, src, 3);
4490
4491 gen_mov_pc_npc(dc);
4492 tcg_gen_mov_tl(cpu_npc, src);
4493 gen_address_mask(dc, cpu_npc);
4494
4495 gen_helper_restore(tcg_env);
4496 dc->npc = DYNAMIC_PC_LOOKUP;
4497 return true;
4498}
4499
4500TRANS(RETURN, 64, do_add_special, a, do_return)
4501
d3825800
RH
4502static bool do_save(DisasContext *dc, int rd, TCGv src)
4503{
4504 gen_helper_save(tcg_env);
4505 gen_store_gpr(dc, rd, src);
4506 return advance_pc(dc);
4507}
4508
4509TRANS(SAVE, ALL, do_add_special, a, do_save)
4510
4511static bool do_restore(DisasContext *dc, int rd, TCGv src)
4512{
4513 gen_helper_restore(tcg_env);
4514 gen_store_gpr(dc, rd, src);
4515 return advance_pc(dc);
4516}
4517
4518TRANS(RESTORE, ALL, do_add_special, a, do_restore)
4519
8f75b8a4
RH
4520static bool do_done_retry(DisasContext *dc, bool done)
4521{
4522 if (!supervisor(dc)) {
4523 return raise_priv(dc);
4524 }
4525 dc->npc = DYNAMIC_PC;
4526 dc->pc = DYNAMIC_PC;
4527 translator_io_start(&dc->base);
4528 if (done) {
4529 gen_helper_done(tcg_env);
4530 } else {
4531 gen_helper_retry(tcg_env);
4532 }
4533 return true;
4534}
4535
4536TRANS(DONE, 64, do_done_retry, true)
4537TRANS(RETRY, 64, do_done_retry, false)
4538
0880d20b
RH
4539/*
4540 * Major opcode 11 -- load and store instructions
4541 */
4542
4543static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
4544{
4545 TCGv addr, tmp = NULL;
4546
4547 /* For simplicity, we under-decoded the rs2 form. */
4548 if (!imm && rs2_or_imm & ~0x1f) {
4549 return NULL;
4550 }
4551
4552 addr = gen_load_gpr(dc, rs1);
4553 if (rs2_or_imm) {
4554 tmp = tcg_temp_new();
4555 if (imm) {
4556 tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
4557 } else {
4558 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
4559 }
4560 addr = tmp;
4561 }
4562 if (AM_CHECK(dc)) {
4563 if (!tmp) {
4564 tmp = tcg_temp_new();
4565 }
4566 tcg_gen_ext32u_tl(tmp, addr);
4567 addr = tmp;
4568 }
4569 return addr;
4570}
4571
4572static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4573{
4574 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4575 DisasASI da;
4576
4577 if (addr == NULL) {
4578 return false;
4579 }
4580 da = resolve_asi(dc, a->asi, mop);
4581
4582 reg = gen_dest_gpr(dc, a->rd);
4583 gen_ld_asi0(dc, &da, reg, addr);
4584 gen_store_gpr(dc, a->rd, reg);
4585 return advance_pc(dc);
4586}
4587
4588TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
4589TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
4590TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
4591TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
4592TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
4593TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
4594TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
4595
4596static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4597{
4598 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4599 DisasASI da;
4600
4601 if (addr == NULL) {
4602 return false;
4603 }
4604 da = resolve_asi(dc, a->asi, mop);
4605
4606 reg = gen_load_gpr(dc, a->rd);
4607 gen_st_asi0(dc, &da, reg, addr);
4608 return advance_pc(dc);
4609}
4610
4611TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
4612TRANS(STB, ALL, do_st_gpr, a, MO_UB)
4613TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
4614TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
4615
4616static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
4617{
4618 TCGv addr;
4619 DisasASI da;
4620
4621 if (a->rd & 1) {
4622 return false;
4623 }
4624 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4625 if (addr == NULL) {
4626 return false;
4627 }
4628 da = resolve_asi(dc, a->asi, MO_TEUQ);
4629 gen_ldda_asi0(dc, &da, addr, a->rd);
4630 return advance_pc(dc);
4631}
4632
4633static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
4634{
4635 TCGv addr;
4636 DisasASI da;
4637
4638 if (a->rd & 1) {
4639 return false;
4640 }
4641 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4642 if (addr == NULL) {
4643 return false;
4644 }
4645 da = resolve_asi(dc, a->asi, MO_TEUQ);
4646 gen_stda_asi0(dc, &da, addr, a->rd);
4647 return advance_pc(dc);
4648}
4649
64a88d5d 4650#define CHECK_IU_FEATURE(dc, FEATURE) \
5578ceab 4651 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
4652 goto illegal_insn;
4653#define CHECK_FPU_FEATURE(dc, FEATURE) \
5578ceab 4654 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
4655 goto nfpu_insn;
4656
0bee699e 4657/* before an instruction, dc->pc must be static */
878cc677 4658static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
cf495bcf 4659{
0184e266 4660 unsigned int opc, rs1, rs2, rd;
8f75b8a4
RH
4661 TCGv cpu_src1;
4662 TCGv cpu_src2 __attribute__((unused));
208ae657 4663 TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
96eda024 4664 TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
67526b20 4665 target_long simm;
7a3f1944 4666
cf495bcf 4667 opc = GET_FIELD(insn, 0, 1);
cf495bcf 4668 rd = GET_FIELD(insn, 2, 6);
6ae20372 4669
cf495bcf 4670 switch (opc) {
6d2a0768
RH
4671 case 0:
4672 goto illegal_insn; /* in decodetree */
23ada1b1
RH
4673 case 1:
4674 g_assert_not_reached(); /* in decodetree */
0f8a249a
BS
4675 case 2: /* FPU & Logical Operations */
4676 {
8f75b8a4 4677 unsigned int xop = GET_FIELD(insn, 7, 12);
af25071c 4678 TCGv cpu_dst __attribute__((unused)) = tcg_temp_new();
5793f2a4 4679
af25071c 4680 if (xop == 0x34) { /* FPU Operations */
5b12f1e8 4681 if (gen_trap_ifnofpu(dc)) {
a80dde08 4682 goto jmp_insn;
5b12f1e8 4683 }
0f8a249a 4684 gen_op_clear_ieee_excp_and_FTT();
e8af50a3 4685 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
4686 rs2 = GET_FIELD(insn, 27, 31);
4687 xop = GET_FIELD(insn, 18, 26);
02c79d78 4688
0f8a249a 4689 switch (xop) {
dc1a6971 4690 case 0x1: /* fmovs */
208ae657
RH
4691 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4692 gen_store_fpr_F(dc, rd, cpu_src1_32);
dc1a6971
BS
4693 break;
4694 case 0x5: /* fnegs */
61f17f6e 4695 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
dc1a6971
BS
4696 break;
4697 case 0x9: /* fabss */
61f17f6e 4698 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
dc1a6971
BS
4699 break;
4700 case 0x29: /* fsqrts */
61f17f6e 4701 gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
dc1a6971
BS
4702 break;
4703 case 0x2a: /* fsqrtd */
61f17f6e 4704 gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
dc1a6971
BS
4705 break;
4706 case 0x2b: /* fsqrtq */
4707 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4708 gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
dc1a6971
BS
4709 break;
4710 case 0x41: /* fadds */
61f17f6e 4711 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
dc1a6971
BS
4712 break;
4713 case 0x42: /* faddd */
61f17f6e 4714 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
dc1a6971
BS
4715 break;
4716 case 0x43: /* faddq */
4717 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4718 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
dc1a6971
BS
4719 break;
4720 case 0x45: /* fsubs */
61f17f6e 4721 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
dc1a6971
BS
4722 break;
4723 case 0x46: /* fsubd */
61f17f6e 4724 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
dc1a6971
BS
4725 break;
4726 case 0x47: /* fsubq */
4727 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4728 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
dc1a6971
BS
4729 break;
4730 case 0x49: /* fmuls */
61f17f6e 4731 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
dc1a6971
BS
4732 break;
4733 case 0x4a: /* fmuld */
61f17f6e 4734 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
dc1a6971
BS
4735 break;
4736 case 0x4b: /* fmulq */
4737 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4738 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
dc1a6971
BS
4739 break;
4740 case 0x4d: /* fdivs */
61f17f6e 4741 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
dc1a6971
BS
4742 break;
4743 case 0x4e: /* fdivd */
61f17f6e 4744 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
dc1a6971
BS
4745 break;
4746 case 0x4f: /* fdivq */
4747 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4748 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
dc1a6971
BS
4749 break;
4750 case 0x69: /* fsmuld */
4751 CHECK_FPU_FEATURE(dc, FSMULD);
61f17f6e 4752 gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
dc1a6971
BS
4753 break;
4754 case 0x6e: /* fdmulq */
4755 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4756 gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
dc1a6971
BS
4757 break;
4758 case 0xc4: /* fitos */
61f17f6e 4759 gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
dc1a6971
BS
4760 break;
4761 case 0xc6: /* fdtos */
61f17f6e 4762 gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
dc1a6971
BS
4763 break;
4764 case 0xc7: /* fqtos */
4765 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4766 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
dc1a6971
BS
4767 break;
4768 case 0xc8: /* fitod */
61f17f6e 4769 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
dc1a6971
BS
4770 break;
4771 case 0xc9: /* fstod */
61f17f6e 4772 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
dc1a6971
BS
4773 break;
4774 case 0xcb: /* fqtod */
4775 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4776 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
dc1a6971
BS
4777 break;
4778 case 0xcc: /* fitoq */
4779 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4780 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
dc1a6971
BS
4781 break;
4782 case 0xcd: /* fstoq */
4783 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4784 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
dc1a6971
BS
4785 break;
4786 case 0xce: /* fdtoq */
4787 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4788 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
dc1a6971
BS
4789 break;
4790 case 0xd1: /* fstoi */
61f17f6e 4791 gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
dc1a6971
BS
4792 break;
4793 case 0xd2: /* fdtoi */
61f17f6e 4794 gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
dc1a6971
BS
4795 break;
4796 case 0xd3: /* fqtoi */
4797 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4798 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
dc1a6971 4799 break;
3475187d 4800#ifdef TARGET_SPARC64
dc1a6971 4801 case 0x2: /* V9 fmovd */
96eda024
RH
4802 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4803 gen_store_fpr_D(dc, rd, cpu_src1_64);
dc1a6971
BS
4804 break;
4805 case 0x3: /* V9 fmovq */
4806 CHECK_FPU_FEATURE(dc, FLOAT128);
f9c816c0 4807 gen_move_Q(dc, rd, rs2);
dc1a6971
BS
4808 break;
4809 case 0x6: /* V9 fnegd */
61f17f6e 4810 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
dc1a6971
BS
4811 break;
4812 case 0x7: /* V9 fnegq */
4813 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4814 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
dc1a6971
BS
4815 break;
4816 case 0xa: /* V9 fabsd */
61f17f6e 4817 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
dc1a6971
BS
4818 break;
4819 case 0xb: /* V9 fabsq */
4820 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4821 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
dc1a6971
BS
4822 break;
4823 case 0x81: /* V9 fstox */
61f17f6e 4824 gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
dc1a6971
BS
4825 break;
4826 case 0x82: /* V9 fdtox */
61f17f6e 4827 gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
dc1a6971
BS
4828 break;
4829 case 0x83: /* V9 fqtox */
4830 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4831 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
dc1a6971
BS
4832 break;
4833 case 0x84: /* V9 fxtos */
61f17f6e 4834 gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
dc1a6971
BS
4835 break;
4836 case 0x88: /* V9 fxtod */
61f17f6e 4837 gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
dc1a6971
BS
4838 break;
4839 case 0x8c: /* V9 fxtoq */
4840 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 4841 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
dc1a6971 4842 break;
0f8a249a 4843#endif
dc1a6971
BS
4844 default:
4845 goto illegal_insn;
0f8a249a
BS
4846 }
4847 } else if (xop == 0x35) { /* FPU Operations */
3475187d 4848#ifdef TARGET_SPARC64
0f8a249a 4849 int cond;
3475187d 4850#endif
5b12f1e8 4851 if (gen_trap_ifnofpu(dc)) {
a80dde08 4852 goto jmp_insn;
5b12f1e8 4853 }
0f8a249a 4854 gen_op_clear_ieee_excp_and_FTT();
cf495bcf 4855 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
4856 rs2 = GET_FIELD(insn, 27, 31);
4857 xop = GET_FIELD(insn, 18, 26);
dcf24905 4858
690995a6
RH
4859#ifdef TARGET_SPARC64
4860#define FMOVR(sz) \
4861 do { \
4862 DisasCompare cmp; \
e7c8afb9 4863 cond = GET_FIELD_SP(insn, 10, 12); \
9d1d4e34 4864 cpu_src1 = get_src1(dc, insn); \
690995a6
RH
4865 gen_compare_reg(&cmp, cond, cpu_src1); \
4866 gen_fmov##sz(dc, &cmp, rd, rs2); \
690995a6
RH
4867 } while (0)
4868
4869 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
4870 FMOVR(s);
0f8a249a
BS
4871 break;
4872 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
690995a6 4873 FMOVR(d);
0f8a249a
BS
4874 break;
4875 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
64a88d5d 4876 CHECK_FPU_FEATURE(dc, FLOAT128);
690995a6 4877 FMOVR(q);
1f587329 4878 break;
0f8a249a 4879 }
690995a6 4880#undef FMOVR
0f8a249a
BS
4881#endif
4882 switch (xop) {
3475187d 4883#ifdef TARGET_SPARC64
7e480893
RH
4884#define FMOVCC(fcc, sz) \
4885 do { \
4886 DisasCompare cmp; \
714547bb 4887 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
4888 gen_fcompare(&cmp, fcc, cond); \
4889 gen_fmov##sz(dc, &cmp, rd, rs2); \
7e480893
RH
4890 } while (0)
4891
0f8a249a 4892 case 0x001: /* V9 fmovscc %fcc0 */
7e480893 4893 FMOVCC(0, s);
0f8a249a
BS
4894 break;
4895 case 0x002: /* V9 fmovdcc %fcc0 */
7e480893 4896 FMOVCC(0, d);
0f8a249a
BS
4897 break;
4898 case 0x003: /* V9 fmovqcc %fcc0 */
64a88d5d 4899 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4900 FMOVCC(0, q);
1f587329 4901 break;
0f8a249a 4902 case 0x041: /* V9 fmovscc %fcc1 */
7e480893 4903 FMOVCC(1, s);
0f8a249a
BS
4904 break;
4905 case 0x042: /* V9 fmovdcc %fcc1 */
7e480893 4906 FMOVCC(1, d);
0f8a249a
BS
4907 break;
4908 case 0x043: /* V9 fmovqcc %fcc1 */
64a88d5d 4909 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4910 FMOVCC(1, q);
1f587329 4911 break;
0f8a249a 4912 case 0x081: /* V9 fmovscc %fcc2 */
7e480893 4913 FMOVCC(2, s);
0f8a249a
BS
4914 break;
4915 case 0x082: /* V9 fmovdcc %fcc2 */
7e480893 4916 FMOVCC(2, d);
0f8a249a
BS
4917 break;
4918 case 0x083: /* V9 fmovqcc %fcc2 */
64a88d5d 4919 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4920 FMOVCC(2, q);
1f587329 4921 break;
0f8a249a 4922 case 0x0c1: /* V9 fmovscc %fcc3 */
7e480893 4923 FMOVCC(3, s);
0f8a249a
BS
4924 break;
4925 case 0x0c2: /* V9 fmovdcc %fcc3 */
7e480893 4926 FMOVCC(3, d);
0f8a249a
BS
4927 break;
4928 case 0x0c3: /* V9 fmovqcc %fcc3 */
64a88d5d 4929 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4930 FMOVCC(3, q);
1f587329 4931 break;
7e480893
RH
4932#undef FMOVCC
4933#define FMOVCC(xcc, sz) \
4934 do { \
4935 DisasCompare cmp; \
714547bb 4936 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
4937 gen_compare(&cmp, xcc, cond, dc); \
4938 gen_fmov##sz(dc, &cmp, rd, rs2); \
7e480893 4939 } while (0)
19f329ad 4940
0f8a249a 4941 case 0x101: /* V9 fmovscc %icc */
7e480893 4942 FMOVCC(0, s);
0f8a249a
BS
4943 break;
4944 case 0x102: /* V9 fmovdcc %icc */
7e480893 4945 FMOVCC(0, d);
b7d69dc2 4946 break;
0f8a249a 4947 case 0x103: /* V9 fmovqcc %icc */
64a88d5d 4948 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4949 FMOVCC(0, q);
1f587329 4950 break;
0f8a249a 4951 case 0x181: /* V9 fmovscc %xcc */
7e480893 4952 FMOVCC(1, s);
0f8a249a
BS
4953 break;
4954 case 0x182: /* V9 fmovdcc %xcc */
7e480893 4955 FMOVCC(1, d);
0f8a249a
BS
4956 break;
4957 case 0x183: /* V9 fmovqcc %xcc */
64a88d5d 4958 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 4959 FMOVCC(1, q);
1f587329 4960 break;
7e480893 4961#undef FMOVCC
1f587329
BS
4962#endif
4963 case 0x51: /* fcmps, V9 %fcc */
208ae657
RH
4964 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4965 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
4966 gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a 4967 break;
1f587329 4968 case 0x52: /* fcmpd, V9 %fcc */
03fb8cfc
RH
4969 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4970 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4971 gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 4972 break;
1f587329 4973 case 0x53: /* fcmpq, V9 %fcc */
64a88d5d 4974 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
4975 gen_op_load_fpr_QT0(QFPREG(rs1));
4976 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 4977 gen_op_fcmpq(rd & 3);
1f587329 4978 break;
0f8a249a 4979 case 0x55: /* fcmpes, V9 %fcc */
208ae657
RH
4980 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4981 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
4982 gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a
BS
4983 break;
4984 case 0x56: /* fcmped, V9 %fcc */
03fb8cfc
RH
4985 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4986 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4987 gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 4988 break;
1f587329 4989 case 0x57: /* fcmpeq, V9 %fcc */
64a88d5d 4990 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
4991 gen_op_load_fpr_QT0(QFPREG(rs1));
4992 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 4993 gen_op_fcmpeq(rd & 3);
1f587329 4994 break;
0f8a249a
BS
4995 default:
4996 goto illegal_insn;
4997 }
d3c7e8ad 4998 } else if (xop == 0x36) {
3299908c 4999#ifdef TARGET_SPARC64
d3c7e8ad 5000 /* VIS */
3299908c
BS
5001 int opf = GET_FIELD_SP(insn, 5, 13);
5002 rs1 = GET_FIELD(insn, 13, 17);
5003 rs2 = GET_FIELD(insn, 27, 31);
5b12f1e8 5004 if (gen_trap_ifnofpu(dc)) {
e9ebed4d 5005 goto jmp_insn;
5b12f1e8 5006 }
3299908c
BS
5007
5008 switch (opf) {
e9ebed4d 5009 case 0x000: /* VIS I edge8cc */
6c073553 5010 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5011 cpu_src1 = gen_load_gpr(dc, rs1);
5012 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5013 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
97ea2859 5014 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5015 break;
e9ebed4d 5016 case 0x001: /* VIS II edge8n */
6c073553 5017 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5018 cpu_src1 = gen_load_gpr(dc, rs1);
5019 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5020 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
97ea2859 5021 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5022 break;
e9ebed4d 5023 case 0x002: /* VIS I edge8lcc */
6c073553 5024 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5025 cpu_src1 = gen_load_gpr(dc, rs1);
5026 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5027 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
97ea2859 5028 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5029 break;
e9ebed4d 5030 case 0x003: /* VIS II edge8ln */
6c073553 5031 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5032 cpu_src1 = gen_load_gpr(dc, rs1);
5033 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5034 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
97ea2859 5035 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5036 break;
e9ebed4d 5037 case 0x004: /* VIS I edge16cc */
6c073553 5038 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5039 cpu_src1 = gen_load_gpr(dc, rs1);
5040 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5041 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
97ea2859 5042 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5043 break;
e9ebed4d 5044 case 0x005: /* VIS II edge16n */
6c073553 5045 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5046 cpu_src1 = gen_load_gpr(dc, rs1);
5047 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5048 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
97ea2859 5049 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5050 break;
e9ebed4d 5051 case 0x006: /* VIS I edge16lcc */
6c073553 5052 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5053 cpu_src1 = gen_load_gpr(dc, rs1);
5054 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5055 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
97ea2859 5056 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5057 break;
e9ebed4d 5058 case 0x007: /* VIS II edge16ln */
6c073553 5059 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5060 cpu_src1 = gen_load_gpr(dc, rs1);
5061 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5062 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
97ea2859 5063 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5064 break;
e9ebed4d 5065 case 0x008: /* VIS I edge32cc */
6c073553 5066 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5067 cpu_src1 = gen_load_gpr(dc, rs1);
5068 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5069 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
97ea2859 5070 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5071 break;
e9ebed4d 5072 case 0x009: /* VIS II edge32n */
6c073553 5073 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5074 cpu_src1 = gen_load_gpr(dc, rs1);
5075 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5076 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
97ea2859 5077 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5078 break;
e9ebed4d 5079 case 0x00a: /* VIS I edge32lcc */
6c073553 5080 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
5081 cpu_src1 = gen_load_gpr(dc, rs1);
5082 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5083 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
97ea2859 5084 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5085 break;
e9ebed4d 5086 case 0x00b: /* VIS II edge32ln */
6c073553 5087 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
5088 cpu_src1 = gen_load_gpr(dc, rs1);
5089 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 5090 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
97ea2859 5091 gen_store_gpr(dc, rd, cpu_dst);
6c073553 5092 break;
e9ebed4d 5093 case 0x010: /* VIS I array8 */
64a88d5d 5094 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 5095 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 5096 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 5097 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
97ea2859 5098 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5099 break;
5100 case 0x012: /* VIS I array16 */
64a88d5d 5101 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 5102 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 5103 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 5104 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 5105 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
97ea2859 5106 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5107 break;
5108 case 0x014: /* VIS I array32 */
64a88d5d 5109 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 5110 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 5111 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 5112 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 5113 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
97ea2859 5114 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d 5115 break;
3299908c 5116 case 0x018: /* VIS I alignaddr */
64a88d5d 5117 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 5118 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 5119 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 5120 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
97ea2859 5121 gen_store_gpr(dc, rd, cpu_dst);
3299908c
BS
5122 break;
5123 case 0x01a: /* VIS I alignaddrl */
add545ab 5124 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 5125 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 5126 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 5127 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
97ea2859 5128 gen_store_gpr(dc, rd, cpu_dst);
add545ab
RH
5129 break;
5130 case 0x019: /* VIS II bmask */
793a137a 5131 CHECK_FPU_FEATURE(dc, VIS2);
9d1d4e34
RH
5132 cpu_src1 = gen_load_gpr(dc, rs1);
5133 cpu_src2 = gen_load_gpr(dc, rs2);
793a137a
RH
5134 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
5135 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
97ea2859 5136 gen_store_gpr(dc, rd, cpu_dst);
793a137a 5137 break;
e9ebed4d 5138 case 0x020: /* VIS I fcmple16 */
64a88d5d 5139 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5140 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5141 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5142 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5143 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5144 break;
5145 case 0x022: /* VIS I fcmpne16 */
64a88d5d 5146 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5147 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5148 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5149 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5150 gen_store_gpr(dc, rd, cpu_dst);
3299908c 5151 break;
e9ebed4d 5152 case 0x024: /* VIS I fcmple32 */
64a88d5d 5153 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5154 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5155 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5156 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5157 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5158 break;
5159 case 0x026: /* VIS I fcmpne32 */
64a88d5d 5160 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5161 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5162 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5163 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5164 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5165 break;
5166 case 0x028: /* VIS I fcmpgt16 */
64a88d5d 5167 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5168 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5169 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5170 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5171 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5172 break;
5173 case 0x02a: /* VIS I fcmpeq16 */
64a88d5d 5174 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5175 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5176 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5177 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5178 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5179 break;
5180 case 0x02c: /* VIS I fcmpgt32 */
64a88d5d 5181 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5182 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5183 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5184 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5185 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5186 break;
5187 case 0x02e: /* VIS I fcmpeq32 */
64a88d5d 5188 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
5189 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5190 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 5191 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 5192 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
5193 break;
5194 case 0x031: /* VIS I fmul8x16 */
64a88d5d 5195 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5196 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
e9ebed4d
BS
5197 break;
5198 case 0x033: /* VIS I fmul8x16au */
64a88d5d 5199 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5200 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
e9ebed4d
BS
5201 break;
5202 case 0x035: /* VIS I fmul8x16al */
64a88d5d 5203 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5204 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
e9ebed4d
BS
5205 break;
5206 case 0x036: /* VIS I fmul8sux16 */
64a88d5d 5207 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5208 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
e9ebed4d
BS
5209 break;
5210 case 0x037: /* VIS I fmul8ulx16 */
64a88d5d 5211 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5212 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
e9ebed4d
BS
5213 break;
5214 case 0x038: /* VIS I fmuld8sux16 */
64a88d5d 5215 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5216 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
e9ebed4d
BS
5217 break;
5218 case 0x039: /* VIS I fmuld8ulx16 */
64a88d5d 5219 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5220 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
e9ebed4d
BS
5221 break;
5222 case 0x03a: /* VIS I fpack32 */
2dedf314
RH
5223 CHECK_FPU_FEATURE(dc, VIS1);
5224 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
5225 break;
e9ebed4d 5226 case 0x03b: /* VIS I fpack16 */
2dedf314
RH
5227 CHECK_FPU_FEATURE(dc, VIS1);
5228 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 5229 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
5230 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
5231 gen_store_fpr_F(dc, rd, cpu_dst_32);
5232 break;
e9ebed4d 5233 case 0x03d: /* VIS I fpackfix */
2dedf314
RH
5234 CHECK_FPU_FEATURE(dc, VIS1);
5235 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 5236 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
5237 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
5238 gen_store_fpr_F(dc, rd, cpu_dst_32);
5239 break;
f888300b
RH
5240 case 0x03e: /* VIS I pdist */
5241 CHECK_FPU_FEATURE(dc, VIS1);
5242 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
5243 break;
3299908c 5244 case 0x048: /* VIS I faligndata */
64a88d5d 5245 CHECK_FPU_FEATURE(dc, VIS1);
50c796f9 5246 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
3299908c 5247 break;
e9ebed4d 5248 case 0x04b: /* VIS I fpmerge */
64a88d5d 5249 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5250 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
e9ebed4d
BS
5251 break;
5252 case 0x04c: /* VIS II bshuffle */
793a137a
RH
5253 CHECK_FPU_FEATURE(dc, VIS2);
5254 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
5255 break;
e9ebed4d 5256 case 0x04d: /* VIS I fexpand */
64a88d5d 5257 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5258 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
e9ebed4d
BS
5259 break;
5260 case 0x050: /* VIS I fpadd16 */
64a88d5d 5261 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5262 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
e9ebed4d
BS
5263 break;
5264 case 0x051: /* VIS I fpadd16s */
64a88d5d 5265 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5266 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
e9ebed4d
BS
5267 break;
5268 case 0x052: /* VIS I fpadd32 */
64a88d5d 5269 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5270 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
e9ebed4d
BS
5271 break;
5272 case 0x053: /* VIS I fpadd32s */
64a88d5d 5273 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5274 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
e9ebed4d
BS
5275 break;
5276 case 0x054: /* VIS I fpsub16 */
64a88d5d 5277 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5278 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
e9ebed4d
BS
5279 break;
5280 case 0x055: /* VIS I fpsub16s */
64a88d5d 5281 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5282 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
e9ebed4d
BS
5283 break;
5284 case 0x056: /* VIS I fpsub32 */
64a88d5d 5285 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5286 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
e9ebed4d
BS
5287 break;
5288 case 0x057: /* VIS I fpsub32s */
64a88d5d 5289 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5290 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
e9ebed4d 5291 break;
3299908c 5292 case 0x060: /* VIS I fzero */
64a88d5d 5293 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 5294 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
5295 tcg_gen_movi_i64(cpu_dst_64, 0);
5296 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
5297 break;
5298 case 0x061: /* VIS I fzeros */
64a88d5d 5299 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 5300 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
5301 tcg_gen_movi_i32(cpu_dst_32, 0);
5302 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 5303 break;
e9ebed4d 5304 case 0x062: /* VIS I fnor */
64a88d5d 5305 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5306 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
e9ebed4d
BS
5307 break;
5308 case 0x063: /* VIS I fnors */
64a88d5d 5309 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5310 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
e9ebed4d
BS
5311 break;
5312 case 0x064: /* VIS I fandnot2 */
64a88d5d 5313 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5314 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
e9ebed4d
BS
5315 break;
5316 case 0x065: /* VIS I fandnot2s */
64a88d5d 5317 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5318 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
e9ebed4d
BS
5319 break;
5320 case 0x066: /* VIS I fnot2 */
64a88d5d 5321 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5322 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
e9ebed4d
BS
5323 break;
5324 case 0x067: /* VIS I fnot2s */
64a88d5d 5325 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5326 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
e9ebed4d
BS
5327 break;
5328 case 0x068: /* VIS I fandnot1 */
64a88d5d 5329 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5330 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
e9ebed4d
BS
5331 break;
5332 case 0x069: /* VIS I fandnot1s */
64a88d5d 5333 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5334 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
e9ebed4d
BS
5335 break;
5336 case 0x06a: /* VIS I fnot1 */
64a88d5d 5337 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5338 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
e9ebed4d
BS
5339 break;
5340 case 0x06b: /* VIS I fnot1s */
64a88d5d 5341 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5342 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
e9ebed4d
BS
5343 break;
5344 case 0x06c: /* VIS I fxor */
64a88d5d 5345 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5346 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
e9ebed4d
BS
5347 break;
5348 case 0x06d: /* VIS I fxors */
64a88d5d 5349 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5350 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
e9ebed4d
BS
5351 break;
5352 case 0x06e: /* VIS I fnand */
64a88d5d 5353 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5354 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
e9ebed4d
BS
5355 break;
5356 case 0x06f: /* VIS I fnands */
64a88d5d 5357 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5358 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
e9ebed4d
BS
5359 break;
5360 case 0x070: /* VIS I fand */
64a88d5d 5361 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5362 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
e9ebed4d
BS
5363 break;
5364 case 0x071: /* VIS I fands */
64a88d5d 5365 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5366 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
e9ebed4d
BS
5367 break;
5368 case 0x072: /* VIS I fxnor */
64a88d5d 5369 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5370 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
e9ebed4d
BS
5371 break;
5372 case 0x073: /* VIS I fxnors */
64a88d5d 5373 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5374 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
e9ebed4d 5375 break;
3299908c 5376 case 0x074: /* VIS I fsrc1 */
64a88d5d 5377 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
5378 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5379 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
5380 break;
5381 case 0x075: /* VIS I fsrc1s */
64a88d5d 5382 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
5383 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
5384 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 5385 break;
e9ebed4d 5386 case 0x076: /* VIS I fornot2 */
64a88d5d 5387 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5388 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
e9ebed4d
BS
5389 break;
5390 case 0x077: /* VIS I fornot2s */
64a88d5d 5391 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5392 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
e9ebed4d 5393 break;
3299908c 5394 case 0x078: /* VIS I fsrc2 */
64a88d5d 5395 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
5396 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
5397 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
5398 break;
5399 case 0x079: /* VIS I fsrc2s */
64a88d5d 5400 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
5401 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
5402 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 5403 break;
e9ebed4d 5404 case 0x07a: /* VIS I fornot1 */
64a88d5d 5405 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5406 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
e9ebed4d
BS
5407 break;
5408 case 0x07b: /* VIS I fornot1s */
64a88d5d 5409 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5410 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
e9ebed4d
BS
5411 break;
5412 case 0x07c: /* VIS I for */
64a88d5d 5413 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5414 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
e9ebed4d
BS
5415 break;
5416 case 0x07d: /* VIS I fors */
64a88d5d 5417 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 5418 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
e9ebed4d 5419 break;
3299908c 5420 case 0x07e: /* VIS I fone */
64a88d5d 5421 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 5422 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
5423 tcg_gen_movi_i64(cpu_dst_64, -1);
5424 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
5425 break;
5426 case 0x07f: /* VIS I fones */
64a88d5d 5427 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 5428 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
5429 tcg_gen_movi_i32(cpu_dst_32, -1);
5430 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 5431 break;
e9ebed4d
BS
5432 case 0x080: /* VIS I shutdown */
5433 case 0x081: /* VIS II siam */
5434 // XXX
5435 goto illegal_insn;
3299908c
BS
5436 default:
5437 goto illegal_insn;
5438 }
fcc72045 5439#endif
0f8a249a 5440 } else {
8f75b8a4 5441 goto illegal_insn; /* in decodetree */
cf495bcf 5442 }
0f8a249a
BS
5443 }
5444 break;
5445 case 3: /* load/store instructions */
5446 {
5447 unsigned int xop = GET_FIELD(insn, 7, 12);
5e6ed439
RH
5448 /* ??? gen_address_mask prevents us from using a source
5449 register directly. Always generate a temporary. */
52123f14 5450 TCGv cpu_addr = tcg_temp_new();
9322a4bf 5451
5e6ed439
RH
5452 tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
5453 if (xop == 0x3c || xop == 0x3e) {
5454 /* V9 casa/casxa : no offset */
71817e48 5455 } else if (IS_IMM) { /* immediate */
67526b20 5456 simm = GET_FIELDs(insn, 19, 31);
5e6ed439
RH
5457 if (simm != 0) {
5458 tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
5459 }
0f8a249a
BS
5460 } else { /* register */
5461 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 5462 if (rs2 != 0) {
5e6ed439 5463 tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
97ea2859 5464 }
0f8a249a 5465 }
2f2ecb83
BS
5466 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
5467 (xop > 0x17 && xop <= 0x1d ) ||
5468 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
81634eea
RH
5469 TCGv cpu_val = gen_dest_gpr(dc, rd);
5470
0f8a249a 5471 switch (xop) {
b89e94af 5472 case 0x0: /* ld, V9 lduw, load unsigned word */
b89e94af 5473 case 0x1: /* ldub, load unsigned byte */
b89e94af 5474 case 0x2: /* lduh, load unsigned halfword */
b89e94af 5475 case 0x3: /* ldd, load double word */
b89e94af 5476 case 0x9: /* ldsb, load signed byte */
b89e94af 5477 case 0xa: /* ldsh, load signed halfword */
0880d20b
RH
5478 g_assert_not_reached(); /* in decodetree */
5479 case 0x08: /* V9 ldsw */
5480 case 0x0b: /* V9 ldx */
5481 goto illegal_insn; /* in decodetree */
fbb4bbb6
RH
5482 case 0xd: /* ldstub */
5483 gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5484 break;
de9e9d9f
RH
5485 case 0x0f:
5486 /* swap, swap register with memory. Also atomically */
4fb554bc
RH
5487 cpu_src1 = gen_load_gpr(dc, rd);
5488 gen_swap(dc, cpu_val, cpu_src1, cpu_addr,
5489 dc->mem_idx, MO_TEUL);
0f8a249a 5490 break;
3475187d 5491#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 5492 case 0x10: /* lda, V9 lduwa, load word alternate */
1d65b0f5 5493 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
0f8a249a 5494 break;
b89e94af 5495 case 0x11: /* lduba, load unsigned byte alternate */
1d65b0f5 5496 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
0f8a249a 5497 break;
b89e94af 5498 case 0x12: /* lduha, load unsigned halfword alternate */
1d65b0f5 5499 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
0f8a249a 5500 break;
b89e94af 5501 case 0x13: /* ldda, load double word alternate */
7ec1e5ea 5502 if (rd & 1) {
d4218d99 5503 goto illegal_insn;
7ec1e5ea 5504 }
e4dc0052 5505 gen_ldda_asi(dc, cpu_addr, insn, rd);
db166940 5506 goto skip_move;
b89e94af 5507 case 0x19: /* ldsba, load signed byte alternate */
1d65b0f5 5508 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
0f8a249a 5509 break;
b89e94af 5510 case 0x1a: /* ldsha, load signed halfword alternate */
1d65b0f5 5511 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESW);
0f8a249a
BS
5512 break;
5513 case 0x1d: /* ldstuba -- XXX: should be atomically */
22e70060 5514 gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
0f8a249a 5515 break;
b89e94af 5516 case 0x1f: /* swapa, swap reg with alt. memory. Also
77f193da 5517 atomically */
06828032 5518 cpu_src1 = gen_load_gpr(dc, rd);
22e70060 5519 gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
0f8a249a 5520 break;
3475187d
FB
5521#endif
5522#ifdef TARGET_SPARC64
0f8a249a 5523 case 0x18: /* V9 ldswa */
1d65b0f5 5524 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
0f8a249a
BS
5525 break;
5526 case 0x1b: /* V9 ldxa */
fc313c64 5527 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ);
0f8a249a
BS
5528 break;
5529 case 0x2d: /* V9 prefetch, no effect */
5530 goto skip_move;
5531 case 0x30: /* V9 ldfa */
5b12f1e8 5532 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5533 goto jmp_insn;
5534 }
22e70060 5535 gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
f9c816c0 5536 gen_update_fprs_dirty(dc, rd);
81ad8ba2 5537 goto skip_move;
0f8a249a 5538 case 0x33: /* V9 lddfa */
5b12f1e8 5539 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5540 goto jmp_insn;
5541 }
22e70060 5542 gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
f9c816c0 5543 gen_update_fprs_dirty(dc, DFPREG(rd));
81ad8ba2 5544 goto skip_move;
0f8a249a
BS
5545 case 0x3d: /* V9 prefetcha, no effect */
5546 goto skip_move;
5547 case 0x32: /* V9 ldqfa */
64a88d5d 5548 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5549 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5550 goto jmp_insn;
5551 }
22e70060 5552 gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
f9c816c0 5553 gen_update_fprs_dirty(dc, QFPREG(rd));
1f587329 5554 goto skip_move;
0f8a249a
BS
5555#endif
5556 default:
5557 goto illegal_insn;
5558 }
97ea2859 5559 gen_store_gpr(dc, rd, cpu_val);
db166940 5560#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 5561 skip_move: ;
3475187d 5562#endif
0f8a249a 5563 } else if (xop >= 0x20 && xop < 0x24) {
5b12f1e8 5564 if (gen_trap_ifnofpu(dc)) {
a80dde08 5565 goto jmp_insn;
5b12f1e8 5566 }
0f8a249a 5567 switch (xop) {
b89e94af 5568 case 0x20: /* ldf, load fpreg */
2cade6a3 5569 gen_address_mask(dc, cpu_addr);
ba5f5179 5570 cpu_dst_32 = gen_dest_fpr_F(dc);
cb21b4da 5571 tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
316b6783 5572 dc->mem_idx, MO_TEUL | MO_ALIGN);
208ae657 5573 gen_store_fpr_F(dc, rd, cpu_dst_32);
0f8a249a 5574 break;
3a3b925d
BS
5575 case 0x21: /* ldfsr, V9 ldxfsr */
5576#ifdef TARGET_SPARC64
2cade6a3 5577 gen_address_mask(dc, cpu_addr);
3a3b925d 5578 if (rd == 1) {
abcc7191 5579 TCGv_i64 t64 = tcg_temp_new_i64();
cb21b4da 5580 tcg_gen_qemu_ld_i64(t64, cpu_addr,
316b6783 5581 dc->mem_idx, MO_TEUQ | MO_ALIGN);
ad75a51e 5582 gen_helper_ldxfsr(cpu_fsr, tcg_env, cpu_fsr, t64);
f8641947 5583 break;
fe987e23 5584 }
f8641947 5585#endif
36ab4623 5586 cpu_dst_32 = tcg_temp_new_i32();
cb21b4da 5587 tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
316b6783 5588 dc->mem_idx, MO_TEUL | MO_ALIGN);
ad75a51e 5589 gen_helper_ldfsr(cpu_fsr, tcg_env, cpu_fsr, cpu_dst_32);
0f8a249a 5590 break;
b89e94af 5591 case 0x22: /* ldqf, load quad fpreg */
f939ffe5
RH
5592 CHECK_FPU_FEATURE(dc, FLOAT128);
5593 gen_address_mask(dc, cpu_addr);
5594 cpu_src1_64 = tcg_temp_new_i64();
cb21b4da 5595 tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
fc313c64 5596 MO_TEUQ | MO_ALIGN_4);
f939ffe5
RH
5597 tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
5598 cpu_src2_64 = tcg_temp_new_i64();
cb21b4da 5599 tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx,
fc313c64 5600 MO_TEUQ | MO_ALIGN_4);
f939ffe5 5601 gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64);
1f587329 5602 break;
b89e94af 5603 case 0x23: /* lddf, load double fpreg */
03fb8cfc 5604 gen_address_mask(dc, cpu_addr);
3886b8a3 5605 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
cb21b4da 5606 tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx,
fc313c64 5607 MO_TEUQ | MO_ALIGN_4);
03fb8cfc 5608 gen_store_fpr_D(dc, rd, cpu_dst_64);
0f8a249a
BS
5609 break;
5610 default:
5611 goto illegal_insn;
5612 }
dc1a6971 5613 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
0f8a249a 5614 xop == 0xe || xop == 0x1e) {
0880d20b 5615#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
81634eea 5616 TCGv cpu_val = gen_load_gpr(dc, rd);
0880d20b 5617#endif
81634eea 5618
0f8a249a 5619 switch (xop) {
b89e94af 5620 case 0x4: /* st, store word */
b89e94af 5621 case 0x5: /* stb, store byte */
b89e94af 5622 case 0x6: /* sth, store halfword */
b89e94af 5623 case 0x7: /* std, store double word */
0880d20b
RH
5624 g_assert_not_reached(); /* in decodetree */
5625 case 0x0e: /* V9 stx */
5626 goto illegal_insn; /* in decodetree */
3475187d 5627#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 5628 case 0x14: /* sta, V9 stwa, store word alternate */
1d65b0f5 5629 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
d39c0b99 5630 break;
b89e94af 5631 case 0x15: /* stba, store byte alternate */
1d65b0f5 5632 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
d39c0b99 5633 break;
b89e94af 5634 case 0x16: /* stha, store halfword alternate */
1d65b0f5 5635 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
d39c0b99 5636 break;
b89e94af 5637 case 0x17: /* stda, store double word alternate */
7ec1e5ea 5638 if (rd & 1) {
0f8a249a 5639 goto illegal_insn;
1a2fb1c0 5640 }
7ec1e5ea 5641 gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
d39c0b99 5642 break;
e80cfcfc 5643#endif
3475187d 5644#ifdef TARGET_SPARC64
0f8a249a 5645 case 0x1e: /* V9 stxa */
fc313c64 5646 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ);
0f8a249a 5647 break;
3475187d 5648#endif
0f8a249a
BS
5649 default:
5650 goto illegal_insn;
5651 }
5652 } else if (xop > 0x23 && xop < 0x28) {
5b12f1e8 5653 if (gen_trap_ifnofpu(dc)) {
a80dde08 5654 goto jmp_insn;
5b12f1e8 5655 }
0f8a249a 5656 switch (xop) {
b89e94af 5657 case 0x24: /* stf, store fpreg */
cb21b4da
RH
5658 gen_address_mask(dc, cpu_addr);
5659 cpu_src1_32 = gen_load_fpr_F(dc, rd);
5660 tcg_gen_qemu_st_i32(cpu_src1_32, cpu_addr,
316b6783 5661 dc->mem_idx, MO_TEUL | MO_ALIGN);
0f8a249a
BS
5662 break;
5663 case 0x25: /* stfsr, V9 stxfsr */
f8641947 5664 {
3a3b925d 5665#ifdef TARGET_SPARC64
f8641947
RH
5666 gen_address_mask(dc, cpu_addr);
5667 if (rd == 1) {
08149118 5668 tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr,
316b6783 5669 dc->mem_idx, MO_TEUQ | MO_ALIGN);
f8641947
RH
5670 break;
5671 }
3a3b925d 5672#endif
08149118 5673 tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr,
316b6783 5674 dc->mem_idx, MO_TEUL | MO_ALIGN);
f8641947 5675 }
0f8a249a 5676 break;
1f587329
BS
5677 case 0x26:
5678#ifdef TARGET_SPARC64
1f587329 5679 /* V9 stqf, store quad fpreg */
f939ffe5
RH
5680 CHECK_FPU_FEATURE(dc, FLOAT128);
5681 gen_address_mask(dc, cpu_addr);
5682 /* ??? While stqf only requires 4-byte alignment, it is
5683 legal for the cpu to signal the unaligned exception.
5684 The OS trap handler is then required to fix it up.
5685 For qemu, this avoids having to probe the second page
5686 before performing the first write. */
5687 cpu_src1_64 = gen_load_fpr_Q0(dc, rd);
5688 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
fc313c64 5689 dc->mem_idx, MO_TEUQ | MO_ALIGN_16);
f939ffe5
RH
5690 tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
5691 cpu_src2_64 = gen_load_fpr_Q1(dc, rd);
5692 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
fc313c64 5693 dc->mem_idx, MO_TEUQ);
1f587329 5694 break;
1f587329
BS
5695#else /* !TARGET_SPARC64 */
5696 /* stdfq, store floating point queue */
5697#if defined(CONFIG_USER_ONLY)
5698 goto illegal_insn;
5699#else
0f8a249a
BS
5700 if (!supervisor(dc))
5701 goto priv_insn;
5b12f1e8 5702 if (gen_trap_ifnofpu(dc)) {
0f8a249a 5703 goto jmp_insn;
5b12f1e8 5704 }
0f8a249a 5705 goto nfq_insn;
1f587329 5706#endif
0f8a249a 5707#endif
b89e94af 5708 case 0x27: /* stdf, store double fpreg */
03fb8cfc
RH
5709 gen_address_mask(dc, cpu_addr);
5710 cpu_src1_64 = gen_load_fpr_D(dc, rd);
cb21b4da 5711 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
fc313c64 5712 MO_TEUQ | MO_ALIGN_4);
0f8a249a
BS
5713 break;
5714 default:
5715 goto illegal_insn;
5716 }
5717 } else if (xop > 0x33 && xop < 0x3f) {
5718 switch (xop) {
a4d17f19 5719#ifdef TARGET_SPARC64
0f8a249a 5720 case 0x34: /* V9 stfa */
5b12f1e8 5721 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5722 goto jmp_insn;
5723 }
22e70060 5724 gen_stf_asi(dc, cpu_addr, insn, 4, rd);
0f8a249a 5725 break;
1f587329 5726 case 0x36: /* V9 stqfa */
2ea815ca 5727 {
2ea815ca 5728 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5729 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5730 goto jmp_insn;
5731 }
22e70060 5732 gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
2ea815ca 5733 }
1f587329 5734 break;
0f8a249a 5735 case 0x37: /* V9 stdfa */
5b12f1e8 5736 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5737 goto jmp_insn;
5738 }
22e70060 5739 gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
0f8a249a 5740 break;
0f8a249a 5741 case 0x3e: /* V9 casxa */
a4273524
RH
5742 rs2 = GET_FIELD(insn, 27, 31);
5743 cpu_src2 = gen_load_gpr(dc, rs2);
81634eea 5744 gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd);
0f8a249a 5745 break;
16c358e9
SH
5746#endif
5747#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5748 case 0x3c: /* V9 or LEON3 casa */
5749#ifndef TARGET_SPARC64
5750 CHECK_IU_FEATURE(dc, CASA);
16c358e9
SH
5751#endif
5752 rs2 = GET_FIELD(insn, 27, 31);
5753 cpu_src2 = gen_load_gpr(dc, rs2);
5754 gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
5755 break;
0f8a249a
BS
5756#endif
5757 default:
5758 goto illegal_insn;
5759 }
a4273524 5760 } else {
0f8a249a 5761 goto illegal_insn;
a4273524 5762 }
0f8a249a
BS
5763 }
5764 break;
cf495bcf 5765 }
878cc677 5766 advance_pc(dc);
e80cfcfc 5767 jmp_insn:
a6ca81cb 5768 return;
cf495bcf 5769 illegal_insn:
4fbe0067 5770 gen_exception(dc, TT_ILL_INSN);
a6ca81cb 5771 return;
8f75b8a4 5772#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
e8af50a3 5773 priv_insn:
4fbe0067 5774 gen_exception(dc, TT_PRIV_INSN);
a6ca81cb 5775 return;
64a88d5d 5776#endif
e80cfcfc 5777 nfpu_insn:
4fbe0067 5778 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
a6ca81cb 5779 return;
64a88d5d 5780#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
9143e598 5781 nfq_insn:
4fbe0067 5782 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
a6ca81cb 5783 return;
9143e598 5784#endif
7a3f1944
FB
5785}
5786
6e61bc94 5787static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
7a3f1944 5788{
6e61bc94 5789 DisasContext *dc = container_of(dcbase, DisasContext, base);
b77af26e 5790 CPUSPARCState *env = cpu_env(cs);
6e61bc94 5791 int bound;
af00be49
EC
5792
5793 dc->pc = dc->base.pc_first;
6e61bc94 5794 dc->npc = (target_ulong)dc->base.tb->cs_base;
8393617c 5795 dc->cc_op = CC_OP_DYNAMIC;
6e61bc94 5796 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
576e1c4c 5797 dc->def = &env->def;
6e61bc94
EC
5798 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
5799 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
c9b459aa 5800#ifndef CONFIG_USER_ONLY
6e61bc94 5801 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
c9b459aa 5802#endif
a6d567e5 5803#ifdef TARGET_SPARC64
f9c816c0 5804 dc->fprs_dirty = 0;
6e61bc94 5805 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
c9b459aa 5806#ifndef CONFIG_USER_ONLY
6e61bc94 5807 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
c9b459aa 5808#endif
a6d567e5 5809#endif
6e61bc94
EC
5810 /*
5811 * if we reach a page boundary, we stop generation so that the
5812 * PC of a TT_TFAULT exception is always in the right page
5813 */
5814 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
5815 dc->base.max_insns = MIN(dc->base.max_insns, bound);
5816}
cf495bcf 5817
6e61bc94
EC
5818static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
5819{
5820}
190ce7fb 5821
6e61bc94
EC
5822static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
5823{
5824 DisasContext *dc = container_of(dcbase, DisasContext, base);
633c4283 5825 target_ulong npc = dc->npc;
667b8e29 5826
633c4283
RH
5827 if (npc & 3) {
5828 switch (npc) {
5829 case JUMP_PC:
5830 assert(dc->jump_pc[1] == dc->pc + 4);
5831 npc = dc->jump_pc[0] | JUMP_PC;
5832 break;
5833 case DYNAMIC_PC:
5834 case DYNAMIC_PC_LOOKUP:
5835 npc = DYNAMIC_PC;
5836 break;
5837 default:
5838 g_assert_not_reached();
5839 }
6e61bc94 5840 }
633c4283 5841 tcg_gen_insn_start(dc->pc, npc);
6e61bc94 5842}
b933066a 5843
6e61bc94
EC
5844static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
5845{
5846 DisasContext *dc = container_of(dcbase, DisasContext, base);
b77af26e 5847 CPUSPARCState *env = cpu_env(cs);
6e61bc94 5848 unsigned int insn;
0f8a249a 5849
4e116893 5850 insn = translator_ldl(env, &dc->base, dc->pc);
6e61bc94 5851 dc->base.pc_next += 4;
878cc677
RH
5852
5853 if (!decode(dc, insn)) {
5854 disas_sparc_legacy(dc, insn);
5855 }
e80cfcfc 5856
6e61bc94
EC
5857 if (dc->base.is_jmp == DISAS_NORETURN) {
5858 return;
5859 }
5860 if (dc->pc != dc->base.pc_next) {
5861 dc->base.is_jmp = DISAS_TOO_MANY;
b09b2fd3 5862 }
6e61bc94
EC
5863}
5864
5865static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
5866{
5867 DisasContext *dc = container_of(dcbase, DisasContext, base);
186e7890 5868 DisasDelayException *e, *e_next;
633c4283 5869 bool may_lookup;
6e61bc94 5870
46bb0137
MCA
5871 switch (dc->base.is_jmp) {
5872 case DISAS_NEXT:
5873 case DISAS_TOO_MANY:
633c4283 5874 if (((dc->pc | dc->npc) & 3) == 0) {
72cbca10 5875 /* static PC and NPC: we can use direct chaining */
2f5680ee 5876 gen_goto_tb(dc, 0, dc->pc, dc->npc);
633c4283
RH
5877 break;
5878 }
5879
930f1865 5880 may_lookup = true;
633c4283
RH
5881 if (dc->pc & 3) {
5882 switch (dc->pc) {
5883 case DYNAMIC_PC_LOOKUP:
633c4283
RH
5884 break;
5885 case DYNAMIC_PC:
5886 may_lookup = false;
5887 break;
5888 default:
5889 g_assert_not_reached();
b09b2fd3 5890 }
633c4283
RH
5891 } else {
5892 tcg_gen_movi_tl(cpu_pc, dc->pc);
633c4283
RH
5893 }
5894
930f1865
RH
5895 if (dc->npc & 3) {
5896 switch (dc->npc) {
5897 case JUMP_PC:
5898 gen_generic_branch(dc);
5899 break;
5900 case DYNAMIC_PC:
5901 may_lookup = false;
5902 break;
5903 case DYNAMIC_PC_LOOKUP:
5904 break;
5905 default:
5906 g_assert_not_reached();
5907 }
5908 } else {
5909 tcg_gen_movi_tl(cpu_npc, dc->npc);
5910 }
633c4283
RH
5911 if (may_lookup) {
5912 tcg_gen_lookup_and_goto_ptr();
5913 } else {
07ea28b4 5914 tcg_gen_exit_tb(NULL, 0);
72cbca10 5915 }
46bb0137
MCA
5916 break;
5917
5918 case DISAS_NORETURN:
5919 break;
5920
5921 case DISAS_EXIT:
5922 /* Exit TB */
5923 save_state(dc);
5924 tcg_gen_exit_tb(NULL, 0);
5925 break;
5926
5927 default:
5928 g_assert_not_reached();
72cbca10 5929 }
186e7890
RH
5930
5931 for (e = dc->delay_excp_list; e ; e = e_next) {
5932 gen_set_label(e->lab);
5933
5934 tcg_gen_movi_tl(cpu_pc, e->pc);
5935 if (e->npc % 4 == 0) {
5936 tcg_gen_movi_tl(cpu_npc, e->npc);
5937 }
5938 gen_helper_raise_exception(tcg_env, e->excp);
5939
5940 e_next = e->next;
5941 g_free(e);
5942 }
6e61bc94
EC
5943}
5944
8eb806a7
RH
5945static void sparc_tr_disas_log(const DisasContextBase *dcbase,
5946 CPUState *cpu, FILE *logfile)
6e61bc94 5947{
8eb806a7
RH
5948 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
5949 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
6e61bc94
EC
5950}
5951
5952static const TranslatorOps sparc_tr_ops = {
5953 .init_disas_context = sparc_tr_init_disas_context,
5954 .tb_start = sparc_tr_tb_start,
5955 .insn_start = sparc_tr_insn_start,
6e61bc94
EC
5956 .translate_insn = sparc_tr_translate_insn,
5957 .tb_stop = sparc_tr_tb_stop,
5958 .disas_log = sparc_tr_disas_log,
5959};
5960
597f9b2d 5961void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
306c8721 5962 target_ulong pc, void *host_pc)
6e61bc94
EC
5963{
5964 DisasContext dc = {};
5965
306c8721 5966 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
7a3f1944
FB
5967}
5968
55c3ceef 5969void sparc_tcg_init(void)
e80cfcfc 5970{
d2dc4069 5971 static const char gregnames[32][4] = {
0ea63844 5972 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
d2dc4069
RH
5973 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5974 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5975 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
f5069b26 5976 };
0ea63844 5977 static const char fregnames[32][4] = {
30038fd8
RH
5978 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5979 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5980 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5981 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5982 };
aaed909a 5983
0ea63844 5984 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
1a2fb1c0 5985#ifdef TARGET_SPARC64
0ea63844 5986 { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
0ea63844 5987 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
0ea63844
RH
5988#endif
5989 { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" },
5990 { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" },
5991 };
5992
5993 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5994#ifdef TARGET_SPARC64
5995 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
1a2fb1c0 5996#endif
0ea63844
RH
5997 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5998 { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" },
5999 { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" },
6000 { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" },
6001 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
6002 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
6003 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
6004 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
0ea63844 6005 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
0ea63844
RH
6006 };
6007
6008 unsigned int i;
6009
ad75a51e 6010 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
0ea63844
RH
6011 offsetof(CPUSPARCState, regwptr),
6012 "regwptr");
6013
6014 for (i = 0; i < ARRAY_SIZE(r32); ++i) {
ad75a51e 6015 *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
0ea63844
RH
6016 }
6017
6018 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
ad75a51e 6019 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
0ea63844
RH
6020 }
6021
f764718d 6022 cpu_regs[0] = NULL;
0ea63844 6023 for (i = 1; i < 8; ++i) {
ad75a51e 6024 cpu_regs[i] = tcg_global_mem_new(tcg_env,
d2dc4069
RH
6025 offsetof(CPUSPARCState, gregs[i]),
6026 gregnames[i]);
6027 }
6028
6029 for (i = 8; i < 32; ++i) {
6030 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
6031 (i - 8) * sizeof(target_ulong),
6032 gregnames[i]);
0ea63844
RH
6033 }
6034
6035 for (i = 0; i < TARGET_DPREGS; i++) {
ad75a51e 6036 cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
0ea63844
RH
6037 offsetof(CPUSPARCState, fpr[i]),
6038 fregnames[i]);
1a2fb1c0 6039 }
658138bc 6040}
d2856f1a 6041
f36aaa53
RH
6042void sparc_restore_state_to_opc(CPUState *cs,
6043 const TranslationBlock *tb,
6044 const uint64_t *data)
d2856f1a 6045{
f36aaa53
RH
6046 SPARCCPU *cpu = SPARC_CPU(cs);
6047 CPUSPARCState *env = &cpu->env;
bad729e2
RH
6048 target_ulong pc = data[0];
6049 target_ulong npc = data[1];
6050
6051 env->pc = pc;
6c42444f 6052 if (npc == DYNAMIC_PC) {
d2856f1a 6053 /* dynamic NPC: already stored */
6c42444f 6054 } else if (npc & JUMP_PC) {
d7da2a10
BS
6055 /* jump PC: use 'cond' and the jump targets of the translation */
6056 if (env->cond) {
6c42444f 6057 env->npc = npc & ~3;
d7da2a10 6058 } else {
6c42444f 6059 env->npc = pc + 4;
d7da2a10 6060 }
d2856f1a
AJ
6061 } else {
6062 env->npc = npc;
6063 }
6064}