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