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