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