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