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