]> git.ipfire.org Git - thirdparty/qemu.git/blame - target-sparc/translate.c
target-sparc: Implement swap_asi 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
1a2fb1c0 2016/* asi moves */
22e70060 2017#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
7ec1e5ea
RH
2018typedef enum {
2019 GET_ASI_HELPER,
2020 GET_ASI_EXCP,
f0913be0 2021 GET_ASI_DIRECT,
e4dc0052 2022 GET_ASI_DTWINX,
ca5ce572
RH
2023 GET_ASI_BLOCK,
2024 GET_ASI_SHORT,
7ec1e5ea
RH
2025} ASIType;
2026
2027typedef struct {
2028 ASIType type;
a6d567e5 2029 int asi;
f0913be0
RH
2030 int mem_idx;
2031 TCGMemOp memop;
7ec1e5ea 2032} DisasASI;
1a2fb1c0 2033
f0913be0 2034static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
7ec1e5ea
RH
2035{
2036 int asi = GET_FIELD(insn, 19, 26);
2037 ASIType type = GET_ASI_HELPER;
f0913be0 2038 int mem_idx = dc->mem_idx;
7ec1e5ea
RH
2039
2040#ifndef TARGET_SPARC64
2041 /* Before v9, all asis are immediate and privileged. */
1a2fb1c0 2042 if (IS_IMM) {
22e70060 2043 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
2044 type = GET_ASI_EXCP;
2045 } else if (supervisor(dc)
2046 /* Note that LEON accepts ASI_USERDATA in user mode, for
2047 use with CASA. Also note that previous versions of
0cc1f4bf
RH
2048 QEMU allowed (and old versions of gcc emitted) ASI_P
2049 for LEON, which is incorrect. */
2050 || (asi == ASI_USERDATA
7ec1e5ea 2051 && (dc->def->features & CPU_FEATURE_CASA))) {
f0913be0
RH
2052 switch (asi) {
2053 case ASI_USERDATA: /* User data access */
2054 mem_idx = MMU_USER_IDX;
2055 type = GET_ASI_DIRECT;
2056 break;
2057 case ASI_KERNELDATA: /* Supervisor data access */
2058 mem_idx = MMU_KERNEL_IDX;
2059 type = GET_ASI_DIRECT;
2060 break;
7f87c905
RH
2061 case ASI_M_BYPASS: /* MMU passthrough */
2062 case ASI_LEON_BYPASS: /* LEON MMU passthrough */
2063 mem_idx = MMU_PHYS_IDX;
2064 type = GET_ASI_DIRECT;
2065 break;
f0913be0 2066 }
1a2fb1c0 2067 } else {
7ec1e5ea
RH
2068 gen_exception(dc, TT_PRIV_INSN);
2069 type = GET_ASI_EXCP;
2070 }
2071#else
2072 if (IS_IMM) {
2073 asi = dc->asi;
1a2fb1c0 2074 }
f0913be0
RH
2075 /* With v9, all asis below 0x80 are privileged. */
2076 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
2077 down that bit into DisasContext. For the moment that's ok,
2078 since the direct implementations below doesn't have any ASIs
2079 in the restricted [0x30, 0x7f] range, and the check will be
2080 done properly in the helper. */
2081 if (!supervisor(dc) && asi < 0x80) {
2082 gen_exception(dc, TT_PRIV_ACT);
2083 type = GET_ASI_EXCP;
2084 } else {
2085 switch (asi) {
7f87c905
RH
2086 case ASI_REAL: /* Bypass */
2087 case ASI_REAL_IO: /* Bypass, non-cacheable */
2088 case ASI_REAL_L: /* Bypass LE */
2089 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
2090 case ASI_TWINX_REAL: /* Real address, twinx */
2091 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
34a6e13d
RH
2092 case ASI_QUAD_LDD_PHYS:
2093 case ASI_QUAD_LDD_PHYS_L:
7f87c905
RH
2094 mem_idx = MMU_PHYS_IDX;
2095 break;
f0913be0
RH
2096 case ASI_N: /* Nucleus */
2097 case ASI_NL: /* Nucleus LE */
e4dc0052
RH
2098 case ASI_TWINX_N:
2099 case ASI_TWINX_NL:
34a6e13d
RH
2100 case ASI_NUCLEUS_QUAD_LDD:
2101 case ASI_NUCLEUS_QUAD_LDD_L:
f0913be0
RH
2102 mem_idx = MMU_NUCLEUS_IDX;
2103 break;
2104 case ASI_AIUP: /* As if user primary */
2105 case ASI_AIUPL: /* As if user primary LE */
e4dc0052
RH
2106 case ASI_TWINX_AIUP:
2107 case ASI_TWINX_AIUP_L:
ca5ce572
RH
2108 case ASI_BLK_AIUP_4V:
2109 case ASI_BLK_AIUP_L_4V:
2110 case ASI_BLK_AIUP:
2111 case ASI_BLK_AIUPL:
f0913be0
RH
2112 mem_idx = MMU_USER_IDX;
2113 break;
2114 case ASI_AIUS: /* As if user secondary */
2115 case ASI_AIUSL: /* As if user secondary LE */
e4dc0052
RH
2116 case ASI_TWINX_AIUS:
2117 case ASI_TWINX_AIUS_L:
ca5ce572
RH
2118 case ASI_BLK_AIUS_4V:
2119 case ASI_BLK_AIUS_L_4V:
2120 case ASI_BLK_AIUS:
2121 case ASI_BLK_AIUSL:
f0913be0
RH
2122 mem_idx = MMU_USER_SECONDARY_IDX;
2123 break;
2124 case ASI_S: /* Secondary */
2125 case ASI_SL: /* Secondary LE */
e4dc0052
RH
2126 case ASI_TWINX_S:
2127 case ASI_TWINX_SL:
ca5ce572
RH
2128 case ASI_BLK_COMMIT_S:
2129 case ASI_BLK_S:
2130 case ASI_BLK_SL:
2131 case ASI_FL8_S:
2132 case ASI_FL8_SL:
2133 case ASI_FL16_S:
2134 case ASI_FL16_SL:
f0913be0
RH
2135 if (mem_idx == MMU_USER_IDX) {
2136 mem_idx = MMU_USER_SECONDARY_IDX;
2137 } else if (mem_idx == MMU_KERNEL_IDX) {
2138 mem_idx = MMU_KERNEL_SECONDARY_IDX;
2139 }
2140 break;
2141 case ASI_P: /* Primary */
2142 case ASI_PL: /* Primary LE */
e4dc0052
RH
2143 case ASI_TWINX_P:
2144 case ASI_TWINX_PL:
ca5ce572
RH
2145 case ASI_BLK_COMMIT_P:
2146 case ASI_BLK_P:
2147 case ASI_BLK_PL:
2148 case ASI_FL8_P:
2149 case ASI_FL8_PL:
2150 case ASI_FL16_P:
2151 case ASI_FL16_PL:
f0913be0
RH
2152 break;
2153 }
2154 switch (asi) {
7f87c905
RH
2155 case ASI_REAL:
2156 case ASI_REAL_IO:
2157 case ASI_REAL_L:
2158 case ASI_REAL_IO_L:
f0913be0
RH
2159 case ASI_N:
2160 case ASI_NL:
2161 case ASI_AIUP:
2162 case ASI_AIUPL:
2163 case ASI_AIUS:
2164 case ASI_AIUSL:
2165 case ASI_S:
2166 case ASI_SL:
2167 case ASI_P:
2168 case ASI_PL:
2169 type = GET_ASI_DIRECT;
2170 break;
7f87c905
RH
2171 case ASI_TWINX_REAL:
2172 case ASI_TWINX_REAL_L:
e4dc0052
RH
2173 case ASI_TWINX_N:
2174 case ASI_TWINX_NL:
2175 case ASI_TWINX_AIUP:
2176 case ASI_TWINX_AIUP_L:
2177 case ASI_TWINX_AIUS:
2178 case ASI_TWINX_AIUS_L:
2179 case ASI_TWINX_P:
2180 case ASI_TWINX_PL:
2181 case ASI_TWINX_S:
2182 case ASI_TWINX_SL:
34a6e13d
RH
2183 case ASI_QUAD_LDD_PHYS:
2184 case ASI_QUAD_LDD_PHYS_L:
2185 case ASI_NUCLEUS_QUAD_LDD:
2186 case ASI_NUCLEUS_QUAD_LDD_L:
e4dc0052
RH
2187 type = GET_ASI_DTWINX;
2188 break;
ca5ce572
RH
2189 case ASI_BLK_COMMIT_P:
2190 case ASI_BLK_COMMIT_S:
2191 case ASI_BLK_AIUP_4V:
2192 case ASI_BLK_AIUP_L_4V:
2193 case ASI_BLK_AIUP:
2194 case ASI_BLK_AIUPL:
2195 case ASI_BLK_AIUS_4V:
2196 case ASI_BLK_AIUS_L_4V:
2197 case ASI_BLK_AIUS:
2198 case ASI_BLK_AIUSL:
2199 case ASI_BLK_S:
2200 case ASI_BLK_SL:
2201 case ASI_BLK_P:
2202 case ASI_BLK_PL:
2203 type = GET_ASI_BLOCK;
2204 break;
2205 case ASI_FL8_S:
2206 case ASI_FL8_SL:
2207 case ASI_FL8_P:
2208 case ASI_FL8_PL:
2209 memop = MO_UB;
2210 type = GET_ASI_SHORT;
2211 break;
2212 case ASI_FL16_S:
2213 case ASI_FL16_SL:
2214 case ASI_FL16_P:
2215 case ASI_FL16_PL:
2216 memop = MO_TEUW;
2217 type = GET_ASI_SHORT;
2218 break;
f0913be0
RH
2219 }
2220 /* The little-endian asis all have bit 3 set. */
2221 if (asi & 8) {
2222 memop ^= MO_BSWAP;
2223 }
2224 }
7ec1e5ea
RH
2225#endif
2226
f0913be0 2227 return (DisasASI){ type, asi, mem_idx, memop };
0425bee5
BS
2228}
2229
22e70060 2230static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
1d65b0f5 2231 int insn, TCGMemOp memop)
0425bee5 2232{
f0913be0 2233 DisasASI da = get_asi(dc, insn, memop);
0425bee5 2234
7ec1e5ea
RH
2235 switch (da.type) {
2236 case GET_ASI_EXCP:
2237 break;
e4dc0052
RH
2238 case GET_ASI_DTWINX: /* Reserved for ldda. */
2239 gen_exception(dc, TT_ILL_INSN);
2240 break;
f0913be0
RH
2241 case GET_ASI_DIRECT:
2242 gen_address_mask(dc, addr);
2243 tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop);
2244 break;
7ec1e5ea
RH
2245 default:
2246 {
2247 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2248 TCGv_i32 r_mop = tcg_const_i32(memop);
7ec1e5ea
RH
2249
2250 save_state(dc);
22e70060 2251#ifdef TARGET_SPARC64
6850811e 2252 gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_mop);
22e70060 2253#else
7ec1e5ea
RH
2254 {
2255 TCGv_i64 t64 = tcg_temp_new_i64();
6850811e 2256 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
7ec1e5ea
RH
2257 tcg_gen_trunc_i64_tl(dst, t64);
2258 tcg_temp_free_i64(t64);
2259 }
22e70060 2260#endif
6850811e 2261 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2262 tcg_temp_free_i32(r_asi);
2263 }
2264 break;
2265 }
1a2fb1c0
BS
2266}
2267
22e70060 2268static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
1d65b0f5 2269 int insn, TCGMemOp memop)
1a2fb1c0 2270{
f0913be0 2271 DisasASI da = get_asi(dc, insn, memop);
1a2fb1c0 2272
7ec1e5ea
RH
2273 switch (da.type) {
2274 case GET_ASI_EXCP:
2275 break;
e4dc0052
RH
2276 case GET_ASI_DTWINX: /* Reserved for stda. */
2277 gen_exception(dc, TT_ILL_INSN);
2278 break;
f0913be0
RH
2279 case GET_ASI_DIRECT:
2280 gen_address_mask(dc, addr);
2281 tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
2282 break;
7ec1e5ea
RH
2283 default:
2284 {
2285 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2286 TCGv_i32 r_mop = tcg_const_i32(memop & MO_SIZE);
7ec1e5ea
RH
2287
2288 save_state(dc);
22e70060 2289#ifdef TARGET_SPARC64
6850811e 2290 gen_helper_st_asi(cpu_env, addr, src, r_asi, r_mop);
22e70060 2291#else
7ec1e5ea
RH
2292 {
2293 TCGv_i64 t64 = tcg_temp_new_i64();
2294 tcg_gen_extu_tl_i64(t64, src);
6850811e 2295 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
7ec1e5ea
RH
2296 tcg_temp_free_i64(t64);
2297 }
22e70060 2298#endif
6850811e 2299 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2300 tcg_temp_free_i32(r_asi);
2301
2302 /* A write to a TLB register may alter page maps. End the TB. */
2303 dc->npc = DYNAMIC_PC;
2304 }
2305 break;
2306 }
1a2fb1c0
BS
2307}
2308
22e70060
RH
2309static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
2310 TCGv addr, int insn)
1a2fb1c0 2311{
f0913be0 2312 DisasASI da = get_asi(dc, insn, MO_TEUL);
22e70060 2313
7ec1e5ea
RH
2314 switch (da.type) {
2315 case GET_ASI_EXCP:
2316 break;
4fb554bc
RH
2317 case GET_ASI_DIRECT:
2318 gen_swap(dc, dst, src, addr, da.mem_idx, da.memop);
2319 break;
7ec1e5ea 2320 default:
4fb554bc
RH
2321 /* ??? Should be DAE_invalid_asi. */
2322 gen_exception(dc, TT_DATA_ACCESS);
7ec1e5ea
RH
2323 break;
2324 }
1a2fb1c0
BS
2325}
2326
22e70060
RH
2327static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
2328 int insn, int rd)
2329{
f0913be0 2330 DisasASI da = get_asi(dc, insn, MO_TEUL);
7ec1e5ea
RH
2331 TCGv val1, dst;
2332 TCGv_i32 r_asi;
22e70060 2333
7ec1e5ea
RH
2334 if (da.type == GET_ASI_EXCP) {
2335 return;
2336 }
2337
2338 save_state(dc);
2339 val1 = gen_load_gpr(dc, rd);
2340 dst = gen_dest_gpr(dc, rd);
2341 r_asi = tcg_const_i32(da.asi);
22e70060
RH
2342 gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
2343 tcg_temp_free_i32(r_asi);
2344 gen_store_gpr(dc, rd, dst);
2345}
2346
2347static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
2348{
f0913be0 2349 DisasASI da = get_asi(dc, insn, MO_UB);
22e70060 2350
7ec1e5ea
RH
2351 switch (da.type) {
2352 case GET_ASI_EXCP:
2353 break;
2354 default:
2355 {
2356 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2357 TCGv_i32 r_mop = tcg_const_i32(MO_UB);
7ec1e5ea
RH
2358 TCGv_i64 s64, t64;
2359
2360 save_state(dc);
2361 t64 = tcg_temp_new_i64();
6850811e 2362 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
7ec1e5ea
RH
2363
2364 s64 = tcg_const_i64(0xff);
6850811e 2365 gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_mop);
7ec1e5ea 2366 tcg_temp_free_i64(s64);
6850811e 2367 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2368 tcg_temp_free_i32(r_asi);
2369
2370 tcg_gen_trunc_i64_tl(dst, t64);
2371 tcg_temp_free_i64(t64);
2372 }
2373 break;
2374 }
22e70060
RH
2375}
2376#endif
2377
2378#ifdef TARGET_SPARC64
2379static void gen_ldf_asi(DisasContext *dc, TCGv addr,
2380 int insn, int size, int rd)
1a2fb1c0 2381{
f0913be0 2382 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
7705091c 2383 TCGv_i32 d32;
1a2fb1c0 2384
7ec1e5ea
RH
2385 switch (da.type) {
2386 case GET_ASI_EXCP:
2387 break;
7705091c
RH
2388
2389 case GET_ASI_DIRECT:
2390 gen_address_mask(dc, addr);
2391 switch (size) {
2392 case 4:
2393 d32 = gen_dest_fpr_F(dc);
2394 tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop);
2395 gen_store_fpr_F(dc, rd, d32);
2396 break;
2397 case 8:
2398 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2399 break;
2400 case 16:
2401 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2402 tcg_gen_addi_tl(addr, addr, 8);
2403 tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
2404 break;
2405 default:
2406 g_assert_not_reached();
2407 }
2408 break;
2409
ca5ce572
RH
2410 case GET_ASI_BLOCK:
2411 /* Valid for lddfa on aligned registers only. */
2412 if (size == 8 && (rd & 7) == 0) {
80883227 2413 TCGMemOp memop;
ca5ce572
RH
2414 TCGv eight;
2415 int i;
2416
ca5ce572
RH
2417 gen_address_mask(dc, addr);
2418
80883227
RH
2419 /* The first operation checks required alignment. */
2420 memop = da.memop | MO_ALIGN_64;
ca5ce572
RH
2421 eight = tcg_const_tl(8);
2422 for (i = 0; ; ++i) {
2423 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr,
80883227 2424 da.mem_idx, memop);
ca5ce572
RH
2425 if (i == 7) {
2426 break;
2427 }
2428 tcg_gen_add_tl(addr, addr, eight);
80883227 2429 memop = da.memop;
ca5ce572
RH
2430 }
2431 tcg_temp_free(eight);
2432 } else {
2433 gen_exception(dc, TT_ILL_INSN);
2434 }
2435 break;
2436
2437 case GET_ASI_SHORT:
2438 /* Valid for lddfa only. */
2439 if (size == 8) {
2440 gen_address_mask(dc, addr);
2441 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2442 } else {
2443 gen_exception(dc, TT_ILL_INSN);
2444 }
2445 break;
2446
7ec1e5ea
RH
2447 default:
2448 {
2449 TCGv_i32 r_asi = tcg_const_i32(da.asi);
f2fe396f 2450 TCGv_i32 r_mop = tcg_const_i32(da.memop);
7ec1e5ea
RH
2451
2452 save_state(dc);
f2fe396f
RH
2453 /* According to the table in the UA2011 manual, the only
2454 other asis that are valid for ldfa/lddfa/ldqfa are
2455 the NO_FAULT asis. We still need a helper for these,
2456 but we can just use the integer asi helper for them. */
2457 switch (size) {
2458 case 4:
2459 {
2460 TCGv d64 = tcg_temp_new_i64();
2461 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop);
2462 d32 = gen_dest_fpr_F(dc);
2463 tcg_gen_extrl_i64_i32(d32, d64);
2464 tcg_temp_free_i64(d64);
2465 gen_store_fpr_F(dc, rd, d32);
2466 }
2467 break;
2468 case 8:
2469 gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop);
2470 break;
2471 case 16:
2472 gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop);
2473 tcg_gen_addi_tl(addr, addr, 8);
2474 gen_helper_ld_asi(cpu_fpr[rd/2+1], cpu_env, addr, r_asi, r_mop);
2475 break;
2476 default:
2477 g_assert_not_reached();
2478 }
2479 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2480 tcg_temp_free_i32(r_asi);
2481 }
2482 break;
2483 }
1a2fb1c0
BS
2484}
2485
22e70060
RH
2486static void gen_stf_asi(DisasContext *dc, TCGv addr,
2487 int insn, int size, int rd)
1a2fb1c0 2488{
f0913be0 2489 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
7705091c 2490 TCGv_i32 d32;
1a2fb1c0 2491
7ec1e5ea
RH
2492 switch (da.type) {
2493 case GET_ASI_EXCP:
2494 break;
7705091c
RH
2495
2496 case GET_ASI_DIRECT:
2497 gen_address_mask(dc, addr);
2498 switch (size) {
2499 case 4:
2500 d32 = gen_load_fpr_F(dc, rd);
2501 tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop);
2502 break;
2503 case 8:
2504 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2505 break;
2506 case 16:
2507 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2508 tcg_gen_addi_tl(addr, addr, 8);
2509 tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
2510 break;
2511 default:
2512 g_assert_not_reached();
2513 }
2514 break;
2515
ca5ce572
RH
2516 case GET_ASI_BLOCK:
2517 /* Valid for stdfa on aligned registers only. */
2518 if (size == 8 && (rd & 7) == 0) {
80883227 2519 TCGMemOp memop;
ca5ce572
RH
2520 TCGv eight;
2521 int i;
2522
ca5ce572
RH
2523 gen_address_mask(dc, addr);
2524
80883227
RH
2525 /* The first operation checks required alignment. */
2526 memop = da.memop | MO_ALIGN_64;
ca5ce572
RH
2527 eight = tcg_const_tl(8);
2528 for (i = 0; ; ++i) {
2529 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr,
80883227 2530 da.mem_idx, memop);
ca5ce572
RH
2531 if (i == 7) {
2532 break;
2533 }
2534 tcg_gen_add_tl(addr, addr, eight);
80883227 2535 memop = da.memop;
ca5ce572
RH
2536 }
2537 tcg_temp_free(eight);
2538 } else {
2539 gen_exception(dc, TT_ILL_INSN);
2540 }
2541 break;
2542
2543 case GET_ASI_SHORT:
2544 /* Valid for stdfa only. */
2545 if (size == 8) {
2546 gen_address_mask(dc, addr);
2547 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2548 } else {
2549 gen_exception(dc, TT_ILL_INSN);
2550 }
2551 break;
2552
7ec1e5ea 2553 default:
f2fe396f
RH
2554 /* According to the table in the UA2011 manual, the only
2555 other asis that are valid for ldfa/lddfa/ldqfa are
2556 the PST* asis, which aren't currently handled. */
2557 gen_exception(dc, TT_ILL_INSN);
7ec1e5ea
RH
2558 break;
2559 }
1a2fb1c0
BS
2560}
2561
e4dc0052 2562static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
1a2fb1c0 2563{
f0913be0 2564 DisasASI da = get_asi(dc, insn, MO_TEQ);
e4dc0052
RH
2565 TCGv_i64 hi = gen_dest_gpr(dc, rd);
2566 TCGv_i64 lo = gen_dest_gpr(dc, rd + 1);
1a2fb1c0 2567
7ec1e5ea
RH
2568 switch (da.type) {
2569 case GET_ASI_EXCP:
e4dc0052
RH
2570 return;
2571
2572 case GET_ASI_DTWINX:
e4dc0052 2573 gen_address_mask(dc, addr);
80883227 2574 tcg_gen_qemu_ld_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16);
e4dc0052
RH
2575 tcg_gen_addi_tl(addr, addr, 8);
2576 tcg_gen_qemu_ld_i64(lo, addr, da.mem_idx, da.memop);
7ec1e5ea 2577 break;
e4dc0052
RH
2578
2579 case GET_ASI_DIRECT:
2580 {
2581 TCGv_i64 tmp = tcg_temp_new_i64();
2582
2583 gen_address_mask(dc, addr);
2584 tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop);
2585
2586 /* Note that LE ldda acts as if each 32-bit register
2587 result is byte swapped. Having just performed one
2588 64-bit bswap, we need now to swap the writebacks. */
2589 if ((da.memop & MO_BSWAP) == MO_TE) {
2590 tcg_gen_extr32_i64(lo, hi, tmp);
2591 } else {
2592 tcg_gen_extr32_i64(hi, lo, tmp);
2593 }
2594 tcg_temp_free_i64(tmp);
2595 }
2596 break;
2597
7ec1e5ea
RH
2598 default:
2599 {
2600 TCGv_i32 r_asi = tcg_const_i32(da.asi);
7ec1e5ea
RH
2601
2602 save_state(dc);
3f4288eb 2603 gen_helper_ldda_asi(cpu_env, addr, r_asi);
7ec1e5ea 2604 tcg_temp_free_i32(r_asi);
3f4288eb 2605
e4dc0052
RH
2606 tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUSPARCState, qt0.high));
2607 tcg_gen_ld_i64(lo, cpu_env, offsetof(CPUSPARCState, qt0.low));
7ec1e5ea
RH
2608 }
2609 break;
2610 }
e4dc0052
RH
2611
2612 gen_store_gpr(dc, rd, hi);
2613 gen_store_gpr(dc, rd + 1, lo);
0425bee5
BS
2614}
2615
22e70060
RH
2616static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2617 int insn, int rd)
0425bee5 2618{
f0913be0 2619 DisasASI da = get_asi(dc, insn, MO_TEQ);
c7785e16 2620 TCGv lo = gen_load_gpr(dc, rd + 1);
a7ec4229 2621
7ec1e5ea
RH
2622 switch (da.type) {
2623 case GET_ASI_EXCP:
2624 break;
e4dc0052
RH
2625
2626 case GET_ASI_DTWINX:
e4dc0052 2627 gen_address_mask(dc, addr);
80883227 2628 tcg_gen_qemu_st_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16);
e4dc0052
RH
2629 tcg_gen_addi_tl(addr, addr, 8);
2630 tcg_gen_qemu_st_i64(lo, addr, da.mem_idx, da.memop);
2631 break;
2632
2633 case GET_ASI_DIRECT:
2634 {
2635 TCGv_i64 t64 = tcg_temp_new_i64();
2636
2637 /* Note that LE stda acts as if each 32-bit register result is
2638 byte swapped. We will perform one 64-bit LE store, so now
2639 we must swap the order of the construction. */
2640 if ((da.memop & MO_BSWAP) == MO_TE) {
2641 tcg_gen_concat32_i64(t64, lo, hi);
2642 } else {
2643 tcg_gen_concat32_i64(t64, hi, lo);
2644 }
2645 gen_address_mask(dc, addr);
2646 tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
2647 tcg_temp_free_i64(t64);
2648 }
2649 break;
2650
7ec1e5ea
RH
2651 default:
2652 {
2653 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2654 TCGv_i32 r_mop = tcg_const_i32(MO_Q);
7ec1e5ea
RH
2655 TCGv_i64 t64;
2656
2657 save_state(dc);
2658
2659 t64 = tcg_temp_new_i64();
2660 tcg_gen_concat_tl_i64(t64, lo, hi);
6850811e
RH
2661 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
2662 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2663 tcg_temp_free_i32(r_asi);
2664 tcg_temp_free_i64(t64);
2665 }
2666 break;
2667 }
1a2fb1c0
BS
2668}
2669
22e70060
RH
2670static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
2671 int insn, int rd)
1a2fb1c0 2672{
f0913be0 2673 DisasASI da = get_asi(dc, insn, MO_TEQ);
81634eea
RH
2674 TCGv val1 = gen_load_gpr(dc, rd);
2675 TCGv dst = gen_dest_gpr(dc, rd);
7ec1e5ea 2676 TCGv_i32 r_asi;
1a2fb1c0 2677
7ec1e5ea
RH
2678 if (da.type == GET_ASI_EXCP) {
2679 return;
2680 }
2681
2682 save_state(dc);
2683 r_asi = tcg_const_i32(da.asi);
81634eea 2684 gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
a7812ae4 2685 tcg_temp_free_i32(r_asi);
81634eea 2686 gen_store_gpr(dc, rd, dst);
1a2fb1c0
BS
2687}
2688
2689#elif !defined(CONFIG_USER_ONLY)
e4dc0052 2690static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
1a2fb1c0 2691{
d2dc4069
RH
2692 /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
2693 whereby "rd + 1" elicits "error: array subscript is above array".
2694 Since we have already asserted that rd is even, the semantics
2695 are unchanged. */
7ec1e5ea 2696 TCGv lo = gen_dest_gpr(dc, rd | 1);
e4dc0052 2697 TCGv hi = gen_dest_gpr(dc, rd);
7ec1e5ea 2698 TCGv_i64 t64 = tcg_temp_new_i64();
f0913be0 2699 DisasASI da = get_asi(dc, insn, MO_TEQ);
7ec1e5ea
RH
2700
2701 switch (da.type) {
2702 case GET_ASI_EXCP:
2703 tcg_temp_free_i64(t64);
2704 return;
e4dc0052
RH
2705 case GET_ASI_DIRECT:
2706 gen_address_mask(dc, addr);
2707 tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop);
2708 break;
7ec1e5ea
RH
2709 default:
2710 {
2711 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2712 TCGv_i32 r_mop = tcg_const_i32(MO_Q);
7ec1e5ea
RH
2713
2714 save_state(dc);
6850811e
RH
2715 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
2716 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2717 tcg_temp_free_i32(r_asi);
2718 }
2719 break;
2720 }
c7785e16 2721
7ec1e5ea 2722 tcg_gen_extr_i64_i32(lo, hi, t64);
1ec789ab 2723 tcg_temp_free_i64(t64);
7ec1e5ea 2724 gen_store_gpr(dc, rd | 1, lo);
c7785e16 2725 gen_store_gpr(dc, rd, hi);
0425bee5
BS
2726}
2727
22e70060
RH
2728static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2729 int insn, int rd)
0425bee5 2730{
f0913be0 2731 DisasASI da = get_asi(dc, insn, MO_TEQ);
c7785e16 2732 TCGv lo = gen_load_gpr(dc, rd + 1);
1ec789ab 2733 TCGv_i64 t64 = tcg_temp_new_i64();
a7ec4229 2734
1ec789ab 2735 tcg_gen_concat_tl_i64(t64, lo, hi);
7ec1e5ea
RH
2736
2737 switch (da.type) {
2738 case GET_ASI_EXCP:
2739 break;
e4dc0052
RH
2740 case GET_ASI_DIRECT:
2741 gen_address_mask(dc, addr);
2742 tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
2743 break;
7ec1e5ea
RH
2744 default:
2745 {
2746 TCGv_i32 r_asi = tcg_const_i32(da.asi);
6850811e 2747 TCGv_i32 r_mop = tcg_const_i32(MO_Q);
7ec1e5ea
RH
2748
2749 save_state(dc);
6850811e
RH
2750 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
2751 tcg_temp_free_i32(r_mop);
7ec1e5ea
RH
2752 tcg_temp_free_i32(r_asi);
2753 }
2754 break;
2755 }
2756
1ec789ab 2757 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2758}
2759#endif
2760
9d1d4e34 2761static TCGv get_src1(DisasContext *dc, unsigned int insn)
9322a4bf 2762{
9d1d4e34
RH
2763 unsigned int rs1 = GET_FIELD(insn, 13, 17);
2764 return gen_load_gpr(dc, rs1);
9322a4bf
BS
2765}
2766
9d1d4e34 2767static TCGv get_src2(DisasContext *dc, unsigned int insn)
a49d9390 2768{
a49d9390 2769 if (IS_IMM) { /* immediate */
42a8aa83 2770 target_long simm = GET_FIELDs(insn, 19, 31);
9d1d4e34
RH
2771 TCGv t = get_temp_tl(dc);
2772 tcg_gen_movi_tl(t, simm);
2773 return t;
2774 } else { /* register */
42a8aa83 2775 unsigned int rs2 = GET_FIELD(insn, 27, 31);
9d1d4e34 2776 return gen_load_gpr(dc, rs2);
a49d9390 2777 }
a49d9390
BS
2778}
2779
8194f35a 2780#ifdef TARGET_SPARC64
7e480893
RH
2781static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2782{
2783 TCGv_i32 c32, zero, dst, s1, s2;
2784
2785 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2786 or fold the comparison down to 32 bits and use movcond_i32. Choose
2787 the later. */
2788 c32 = tcg_temp_new_i32();
2789 if (cmp->is_bool) {
ecc7b3aa 2790 tcg_gen_extrl_i64_i32(c32, cmp->c1);
7e480893
RH
2791 } else {
2792 TCGv_i64 c64 = tcg_temp_new_i64();
2793 tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
ecc7b3aa 2794 tcg_gen_extrl_i64_i32(c32, c64);
7e480893
RH
2795 tcg_temp_free_i64(c64);
2796 }
2797
2798 s1 = gen_load_fpr_F(dc, rs);
2799 s2 = gen_load_fpr_F(dc, rd);
ba5f5179 2800 dst = gen_dest_fpr_F(dc);
7e480893
RH
2801 zero = tcg_const_i32(0);
2802
2803 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2804
2805 tcg_temp_free_i32(c32);
2806 tcg_temp_free_i32(zero);
2807 gen_store_fpr_F(dc, rd, dst);
2808}
2809
2810static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2811{
3886b8a3 2812 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
7e480893
RH
2813 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
2814 gen_load_fpr_D(dc, rs),
2815 gen_load_fpr_D(dc, rd));
2816 gen_store_fpr_D(dc, rd, dst);
2817}
2818
2819static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2820{
2821 int qd = QFPREG(rd);
2822 int qs = QFPREG(rs);
2823
2824 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
2825 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2826 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
2827 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2828
f9c816c0 2829 gen_update_fprs_dirty(dc, qd);
7e480893
RH
2830}
2831
a2035e83 2832#ifndef CONFIG_USER_ONLY
1bcea73e 2833static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env cpu_env)
8194f35a 2834{
b551ec04 2835 TCGv_i32 r_tl = tcg_temp_new_i32();
8194f35a
IK
2836
2837 /* load env->tl into r_tl */
b551ec04 2838 tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
8194f35a
IK
2839
2840 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
b551ec04 2841 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
8194f35a
IK
2842
2843 /* calculate offset to current trap state from env->ts, reuse r_tl */
b551ec04 2844 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
c5f9864e 2845 tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
8194f35a
IK
2846
2847 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
b551ec04
JF
2848 {
2849 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2850 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2851 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
bc57c114 2852 tcg_temp_free_ptr(r_tl_tmp);
b551ec04 2853 }
8194f35a 2854
b551ec04 2855 tcg_temp_free_i32(r_tl);
8194f35a 2856}
a2035e83 2857#endif
6c073553
RH
2858
2859static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2860 int width, bool cc, bool left)
2861{
2862 TCGv lo1, lo2, t1, t2;
2863 uint64_t amask, tabl, tabr;
2864 int shift, imask, omask;
2865
2866 if (cc) {
2867 tcg_gen_mov_tl(cpu_cc_src, s1);
2868 tcg_gen_mov_tl(cpu_cc_src2, s2);
2869 tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2870 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2871 dc->cc_op = CC_OP_SUB;
2872 }
2873
2874 /* Theory of operation: there are two tables, left and right (not to
2875 be confused with the left and right versions of the opcode). These
2876 are indexed by the low 3 bits of the inputs. To make things "easy",
2877 these tables are loaded into two constants, TABL and TABR below.
2878 The operation index = (input & imask) << shift calculates the index
2879 into the constant, while val = (table >> index) & omask calculates
2880 the value we're looking for. */
2881 switch (width) {
2882 case 8:
2883 imask = 0x7;
2884 shift = 3;
2885 omask = 0xff;
2886 if (left) {
2887 tabl = 0x80c0e0f0f8fcfeffULL;
2888 tabr = 0xff7f3f1f0f070301ULL;
2889 } else {
2890 tabl = 0x0103070f1f3f7fffULL;
2891 tabr = 0xfffefcf8f0e0c080ULL;
2892 }
2893 break;
2894 case 16:
2895 imask = 0x6;
2896 shift = 1;
2897 omask = 0xf;
2898 if (left) {
2899 tabl = 0x8cef;
2900 tabr = 0xf731;
2901 } else {
2902 tabl = 0x137f;
2903 tabr = 0xfec8;
2904 }
2905 break;
2906 case 32:
2907 imask = 0x4;
2908 shift = 0;
2909 omask = 0x3;
2910 if (left) {
2911 tabl = (2 << 2) | 3;
2912 tabr = (3 << 2) | 1;
2913 } else {
2914 tabl = (1 << 2) | 3;
2915 tabr = (3 << 2) | 2;
2916 }
2917 break;
2918 default:
2919 abort();
2920 }
2921
2922 lo1 = tcg_temp_new();
2923 lo2 = tcg_temp_new();
2924 tcg_gen_andi_tl(lo1, s1, imask);
2925 tcg_gen_andi_tl(lo2, s2, imask);
2926 tcg_gen_shli_tl(lo1, lo1, shift);
2927 tcg_gen_shli_tl(lo2, lo2, shift);
2928
2929 t1 = tcg_const_tl(tabl);
2930 t2 = tcg_const_tl(tabr);
2931 tcg_gen_shr_tl(lo1, t1, lo1);
2932 tcg_gen_shr_tl(lo2, t2, lo2);
2933 tcg_gen_andi_tl(dst, lo1, omask);
2934 tcg_gen_andi_tl(lo2, lo2, omask);
2935
2936 amask = -8;
2937 if (AM_CHECK(dc)) {
2938 amask &= 0xffffffffULL;
2939 }
2940 tcg_gen_andi_tl(s1, s1, amask);
2941 tcg_gen_andi_tl(s2, s2, amask);
2942
2943 /* We want to compute
2944 dst = (s1 == s2 ? lo1 : lo1 & lo2).
2945 We've already done dst = lo1, so this reduces to
2946 dst &= (s1 == s2 ? -1 : lo2)
2947 Which we perform by
2948 lo2 |= -(s1 == s2)
2949 dst &= lo2
2950 */
2951 tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2);
2952 tcg_gen_neg_tl(t1, t1);
2953 tcg_gen_or_tl(lo2, lo2, t1);
2954 tcg_gen_and_tl(dst, dst, lo2);
2955
2956 tcg_temp_free(lo1);
2957 tcg_temp_free(lo2);
2958 tcg_temp_free(t1);
2959 tcg_temp_free(t2);
2960}
add545ab
RH
2961
2962static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
2963{
2964 TCGv tmp = tcg_temp_new();
2965
2966 tcg_gen_add_tl(tmp, s1, s2);
2967 tcg_gen_andi_tl(dst, tmp, -8);
2968 if (left) {
2969 tcg_gen_neg_tl(tmp, tmp);
2970 }
2971 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
2972
2973 tcg_temp_free(tmp);
2974}
50c796f9
RH
2975
2976static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
2977{
2978 TCGv t1, t2, shift;
2979
2980 t1 = tcg_temp_new();
2981 t2 = tcg_temp_new();
2982 shift = tcg_temp_new();
2983
2984 tcg_gen_andi_tl(shift, gsr, 7);
2985 tcg_gen_shli_tl(shift, shift, 3);
2986 tcg_gen_shl_tl(t1, s1, shift);
2987
2988 /* A shift of 64 does not produce 0 in TCG. Divide this into a
2989 shift of (up to 63) followed by a constant shift of 1. */
2990 tcg_gen_xori_tl(shift, shift, 63);
2991 tcg_gen_shr_tl(t2, s2, shift);
2992 tcg_gen_shri_tl(t2, t2, 1);
2993
2994 tcg_gen_or_tl(dst, t1, t2);
2995
2996 tcg_temp_free(t1);
2997 tcg_temp_free(t2);
2998 tcg_temp_free(shift);
2999}
8194f35a
IK
3000#endif
3001
64a88d5d 3002#define CHECK_IU_FEATURE(dc, FEATURE) \
5578ceab 3003 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
3004 goto illegal_insn;
3005#define CHECK_FPU_FEATURE(dc, FEATURE) \
5578ceab 3006 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
3007 goto nfpu_insn;
3008
0bee699e 3009/* before an instruction, dc->pc must be static */
0184e266 3010static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cf495bcf 3011{
0184e266 3012 unsigned int opc, rs1, rs2, rd;
a4273524 3013 TCGv cpu_src1, cpu_src2;
208ae657 3014 TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
96eda024 3015 TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
67526b20 3016 target_long simm;
7a3f1944 3017
cf495bcf 3018 opc = GET_FIELD(insn, 0, 1);
cf495bcf 3019 rd = GET_FIELD(insn, 2, 6);
6ae20372 3020
cf495bcf 3021 switch (opc) {
0f8a249a
BS
3022 case 0: /* branches/sethi */
3023 {
3024 unsigned int xop = GET_FIELD(insn, 7, 9);
3025 int32_t target;
3026 switch (xop) {
3475187d 3027#ifdef TARGET_SPARC64
0f8a249a
BS
3028 case 0x1: /* V9 BPcc */
3029 {
3030 int cc;
3031
3032 target = GET_FIELD_SP(insn, 0, 18);
86f1f2ae 3033 target = sign_extend(target, 19);
0f8a249a
BS
3034 target <<= 2;
3035 cc = GET_FIELD_SP(insn, 20, 21);
3036 if (cc == 0)
d4a288ef 3037 do_branch(dc, target, insn, 0);
0f8a249a 3038 else if (cc == 2)
d4a288ef 3039 do_branch(dc, target, insn, 1);
0f8a249a
BS
3040 else
3041 goto illegal_insn;
3042 goto jmp_insn;
3043 }
3044 case 0x3: /* V9 BPr */
3045 {
3046 target = GET_FIELD_SP(insn, 0, 13) |
13846e70 3047 (GET_FIELD_SP(insn, 20, 21) << 14);
0f8a249a
BS
3048 target = sign_extend(target, 16);
3049 target <<= 2;
9d1d4e34 3050 cpu_src1 = get_src1(dc, insn);
d4a288ef 3051 do_branch_reg(dc, target, insn, cpu_src1);
0f8a249a
BS
3052 goto jmp_insn;
3053 }
3054 case 0x5: /* V9 FBPcc */
3055 {
3056 int cc = GET_FIELD_SP(insn, 20, 21);
5b12f1e8 3057 if (gen_trap_ifnofpu(dc)) {
a80dde08 3058 goto jmp_insn;
5b12f1e8 3059 }
0f8a249a
BS
3060 target = GET_FIELD_SP(insn, 0, 18);
3061 target = sign_extend(target, 19);
3062 target <<= 2;
d4a288ef 3063 do_fbranch(dc, target, insn, cc);
0f8a249a
BS
3064 goto jmp_insn;
3065 }
a4d17f19 3066#else
0f8a249a
BS
3067 case 0x7: /* CBN+x */
3068 {
3069 goto ncp_insn;
3070 }
3071#endif
3072 case 0x2: /* BN+x */
3073 {
3074 target = GET_FIELD(insn, 10, 31);
3075 target = sign_extend(target, 22);
3076 target <<= 2;
d4a288ef 3077 do_branch(dc, target, insn, 0);
0f8a249a
BS
3078 goto jmp_insn;
3079 }
3080 case 0x6: /* FBN+x */
3081 {
5b12f1e8 3082 if (gen_trap_ifnofpu(dc)) {
a80dde08 3083 goto jmp_insn;
5b12f1e8 3084 }
0f8a249a
BS
3085 target = GET_FIELD(insn, 10, 31);
3086 target = sign_extend(target, 22);
3087 target <<= 2;
d4a288ef 3088 do_fbranch(dc, target, insn, 0);
0f8a249a
BS
3089 goto jmp_insn;
3090 }
3091 case 0x4: /* SETHI */
97ea2859
RH
3092 /* Special-case %g0 because that's the canonical nop. */
3093 if (rd) {
0f8a249a 3094 uint32_t value = GET_FIELD(insn, 10, 31);
97ea2859
RH
3095 TCGv t = gen_dest_gpr(dc, rd);
3096 tcg_gen_movi_tl(t, value << 10);
3097 gen_store_gpr(dc, rd, t);
0f8a249a 3098 }
0f8a249a
BS
3099 break;
3100 case 0x0: /* UNIMPL */
3101 default:
3475187d 3102 goto illegal_insn;
0f8a249a
BS
3103 }
3104 break;
3105 }
3106 break;
dc1a6971
BS
3107 case 1: /*CALL*/
3108 {
0f8a249a 3109 target_long target = GET_FIELDs(insn, 2, 31) << 2;
97ea2859 3110 TCGv o7 = gen_dest_gpr(dc, 15);
cf495bcf 3111
97ea2859
RH
3112 tcg_gen_movi_tl(o7, dc->pc);
3113 gen_store_gpr(dc, 15, o7);
0f8a249a 3114 target += dc->pc;
13a6dd00 3115 gen_mov_pc_npc(dc);
22036a49
AT
3116#ifdef TARGET_SPARC64
3117 if (unlikely(AM_CHECK(dc))) {
3118 target &= 0xffffffffULL;
3119 }
3120#endif
0f8a249a
BS
3121 dc->npc = target;
3122 }
3123 goto jmp_insn;
3124 case 2: /* FPU & Logical Operations */
3125 {
3126 unsigned int xop = GET_FIELD(insn, 7, 12);
e7d51b34 3127 TCGv cpu_dst = get_temp_tl(dc);
de9e9d9f 3128 TCGv cpu_tmp0;
5793f2a4 3129
0f8a249a 3130 if (xop == 0x3a) { /* generate trap */
bd49ed41
RH
3131 int cond = GET_FIELD(insn, 3, 6);
3132 TCGv_i32 trap;
42a268c2
RH
3133 TCGLabel *l1 = NULL;
3134 int mask;
3475187d 3135
bd49ed41
RH
3136 if (cond == 0) {
3137 /* Trap never. */
3138 break;
cf495bcf 3139 }
b04d9890 3140
bd49ed41 3141 save_state(dc);
b04d9890 3142
bd49ed41
RH
3143 if (cond != 8) {
3144 /* Conditional trap. */
3a49e759 3145 DisasCompare cmp;
3475187d 3146#ifdef TARGET_SPARC64
0f8a249a
BS
3147 /* V9 icc/xcc */
3148 int cc = GET_FIELD_SP(insn, 11, 12);
3a49e759
RH
3149 if (cc == 0) {
3150 gen_compare(&cmp, 0, cond, dc);
3151 } else if (cc == 2) {
3152 gen_compare(&cmp, 1, cond, dc);
3153 } else {
0f8a249a 3154 goto illegal_insn;
3a49e759 3155 }
3475187d 3156#else
3a49e759 3157 gen_compare(&cmp, 0, cond, dc);
3475187d 3158#endif
b158a785 3159 l1 = gen_new_label();
3a49e759
RH
3160 tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
3161 cmp.c1, cmp.c2, l1);
3162 free_compare(&cmp);
bd49ed41 3163 }
b158a785 3164
bd49ed41
RH
3165 mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
3166 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
3167
3168 /* Don't use the normal temporaries, as they may well have
3169 gone out of scope with the branch above. While we're
3170 doing that we might as well pre-truncate to 32-bit. */
3171 trap = tcg_temp_new_i32();
3172
3173 rs1 = GET_FIELD_SP(insn, 14, 18);
3174 if (IS_IMM) {
3175 rs2 = GET_FIELD_SP(insn, 0, 6);
3176 if (rs1 == 0) {
3177 tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
3178 /* Signal that the trap value is fully constant. */
3179 mask = 0;
3180 } else {
97ea2859 3181 TCGv t1 = gen_load_gpr(dc, rs1);
bd49ed41 3182 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
3183 tcg_gen_addi_i32(trap, trap, rs2);
3184 }
3185 } else {
97ea2859 3186 TCGv t1, t2;
bd49ed41 3187 rs2 = GET_FIELD_SP(insn, 0, 4);
97ea2859
RH
3188 t1 = gen_load_gpr(dc, rs1);
3189 t2 = gen_load_gpr(dc, rs2);
bd49ed41
RH
3190 tcg_gen_add_tl(t1, t1, t2);
3191 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
3192 }
3193 if (mask != 0) {
3194 tcg_gen_andi_i32(trap, trap, mask);
3195 tcg_gen_addi_i32(trap, trap, TT_TRAP);
3196 }
3197
3198 gen_helper_raise_exception(cpu_env, trap);
3199 tcg_temp_free_i32(trap);
b158a785 3200
fe1755cb
RH
3201 if (cond == 8) {
3202 /* An unconditional trap ends the TB. */
3203 dc->is_br = 1;
3204 goto jmp_insn;
3205 } else {
3206 /* A conditional trap falls through to the next insn. */
b158a785 3207 gen_set_label(l1);
fe1755cb 3208 break;
cf495bcf
FB
3209 }
3210 } else if (xop == 0x28) {
3211 rs1 = GET_FIELD(insn, 13, 17);
3212 switch(rs1) {
3213 case 0: /* rdy */
65fe7b09
BS
3214#ifndef TARGET_SPARC64
3215 case 0x01 ... 0x0e: /* undefined in the SPARCv8
3216 manual, rdy on the microSPARC
3217 II */
3218 case 0x0f: /* stbar in the SPARCv8 manual,
3219 rdy on the microSPARC II */
3220 case 0x10 ... 0x1f: /* implementation-dependent in the
3221 SPARCv8 manual, rdy on the
3222 microSPARC II */
4a2ba232
FC
3223 /* Read Asr17 */
3224 if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
97ea2859 3225 TCGv t = gen_dest_gpr(dc, rd);
4a2ba232 3226 /* Read Asr17 for a Leon3 monoprocessor */
97ea2859
RH
3227 tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1));
3228 gen_store_gpr(dc, rd, t);
4a2ba232
FC
3229 break;
3230 }
65fe7b09 3231#endif
97ea2859 3232 gen_store_gpr(dc, rd, cpu_y);
cf495bcf 3233 break;
3475187d 3234#ifdef TARGET_SPARC64
0f8a249a 3235 case 0x2: /* V9 rdccr */
20132b96 3236 update_psr(dc);
063c3675 3237 gen_helper_rdccr(cpu_dst, cpu_env);
97ea2859 3238 gen_store_gpr(dc, rd, cpu_dst);
3475187d 3239 break;
0f8a249a 3240 case 0x3: /* V9 rdasi */
a6d567e5 3241 tcg_gen_movi_tl(cpu_dst, dc->asi);
97ea2859 3242 gen_store_gpr(dc, rd, cpu_dst);
3475187d 3243 break;
0f8a249a 3244 case 0x4: /* V9 rdtick */
ccd4a219 3245 {
a7812ae4 3246 TCGv_ptr r_tickptr;
c9a46442 3247 TCGv_i32 r_const;
ccd4a219 3248
a7812ae4 3249 r_tickptr = tcg_temp_new_ptr();
c9a46442 3250 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 3251 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3252 offsetof(CPUSPARCState, tick));
c9a46442
MCA
3253 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
3254 r_const);
a7812ae4 3255 tcg_temp_free_ptr(r_tickptr);
c9a46442 3256 tcg_temp_free_i32(r_const);
97ea2859 3257 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 3258 }
3475187d 3259 break;
0f8a249a 3260 case 0x5: /* V9 rdpc */
2ea815ca 3261 {
97ea2859 3262 TCGv t = gen_dest_gpr(dc, rd);
22036a49 3263 if (unlikely(AM_CHECK(dc))) {
97ea2859 3264 tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL);
22036a49 3265 } else {
97ea2859 3266 tcg_gen_movi_tl(t, dc->pc);
22036a49 3267 }
97ea2859 3268 gen_store_gpr(dc, rd, t);
2ea815ca 3269 }
0f8a249a
BS
3270 break;
3271 case 0x6: /* V9 rdfprs */
255e1fcb 3272 tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
97ea2859 3273 gen_store_gpr(dc, rd, cpu_dst);
3475187d 3274 break;
65fe7b09
BS
3275 case 0xf: /* V9 membar */
3276 break; /* no effect */
0f8a249a 3277 case 0x13: /* Graphics Status */
5b12f1e8 3278 if (gen_trap_ifnofpu(dc)) {
725cb90b 3279 goto jmp_insn;
5b12f1e8 3280 }
97ea2859 3281 gen_store_gpr(dc, rd, cpu_gsr);
725cb90b 3282 break;
9d926598 3283 case 0x16: /* Softint */
e86ceb0d
RH
3284 tcg_gen_ld32s_tl(cpu_dst, cpu_env,
3285 offsetof(CPUSPARCState, softint));
97ea2859 3286 gen_store_gpr(dc, rd, cpu_dst);
9d926598 3287 break;
0f8a249a 3288 case 0x17: /* Tick compare */
97ea2859 3289 gen_store_gpr(dc, rd, cpu_tick_cmpr);
83469015 3290 break;
0f8a249a 3291 case 0x18: /* System tick */
ccd4a219 3292 {
a7812ae4 3293 TCGv_ptr r_tickptr;
c9a46442 3294 TCGv_i32 r_const;
ccd4a219 3295
a7812ae4 3296 r_tickptr = tcg_temp_new_ptr();
c9a46442 3297 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 3298 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3299 offsetof(CPUSPARCState, stick));
c9a46442
MCA
3300 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
3301 r_const);
a7812ae4 3302 tcg_temp_free_ptr(r_tickptr);
c9a46442 3303 tcg_temp_free_i32(r_const);
97ea2859 3304 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 3305 }
83469015 3306 break;
0f8a249a 3307 case 0x19: /* System tick compare */
97ea2859 3308 gen_store_gpr(dc, rd, cpu_stick_cmpr);
83469015 3309 break;
0f8a249a
BS
3310 case 0x10: /* Performance Control */
3311 case 0x11: /* Performance Instrumentation Counter */
3312 case 0x12: /* Dispatch Control */
3313 case 0x14: /* Softint set, WO */
3314 case 0x15: /* Softint clear, WO */
3475187d
FB
3315#endif
3316 default:
cf495bcf
FB
3317 goto illegal_insn;
3318 }
e8af50a3 3319#if !defined(CONFIG_USER_ONLY)
e9ebed4d 3320 } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
3475187d 3321#ifndef TARGET_SPARC64
20132b96 3322 if (!supervisor(dc)) {
0f8a249a 3323 goto priv_insn;
20132b96
RH
3324 }
3325 update_psr(dc);
063c3675 3326 gen_helper_rdpsr(cpu_dst, cpu_env);
e9ebed4d 3327#else
fb79ceb9 3328 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3329 if (!hypervisor(dc))
3330 goto priv_insn;
3331 rs1 = GET_FIELD(insn, 13, 17);
3332 switch (rs1) {
3333 case 0: // hpstate
3334 // gen_op_rdhpstate();
3335 break;
3336 case 1: // htstate
3337 // gen_op_rdhtstate();
3338 break;
3339 case 3: // hintp
255e1fcb 3340 tcg_gen_mov_tl(cpu_dst, cpu_hintp);
e9ebed4d
BS
3341 break;
3342 case 5: // htba
255e1fcb 3343 tcg_gen_mov_tl(cpu_dst, cpu_htba);
e9ebed4d
BS
3344 break;
3345 case 6: // hver
255e1fcb 3346 tcg_gen_mov_tl(cpu_dst, cpu_hver);
e9ebed4d
BS
3347 break;
3348 case 31: // hstick_cmpr
255e1fcb 3349 tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
e9ebed4d
BS
3350 break;
3351 default:
3352 goto illegal_insn;
3353 }
3354#endif
97ea2859 3355 gen_store_gpr(dc, rd, cpu_dst);
e8af50a3 3356 break;
3475187d 3357 } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
de9e9d9f 3358 if (!supervisor(dc)) {
0f8a249a 3359 goto priv_insn;
de9e9d9f
RH
3360 }
3361 cpu_tmp0 = get_temp_tl(dc);
3475187d
FB
3362#ifdef TARGET_SPARC64
3363 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3364 switch (rs1) {
3365 case 0: // tpc
375ee38b 3366 {
a7812ae4 3367 TCGv_ptr r_tsptr;
375ee38b 3368
a7812ae4 3369 r_tsptr = tcg_temp_new_ptr();
8194f35a 3370 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
a7812ae4 3371 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 3372 offsetof(trap_state, tpc));
a7812ae4 3373 tcg_temp_free_ptr(r_tsptr);
375ee38b 3374 }
0f8a249a
BS
3375 break;
3376 case 1: // tnpc
375ee38b 3377 {
a7812ae4 3378 TCGv_ptr r_tsptr;
375ee38b 3379
a7812ae4 3380 r_tsptr = tcg_temp_new_ptr();
8194f35a 3381 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3382 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 3383 offsetof(trap_state, tnpc));
a7812ae4 3384 tcg_temp_free_ptr(r_tsptr);
375ee38b 3385 }
0f8a249a
BS
3386 break;
3387 case 2: // tstate
375ee38b 3388 {
a7812ae4 3389 TCGv_ptr r_tsptr;
375ee38b 3390
a7812ae4 3391 r_tsptr = tcg_temp_new_ptr();
8194f35a 3392 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3393 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 3394 offsetof(trap_state, tstate));
a7812ae4 3395 tcg_temp_free_ptr(r_tsptr);
375ee38b 3396 }
0f8a249a
BS
3397 break;
3398 case 3: // tt
375ee38b 3399 {
45778f99 3400 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
375ee38b 3401
8194f35a 3402 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
45778f99
RH
3403 tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr,
3404 offsetof(trap_state, tt));
a7812ae4 3405 tcg_temp_free_ptr(r_tsptr);
375ee38b 3406 }
0f8a249a
BS
3407 break;
3408 case 4: // tick
ccd4a219 3409 {
a7812ae4 3410 TCGv_ptr r_tickptr;
c9a46442 3411 TCGv_i32 r_const;
ccd4a219 3412
a7812ae4 3413 r_tickptr = tcg_temp_new_ptr();
c9a46442 3414 r_const = tcg_const_i32(dc->mem_idx);
ccd4a219 3415 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3416 offsetof(CPUSPARCState, tick));
c9a46442
MCA
3417 gen_helper_tick_get_count(cpu_tmp0, cpu_env,
3418 r_tickptr, r_const);
a7812ae4 3419 tcg_temp_free_ptr(r_tickptr);
c9a46442 3420 tcg_temp_free_i32(r_const);
ccd4a219 3421 }
0f8a249a
BS
3422 break;
3423 case 5: // tba
255e1fcb 3424 tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
0f8a249a
BS
3425 break;
3426 case 6: // pstate
45778f99
RH
3427 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3428 offsetof(CPUSPARCState, pstate));
0f8a249a
BS
3429 break;
3430 case 7: // tl
45778f99
RH
3431 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3432 offsetof(CPUSPARCState, tl));
0f8a249a
BS
3433 break;
3434 case 8: // pil
45778f99
RH
3435 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3436 offsetof(CPUSPARCState, psrpil));
0f8a249a
BS
3437 break;
3438 case 9: // cwp
063c3675 3439 gen_helper_rdcwp(cpu_tmp0, cpu_env);
0f8a249a
BS
3440 break;
3441 case 10: // cansave
45778f99
RH
3442 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3443 offsetof(CPUSPARCState, cansave));
0f8a249a
BS
3444 break;
3445 case 11: // canrestore
45778f99
RH
3446 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3447 offsetof(CPUSPARCState, canrestore));
0f8a249a
BS
3448 break;
3449 case 12: // cleanwin
45778f99
RH
3450 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3451 offsetof(CPUSPARCState, cleanwin));
0f8a249a
BS
3452 break;
3453 case 13: // otherwin
45778f99
RH
3454 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3455 offsetof(CPUSPARCState, otherwin));
0f8a249a
BS
3456 break;
3457 case 14: // wstate
45778f99
RH
3458 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3459 offsetof(CPUSPARCState, wstate));
0f8a249a 3460 break;
e9ebed4d 3461 case 16: // UA2005 gl
fb79ceb9 3462 CHECK_IU_FEATURE(dc, GL);
45778f99
RH
3463 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3464 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
3465 break;
3466 case 26: // UA2005 strand status
fb79ceb9 3467 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3468 if (!hypervisor(dc))
3469 goto priv_insn;
527067d8 3470 tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
e9ebed4d 3471 break;
0f8a249a 3472 case 31: // ver
255e1fcb 3473 tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
0f8a249a
BS
3474 break;
3475 case 15: // fq
3476 default:
3477 goto illegal_insn;
3478 }
3475187d 3479#else
255e1fcb 3480 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
3475187d 3481#endif
97ea2859 3482 gen_store_gpr(dc, rd, cpu_tmp0);
e8af50a3 3483 break;
3475187d
FB
3484 } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
3485#ifdef TARGET_SPARC64
063c3675 3486 gen_helper_flushw(cpu_env);
3475187d 3487#else
0f8a249a
BS
3488 if (!supervisor(dc))
3489 goto priv_insn;
97ea2859 3490 gen_store_gpr(dc, rd, cpu_tbr);
3475187d 3491#endif
e8af50a3
FB
3492 break;
3493#endif
0f8a249a 3494 } else if (xop == 0x34) { /* FPU Operations */
5b12f1e8 3495 if (gen_trap_ifnofpu(dc)) {
a80dde08 3496 goto jmp_insn;
5b12f1e8 3497 }
0f8a249a 3498 gen_op_clear_ieee_excp_and_FTT();
e8af50a3 3499 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3500 rs2 = GET_FIELD(insn, 27, 31);
3501 xop = GET_FIELD(insn, 18, 26);
02c79d78 3502
0f8a249a 3503 switch (xop) {
dc1a6971 3504 case 0x1: /* fmovs */
208ae657
RH
3505 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
3506 gen_store_fpr_F(dc, rd, cpu_src1_32);
dc1a6971
BS
3507 break;
3508 case 0x5: /* fnegs */
61f17f6e 3509 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
dc1a6971
BS
3510 break;
3511 case 0x9: /* fabss */
61f17f6e 3512 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
dc1a6971
BS
3513 break;
3514 case 0x29: /* fsqrts */
3515 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 3516 gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
dc1a6971
BS
3517 break;
3518 case 0x2a: /* fsqrtd */
3519 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 3520 gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
dc1a6971
BS
3521 break;
3522 case 0x2b: /* fsqrtq */
3523 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3524 gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
dc1a6971
BS
3525 break;
3526 case 0x41: /* fadds */
61f17f6e 3527 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
dc1a6971
BS
3528 break;
3529 case 0x42: /* faddd */
61f17f6e 3530 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
dc1a6971
BS
3531 break;
3532 case 0x43: /* faddq */
3533 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3534 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
dc1a6971
BS
3535 break;
3536 case 0x45: /* fsubs */
61f17f6e 3537 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
dc1a6971
BS
3538 break;
3539 case 0x46: /* fsubd */
61f17f6e 3540 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
dc1a6971
BS
3541 break;
3542 case 0x47: /* fsubq */
3543 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3544 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
dc1a6971
BS
3545 break;
3546 case 0x49: /* fmuls */
3547 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3548 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
dc1a6971
BS
3549 break;
3550 case 0x4a: /* fmuld */
3551 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3552 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
dc1a6971
BS
3553 break;
3554 case 0x4b: /* fmulq */
3555 CHECK_FPU_FEATURE(dc, FLOAT128);
3556 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3557 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
dc1a6971
BS
3558 break;
3559 case 0x4d: /* fdivs */
61f17f6e 3560 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
dc1a6971
BS
3561 break;
3562 case 0x4e: /* fdivd */
61f17f6e 3563 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
dc1a6971
BS
3564 break;
3565 case 0x4f: /* fdivq */
3566 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3567 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
dc1a6971
BS
3568 break;
3569 case 0x69: /* fsmuld */
3570 CHECK_FPU_FEATURE(dc, FSMULD);
61f17f6e 3571 gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
dc1a6971
BS
3572 break;
3573 case 0x6e: /* fdmulq */
3574 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3575 gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
dc1a6971
BS
3576 break;
3577 case 0xc4: /* fitos */
61f17f6e 3578 gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
dc1a6971
BS
3579 break;
3580 case 0xc6: /* fdtos */
61f17f6e 3581 gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
dc1a6971
BS
3582 break;
3583 case 0xc7: /* fqtos */
3584 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3585 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
dc1a6971
BS
3586 break;
3587 case 0xc8: /* fitod */
61f17f6e 3588 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
dc1a6971
BS
3589 break;
3590 case 0xc9: /* fstod */
61f17f6e 3591 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
dc1a6971
BS
3592 break;
3593 case 0xcb: /* fqtod */
3594 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3595 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
dc1a6971
BS
3596 break;
3597 case 0xcc: /* fitoq */
3598 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3599 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
dc1a6971
BS
3600 break;
3601 case 0xcd: /* fstoq */
3602 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3603 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
dc1a6971
BS
3604 break;
3605 case 0xce: /* fdtoq */
3606 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3607 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
dc1a6971
BS
3608 break;
3609 case 0xd1: /* fstoi */
61f17f6e 3610 gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
dc1a6971
BS
3611 break;
3612 case 0xd2: /* fdtoi */
61f17f6e 3613 gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
dc1a6971
BS
3614 break;
3615 case 0xd3: /* fqtoi */
3616 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3617 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
dc1a6971 3618 break;
3475187d 3619#ifdef TARGET_SPARC64
dc1a6971 3620 case 0x2: /* V9 fmovd */
96eda024
RH
3621 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
3622 gen_store_fpr_D(dc, rd, cpu_src1_64);
dc1a6971
BS
3623 break;
3624 case 0x3: /* V9 fmovq */
3625 CHECK_FPU_FEATURE(dc, FLOAT128);
f9c816c0 3626 gen_move_Q(dc, rd, rs2);
dc1a6971
BS
3627 break;
3628 case 0x6: /* V9 fnegd */
61f17f6e 3629 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
dc1a6971
BS
3630 break;
3631 case 0x7: /* V9 fnegq */
3632 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3633 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
dc1a6971
BS
3634 break;
3635 case 0xa: /* V9 fabsd */
61f17f6e 3636 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
dc1a6971
BS
3637 break;
3638 case 0xb: /* V9 fabsq */
3639 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3640 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
dc1a6971
BS
3641 break;
3642 case 0x81: /* V9 fstox */
61f17f6e 3643 gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
dc1a6971
BS
3644 break;
3645 case 0x82: /* V9 fdtox */
61f17f6e 3646 gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
dc1a6971
BS
3647 break;
3648 case 0x83: /* V9 fqtox */
3649 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3650 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
dc1a6971
BS
3651 break;
3652 case 0x84: /* V9 fxtos */
61f17f6e 3653 gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
dc1a6971
BS
3654 break;
3655 case 0x88: /* V9 fxtod */
61f17f6e 3656 gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
dc1a6971
BS
3657 break;
3658 case 0x8c: /* V9 fxtoq */
3659 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3660 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
dc1a6971 3661 break;
0f8a249a 3662#endif
dc1a6971
BS
3663 default:
3664 goto illegal_insn;
0f8a249a
BS
3665 }
3666 } else if (xop == 0x35) { /* FPU Operations */
3475187d 3667#ifdef TARGET_SPARC64
0f8a249a 3668 int cond;
3475187d 3669#endif
5b12f1e8 3670 if (gen_trap_ifnofpu(dc)) {
a80dde08 3671 goto jmp_insn;
5b12f1e8 3672 }
0f8a249a 3673 gen_op_clear_ieee_excp_and_FTT();
cf495bcf 3674 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3675 rs2 = GET_FIELD(insn, 27, 31);
3676 xop = GET_FIELD(insn, 18, 26);
dcf24905 3677
690995a6
RH
3678#ifdef TARGET_SPARC64
3679#define FMOVR(sz) \
3680 do { \
3681 DisasCompare cmp; \
e7c8afb9 3682 cond = GET_FIELD_SP(insn, 10, 12); \
9d1d4e34 3683 cpu_src1 = get_src1(dc, insn); \
690995a6
RH
3684 gen_compare_reg(&cmp, cond, cpu_src1); \
3685 gen_fmov##sz(dc, &cmp, rd, rs2); \
3686 free_compare(&cmp); \
3687 } while (0)
3688
3689 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
3690 FMOVR(s);
0f8a249a
BS
3691 break;
3692 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
690995a6 3693 FMOVR(d);
0f8a249a
BS
3694 break;
3695 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
64a88d5d 3696 CHECK_FPU_FEATURE(dc, FLOAT128);
690995a6 3697 FMOVR(q);
1f587329 3698 break;
0f8a249a 3699 }
690995a6 3700#undef FMOVR
0f8a249a
BS
3701#endif
3702 switch (xop) {
3475187d 3703#ifdef TARGET_SPARC64
7e480893
RH
3704#define FMOVCC(fcc, sz) \
3705 do { \
3706 DisasCompare cmp; \
714547bb 3707 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3708 gen_fcompare(&cmp, fcc, cond); \
3709 gen_fmov##sz(dc, &cmp, rd, rs2); \
3710 free_compare(&cmp); \
3711 } while (0)
3712
0f8a249a 3713 case 0x001: /* V9 fmovscc %fcc0 */
7e480893 3714 FMOVCC(0, s);
0f8a249a
BS
3715 break;
3716 case 0x002: /* V9 fmovdcc %fcc0 */
7e480893 3717 FMOVCC(0, d);
0f8a249a
BS
3718 break;
3719 case 0x003: /* V9 fmovqcc %fcc0 */
64a88d5d 3720 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3721 FMOVCC(0, q);
1f587329 3722 break;
0f8a249a 3723 case 0x041: /* V9 fmovscc %fcc1 */
7e480893 3724 FMOVCC(1, s);
0f8a249a
BS
3725 break;
3726 case 0x042: /* V9 fmovdcc %fcc1 */
7e480893 3727 FMOVCC(1, d);
0f8a249a
BS
3728 break;
3729 case 0x043: /* V9 fmovqcc %fcc1 */
64a88d5d 3730 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3731 FMOVCC(1, q);
1f587329 3732 break;
0f8a249a 3733 case 0x081: /* V9 fmovscc %fcc2 */
7e480893 3734 FMOVCC(2, s);
0f8a249a
BS
3735 break;
3736 case 0x082: /* V9 fmovdcc %fcc2 */
7e480893 3737 FMOVCC(2, d);
0f8a249a
BS
3738 break;
3739 case 0x083: /* V9 fmovqcc %fcc2 */
64a88d5d 3740 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3741 FMOVCC(2, q);
1f587329 3742 break;
0f8a249a 3743 case 0x0c1: /* V9 fmovscc %fcc3 */
7e480893 3744 FMOVCC(3, s);
0f8a249a
BS
3745 break;
3746 case 0x0c2: /* V9 fmovdcc %fcc3 */
7e480893 3747 FMOVCC(3, d);
0f8a249a
BS
3748 break;
3749 case 0x0c3: /* V9 fmovqcc %fcc3 */
64a88d5d 3750 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3751 FMOVCC(3, q);
1f587329 3752 break;
7e480893
RH
3753#undef FMOVCC
3754#define FMOVCC(xcc, sz) \
3755 do { \
3756 DisasCompare cmp; \
714547bb 3757 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3758 gen_compare(&cmp, xcc, cond, dc); \
3759 gen_fmov##sz(dc, &cmp, rd, rs2); \
3760 free_compare(&cmp); \
3761 } while (0)
19f329ad 3762
0f8a249a 3763 case 0x101: /* V9 fmovscc %icc */
7e480893 3764 FMOVCC(0, s);
0f8a249a
BS
3765 break;
3766 case 0x102: /* V9 fmovdcc %icc */
7e480893 3767 FMOVCC(0, d);
b7d69dc2 3768 break;
0f8a249a 3769 case 0x103: /* V9 fmovqcc %icc */
64a88d5d 3770 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3771 FMOVCC(0, q);
1f587329 3772 break;
0f8a249a 3773 case 0x181: /* V9 fmovscc %xcc */
7e480893 3774 FMOVCC(1, s);
0f8a249a
BS
3775 break;
3776 case 0x182: /* V9 fmovdcc %xcc */
7e480893 3777 FMOVCC(1, d);
0f8a249a
BS
3778 break;
3779 case 0x183: /* V9 fmovqcc %xcc */
64a88d5d 3780 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3781 FMOVCC(1, q);
1f587329 3782 break;
7e480893 3783#undef FMOVCC
1f587329
BS
3784#endif
3785 case 0x51: /* fcmps, V9 %fcc */
208ae657
RH
3786 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3787 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3788 gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a 3789 break;
1f587329 3790 case 0x52: /* fcmpd, V9 %fcc */
03fb8cfc
RH
3791 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3792 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3793 gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3794 break;
1f587329 3795 case 0x53: /* fcmpq, V9 %fcc */
64a88d5d 3796 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3797 gen_op_load_fpr_QT0(QFPREG(rs1));
3798 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3799 gen_op_fcmpq(rd & 3);
1f587329 3800 break;
0f8a249a 3801 case 0x55: /* fcmpes, V9 %fcc */
208ae657
RH
3802 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3803 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3804 gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a
BS
3805 break;
3806 case 0x56: /* fcmped, V9 %fcc */
03fb8cfc
RH
3807 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3808 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3809 gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3810 break;
1f587329 3811 case 0x57: /* fcmpeq, V9 %fcc */
64a88d5d 3812 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3813 gen_op_load_fpr_QT0(QFPREG(rs1));
3814 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3815 gen_op_fcmpeq(rd & 3);
1f587329 3816 break;
0f8a249a
BS
3817 default:
3818 goto illegal_insn;
3819 }
0f8a249a 3820 } else if (xop == 0x2) {
97ea2859 3821 TCGv dst = gen_dest_gpr(dc, rd);
e80cfcfc 3822 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a 3823 if (rs1 == 0) {
97ea2859 3824 /* clr/mov shortcut : or %g0, x, y -> mov x, y */
0f8a249a 3825 if (IS_IMM) { /* immediate */
67526b20 3826 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3827 tcg_gen_movi_tl(dst, simm);
3828 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
3829 } else { /* register */
3830 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3831 if (rs2 == 0) {
3832 tcg_gen_movi_tl(dst, 0);
3833 gen_store_gpr(dc, rd, dst);
3834 } else {
3835 cpu_src2 = gen_load_gpr(dc, rs2);
3836 gen_store_gpr(dc, rd, cpu_src2);
3837 }
0f8a249a 3838 }
0f8a249a 3839 } else {
9d1d4e34 3840 cpu_src1 = get_src1(dc, insn);
0f8a249a 3841 if (IS_IMM) { /* immediate */
67526b20 3842 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3843 tcg_gen_ori_tl(dst, cpu_src1, simm);
3844 gen_store_gpr(dc, rd, dst);
0f8a249a 3845 } else { /* register */
0f8a249a 3846 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3847 if (rs2 == 0) {
3848 /* mov shortcut: or x, %g0, y -> mov x, y */
3849 gen_store_gpr(dc, rd, cpu_src1);
3850 } else {
3851 cpu_src2 = gen_load_gpr(dc, rs2);
3852 tcg_gen_or_tl(dst, cpu_src1, cpu_src2);
3853 gen_store_gpr(dc, rd, dst);
3854 }
0f8a249a 3855 }
0f8a249a 3856 }
83469015 3857#ifdef TARGET_SPARC64
0f8a249a 3858 } else if (xop == 0x25) { /* sll, V9 sllx */
9d1d4e34 3859 cpu_src1 = get_src1(dc, insn);
0f8a249a 3860 if (IS_IMM) { /* immediate */
67526b20 3861 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3862 if (insn & (1 << 12)) {
67526b20 3863 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3864 } else {
67526b20 3865 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
1a2fb1c0 3866 }
0f8a249a 3867 } else { /* register */
83469015 3868 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3869 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3870 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3871 if (insn & (1 << 12)) {
6ae20372 3872 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
1a2fb1c0 3873 } else {
6ae20372 3874 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
1a2fb1c0 3875 }
01b1fa6d 3876 tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
83469015 3877 }
97ea2859 3878 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3879 } else if (xop == 0x26) { /* srl, V9 srlx */
9d1d4e34 3880 cpu_src1 = get_src1(dc, insn);
0f8a249a 3881 if (IS_IMM) { /* immediate */
67526b20 3882 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3883 if (insn & (1 << 12)) {
67526b20 3884 tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3885 } else {
6ae20372 3886 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
67526b20 3887 tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3888 }
0f8a249a 3889 } else { /* register */
83469015 3890 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3891 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3892 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3893 if (insn & (1 << 12)) {
6ae20372
BS
3894 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3895 tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3896 } else {
6ae20372
BS
3897 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3898 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3899 tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3900 }
83469015 3901 }
97ea2859 3902 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3903 } else if (xop == 0x27) { /* sra, V9 srax */
9d1d4e34 3904 cpu_src1 = get_src1(dc, insn);
0f8a249a 3905 if (IS_IMM) { /* immediate */
67526b20 3906 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3907 if (insn & (1 << 12)) {
67526b20 3908 tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3909 } else {
97ea2859 3910 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
67526b20 3911 tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3912 }
0f8a249a 3913 } else { /* register */
83469015 3914 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3915 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3916 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3917 if (insn & (1 << 12)) {
6ae20372
BS
3918 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3919 tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3920 } else {
6ae20372 3921 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
97ea2859 3922 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
6ae20372 3923 tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3924 }
83469015 3925 }
97ea2859 3926 gen_store_gpr(dc, rd, cpu_dst);
e80cfcfc 3927#endif
fcc72045 3928 } else if (xop < 0x36) {
cf495bcf 3929 if (xop < 0x20) {
9d1d4e34
RH
3930 cpu_src1 = get_src1(dc, insn);
3931 cpu_src2 = get_src2(dc, insn);
cf495bcf 3932 switch (xop & ~0x10) {
b89e94af 3933 case 0x0: /* add */
97ea2859
RH
3934 if (xop & 0x10) {
3935 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
3936 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3937 dc->cc_op = CC_OP_ADD;
41d72852 3938 } else {
97ea2859 3939 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3940 }
cf495bcf 3941 break;
b89e94af 3942 case 0x1: /* and */
97ea2859 3943 tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3944 if (xop & 0x10) {
38482a77
BS
3945 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3946 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3947 dc->cc_op = CC_OP_LOGIC;
41d72852 3948 }
cf495bcf 3949 break;
b89e94af 3950 case 0x2: /* or */
97ea2859 3951 tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3952 if (xop & 0x10) {
38482a77
BS
3953 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3954 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3955 dc->cc_op = CC_OP_LOGIC;
8393617c 3956 }
0f8a249a 3957 break;
b89e94af 3958 case 0x3: /* xor */
97ea2859 3959 tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3960 if (xop & 0x10) {
38482a77
BS
3961 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3962 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3963 dc->cc_op = CC_OP_LOGIC;
8393617c 3964 }
cf495bcf 3965 break;
b89e94af 3966 case 0x4: /* sub */
97ea2859
RH
3967 if (xop & 0x10) {
3968 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
3969 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
3970 dc->cc_op = CC_OP_SUB;
41d72852 3971 } else {
97ea2859 3972 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3973 }
cf495bcf 3974 break;
b89e94af 3975 case 0x5: /* andn */
97ea2859 3976 tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3977 if (xop & 0x10) {
38482a77
BS
3978 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3979 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3980 dc->cc_op = CC_OP_LOGIC;
8393617c 3981 }
cf495bcf 3982 break;
b89e94af 3983 case 0x6: /* orn */
97ea2859 3984 tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3985 if (xop & 0x10) {
38482a77
BS
3986 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3987 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3988 dc->cc_op = CC_OP_LOGIC;
8393617c 3989 }
cf495bcf 3990 break;
b89e94af 3991 case 0x7: /* xorn */
97ea2859 3992 tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3993 if (xop & 0x10) {
38482a77
BS
3994 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3995 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3996 dc->cc_op = CC_OP_LOGIC;
8393617c 3997 }
cf495bcf 3998 break;
b89e94af 3999 case 0x8: /* addx, V9 addc */
70c48285
RH
4000 gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
4001 (xop & 0x10));
cf495bcf 4002 break;
ded3ab80 4003#ifdef TARGET_SPARC64
0f8a249a 4004 case 0x9: /* V9 mulx */
97ea2859 4005 tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
ded3ab80
PB
4006 break;
4007#endif
b89e94af 4008 case 0xa: /* umul */
64a88d5d 4009 CHECK_IU_FEATURE(dc, MUL);
6ae20372 4010 gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
8393617c 4011 if (xop & 0x10) {
38482a77
BS
4012 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4013 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4014 dc->cc_op = CC_OP_LOGIC;
8393617c 4015 }
cf495bcf 4016 break;
b89e94af 4017 case 0xb: /* smul */
64a88d5d 4018 CHECK_IU_FEATURE(dc, MUL);
6ae20372 4019 gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
8393617c 4020 if (xop & 0x10) {
38482a77
BS
4021 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4022 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4023 dc->cc_op = CC_OP_LOGIC;
8393617c 4024 }
cf495bcf 4025 break;
b89e94af 4026 case 0xc: /* subx, V9 subc */
70c48285
RH
4027 gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
4028 (xop & 0x10));
cf495bcf 4029 break;
ded3ab80 4030#ifdef TARGET_SPARC64
0f8a249a 4031 case 0xd: /* V9 udivx */
c28ae41e 4032 gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
ded3ab80
PB
4033 break;
4034#endif
b89e94af 4035 case 0xe: /* udiv */
64a88d5d 4036 CHECK_IU_FEATURE(dc, DIV);
8393617c 4037 if (xop & 0x10) {
7a5e4488
BS
4038 gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
4039 cpu_src2);
6c78ea32 4040 dc->cc_op = CC_OP_DIV;
0fcec41e 4041 } else {
7a5e4488
BS
4042 gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
4043 cpu_src2);
8393617c 4044 }
cf495bcf 4045 break;
b89e94af 4046 case 0xf: /* sdiv */
64a88d5d 4047 CHECK_IU_FEATURE(dc, DIV);
8393617c 4048 if (xop & 0x10) {
7a5e4488
BS
4049 gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
4050 cpu_src2);
6c78ea32 4051 dc->cc_op = CC_OP_DIV;
0fcec41e 4052 } else {
7a5e4488
BS
4053 gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
4054 cpu_src2);
8393617c 4055 }
cf495bcf
FB
4056 break;
4057 default:
4058 goto illegal_insn;
4059 }
97ea2859 4060 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 4061 } else {
9d1d4e34
RH
4062 cpu_src1 = get_src1(dc, insn);
4063 cpu_src2 = get_src2(dc, insn);
cf495bcf 4064 switch (xop) {
0f8a249a 4065 case 0x20: /* taddcc */
a2ea4aa9 4066 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4067 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
4068 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
4069 dc->cc_op = CC_OP_TADD;
0f8a249a
BS
4070 break;
4071 case 0x21: /* tsubcc */
a2ea4aa9 4072 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4073 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
4074 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
4075 dc->cc_op = CC_OP_TSUB;
0f8a249a
BS
4076 break;
4077 case 0x22: /* taddcctv */
a2ea4aa9
RH
4078 gen_helper_taddcctv(cpu_dst, cpu_env,
4079 cpu_src1, cpu_src2);
97ea2859 4080 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 4081 dc->cc_op = CC_OP_TADDTV;
0f8a249a
BS
4082 break;
4083 case 0x23: /* tsubcctv */
a2ea4aa9
RH
4084 gen_helper_tsubcctv(cpu_dst, cpu_env,
4085 cpu_src1, cpu_src2);
97ea2859 4086 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 4087 dc->cc_op = CC_OP_TSUBTV;
0f8a249a 4088 break;
cf495bcf 4089 case 0x24: /* mulscc */
20132b96 4090 update_psr(dc);
6ae20372 4091 gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4092 gen_store_gpr(dc, rd, cpu_dst);
d084469c
BS
4093 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
4094 dc->cc_op = CC_OP_ADD;
cf495bcf 4095 break;
83469015 4096#ifndef TARGET_SPARC64
0f8a249a 4097 case 0x25: /* sll */
e35298cd 4098 if (IS_IMM) { /* immediate */
67526b20
BS
4099 simm = GET_FIELDs(insn, 20, 31);
4100 tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 4101 } else { /* register */
de9e9d9f 4102 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
4103 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4104 tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
4105 }
97ea2859 4106 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 4107 break;
83469015 4108 case 0x26: /* srl */
e35298cd 4109 if (IS_IMM) { /* immediate */
67526b20
BS
4110 simm = GET_FIELDs(insn, 20, 31);
4111 tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 4112 } else { /* register */
de9e9d9f 4113 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
4114 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4115 tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
4116 }
97ea2859 4117 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 4118 break;
83469015 4119 case 0x27: /* sra */
e35298cd 4120 if (IS_IMM) { /* immediate */
67526b20
BS
4121 simm = GET_FIELDs(insn, 20, 31);
4122 tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 4123 } else { /* register */
de9e9d9f 4124 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
4125 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4126 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
4127 }
97ea2859 4128 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 4129 break;
83469015 4130#endif
cf495bcf
FB
4131 case 0x30:
4132 {
de9e9d9f 4133 cpu_tmp0 = get_temp_tl(dc);
cf495bcf 4134 switch(rd) {
3475187d 4135 case 0: /* wry */
5068cbd9
BS
4136 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4137 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
cf495bcf 4138 break;
65fe7b09
BS
4139#ifndef TARGET_SPARC64
4140 case 0x01 ... 0x0f: /* undefined in the
4141 SPARCv8 manual, nop
4142 on the microSPARC
4143 II */
4144 case 0x10 ... 0x1f: /* implementation-dependent
4145 in the SPARCv8
4146 manual, nop on the
4147 microSPARC II */
d1c36ba7
RH
4148 if ((rd == 0x13) && (dc->def->features &
4149 CPU_FEATURE_POWERDOWN)) {
4150 /* LEON3 power-down */
1cf892ca 4151 save_state(dc);
d1c36ba7
RH
4152 gen_helper_power_down(cpu_env);
4153 }
65fe7b09
BS
4154 break;
4155#else
0f8a249a 4156 case 0x2: /* V9 wrccr */
7b04bd5c
RH
4157 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4158 gen_helper_wrccr(cpu_env, cpu_tmp0);
8393617c
BS
4159 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
4160 dc->cc_op = CC_OP_FLAGS;
0f8a249a
BS
4161 break;
4162 case 0x3: /* V9 wrasi */
7b04bd5c
RH
4163 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4164 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
a6d567e5
RH
4165 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4166 offsetof(CPUSPARCState, asi));
4167 /* End TB to notice changed ASI. */
4168 save_state(dc);
4169 gen_op_next_insn();
4170 tcg_gen_exit_tb(0);
4171 dc->is_br = 1;
0f8a249a
BS
4172 break;
4173 case 0x6: /* V9 wrfprs */
7b04bd5c
RH
4174 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4175 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
f9c816c0 4176 dc->fprs_dirty = 0;
66442b07 4177 save_state(dc);
3299908c 4178 gen_op_next_insn();
57fec1fe 4179 tcg_gen_exit_tb(0);
3299908c 4180 dc->is_br = 1;
0f8a249a
BS
4181 break;
4182 case 0xf: /* V9 sir, nop if user */
3475187d 4183#if !defined(CONFIG_USER_ONLY)
6ad6135d 4184 if (supervisor(dc)) {
1a2fb1c0 4185 ; // XXX
6ad6135d 4186 }
3475187d 4187#endif
0f8a249a
BS
4188 break;
4189 case 0x13: /* Graphics Status */
5b12f1e8 4190 if (gen_trap_ifnofpu(dc)) {
725cb90b 4191 goto jmp_insn;
5b12f1e8 4192 }
255e1fcb 4193 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
0f8a249a 4194 break;
9d926598
BS
4195 case 0x14: /* Softint set */
4196 if (!supervisor(dc))
4197 goto illegal_insn;
aeff993c
RH
4198 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4199 gen_helper_set_softint(cpu_env, cpu_tmp0);
9d926598
BS
4200 break;
4201 case 0x15: /* Softint clear */
4202 if (!supervisor(dc))
4203 goto illegal_insn;
aeff993c
RH
4204 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4205 gen_helper_clear_softint(cpu_env, cpu_tmp0);
9d926598
BS
4206 break;
4207 case 0x16: /* Softint write */
4208 if (!supervisor(dc))
4209 goto illegal_insn;
aeff993c
RH
4210 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4211 gen_helper_write_softint(cpu_env, cpu_tmp0);
9d926598 4212 break;
0f8a249a 4213 case 0x17: /* Tick compare */
83469015 4214#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
4215 if (!supervisor(dc))
4216 goto illegal_insn;
83469015 4217#endif
ccd4a219 4218 {
a7812ae4 4219 TCGv_ptr r_tickptr;
ccd4a219 4220
255e1fcb 4221 tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
6ae20372 4222 cpu_src2);
a7812ae4 4223 r_tickptr = tcg_temp_new_ptr();
ccd4a219 4224 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 4225 offsetof(CPUSPARCState, tick));
a7812ae4
PB
4226 gen_helper_tick_set_limit(r_tickptr,
4227 cpu_tick_cmpr);
4228 tcg_temp_free_ptr(r_tickptr);
ccd4a219 4229 }
0f8a249a
BS
4230 break;
4231 case 0x18: /* System tick */
83469015 4232#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
4233 if (!supervisor(dc))
4234 goto illegal_insn;
83469015 4235#endif
ccd4a219 4236 {
a7812ae4 4237 TCGv_ptr r_tickptr;
ccd4a219 4238
7b04bd5c 4239 tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
6ae20372 4240 cpu_src2);
a7812ae4 4241 r_tickptr = tcg_temp_new_ptr();
ccd4a219 4242 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 4243 offsetof(CPUSPARCState, stick));
a7812ae4 4244 gen_helper_tick_set_count(r_tickptr,
7b04bd5c 4245 cpu_tmp0);
a7812ae4 4246 tcg_temp_free_ptr(r_tickptr);
ccd4a219 4247 }
0f8a249a
BS
4248 break;
4249 case 0x19: /* System tick compare */
83469015 4250#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
4251 if (!supervisor(dc))
4252 goto illegal_insn;
3475187d 4253#endif
ccd4a219 4254 {
a7812ae4 4255 TCGv_ptr r_tickptr;
ccd4a219 4256
255e1fcb 4257 tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
6ae20372 4258 cpu_src2);
a7812ae4 4259 r_tickptr = tcg_temp_new_ptr();
ccd4a219 4260 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 4261 offsetof(CPUSPARCState, stick));
a7812ae4
PB
4262 gen_helper_tick_set_limit(r_tickptr,
4263 cpu_stick_cmpr);
4264 tcg_temp_free_ptr(r_tickptr);
ccd4a219 4265 }
0f8a249a 4266 break;
83469015 4267
0f8a249a 4268 case 0x10: /* Performance Control */
77f193da
BS
4269 case 0x11: /* Performance Instrumentation
4270 Counter */
0f8a249a 4271 case 0x12: /* Dispatch Control */
83469015 4272#endif
3475187d 4273 default:
cf495bcf
FB
4274 goto illegal_insn;
4275 }
4276 }
4277 break;
e8af50a3 4278#if !defined(CONFIG_USER_ONLY)
af7bf89b 4279 case 0x31: /* wrpsr, V9 saved, restored */
e8af50a3 4280 {
0f8a249a
BS
4281 if (!supervisor(dc))
4282 goto priv_insn;
3475187d 4283#ifdef TARGET_SPARC64
0f8a249a
BS
4284 switch (rd) {
4285 case 0:
063c3675 4286 gen_helper_saved(cpu_env);
0f8a249a
BS
4287 break;
4288 case 1:
063c3675 4289 gen_helper_restored(cpu_env);
0f8a249a 4290 break;
e9ebed4d
BS
4291 case 2: /* UA2005 allclean */
4292 case 3: /* UA2005 otherw */
4293 case 4: /* UA2005 normalw */
4294 case 5: /* UA2005 invalw */
4295 // XXX
0f8a249a 4296 default:
3475187d
FB
4297 goto illegal_insn;
4298 }
4299#else
de9e9d9f 4300 cpu_tmp0 = get_temp_tl(dc);
7b04bd5c
RH
4301 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4302 gen_helper_wrpsr(cpu_env, cpu_tmp0);
8393617c
BS
4303 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
4304 dc->cc_op = CC_OP_FLAGS;
66442b07 4305 save_state(dc);
9e61bde5 4306 gen_op_next_insn();
57fec1fe 4307 tcg_gen_exit_tb(0);
0f8a249a 4308 dc->is_br = 1;
3475187d 4309#endif
e8af50a3
FB
4310 }
4311 break;
af7bf89b 4312 case 0x32: /* wrwim, V9 wrpr */
e8af50a3 4313 {
0f8a249a
BS
4314 if (!supervisor(dc))
4315 goto priv_insn;
de9e9d9f 4316 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 4317 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3475187d 4318#ifdef TARGET_SPARC64
0f8a249a
BS
4319 switch (rd) {
4320 case 0: // tpc
375ee38b 4321 {
a7812ae4 4322 TCGv_ptr r_tsptr;
375ee38b 4323
a7812ae4 4324 r_tsptr = tcg_temp_new_ptr();
8194f35a 4325 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 4326 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 4327 offsetof(trap_state, tpc));
a7812ae4 4328 tcg_temp_free_ptr(r_tsptr);
375ee38b 4329 }
0f8a249a
BS
4330 break;
4331 case 1: // tnpc
375ee38b 4332 {
a7812ae4 4333 TCGv_ptr r_tsptr;
375ee38b 4334
a7812ae4 4335 r_tsptr = tcg_temp_new_ptr();
8194f35a 4336 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 4337 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 4338 offsetof(trap_state, tnpc));
a7812ae4 4339 tcg_temp_free_ptr(r_tsptr);
375ee38b 4340 }
0f8a249a
BS
4341 break;
4342 case 2: // tstate
375ee38b 4343 {
a7812ae4 4344 TCGv_ptr r_tsptr;
375ee38b 4345
a7812ae4 4346 r_tsptr = tcg_temp_new_ptr();
8194f35a 4347 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 4348 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
77f193da
BS
4349 offsetof(trap_state,
4350 tstate));
a7812ae4 4351 tcg_temp_free_ptr(r_tsptr);
375ee38b 4352 }
0f8a249a
BS
4353 break;
4354 case 3: // tt
375ee38b 4355 {
a7812ae4 4356 TCGv_ptr r_tsptr;
375ee38b 4357
a7812ae4 4358 r_tsptr = tcg_temp_new_ptr();
8194f35a 4359 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
7b9e066b
RH
4360 tcg_gen_st32_tl(cpu_tmp0, r_tsptr,
4361 offsetof(trap_state, tt));
a7812ae4 4362 tcg_temp_free_ptr(r_tsptr);
375ee38b 4363 }
0f8a249a
BS
4364 break;
4365 case 4: // tick
ccd4a219 4366 {
a7812ae4 4367 TCGv_ptr r_tickptr;
ccd4a219 4368
a7812ae4 4369 r_tickptr = tcg_temp_new_ptr();
ccd4a219 4370 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 4371 offsetof(CPUSPARCState, tick));
a7812ae4
PB
4372 gen_helper_tick_set_count(r_tickptr,
4373 cpu_tmp0);
4374 tcg_temp_free_ptr(r_tickptr);
ccd4a219 4375 }
0f8a249a
BS
4376 break;
4377 case 5: // tba
255e1fcb 4378 tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
0f8a249a
BS
4379 break;
4380 case 6: // pstate
6234ac09
RH
4381 save_state(dc);
4382 gen_helper_wrpstate(cpu_env, cpu_tmp0);
4383 dc->npc = DYNAMIC_PC;
0f8a249a
BS
4384 break;
4385 case 7: // tl
6234ac09 4386 save_state(dc);
7b9e066b 4387 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
6234ac09
RH
4388 offsetof(CPUSPARCState, tl));
4389 dc->npc = DYNAMIC_PC;
0f8a249a
BS
4390 break;
4391 case 8: // pil
063c3675 4392 gen_helper_wrpil(cpu_env, cpu_tmp0);
0f8a249a
BS
4393 break;
4394 case 9: // cwp
063c3675 4395 gen_helper_wrcwp(cpu_env, cpu_tmp0);
0f8a249a
BS
4396 break;
4397 case 10: // cansave
7b9e066b
RH
4398 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4399 offsetof(CPUSPARCState,
4400 cansave));
0f8a249a
BS
4401 break;
4402 case 11: // canrestore
7b9e066b
RH
4403 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4404 offsetof(CPUSPARCState,
4405 canrestore));
0f8a249a
BS
4406 break;
4407 case 12: // cleanwin
7b9e066b
RH
4408 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4409 offsetof(CPUSPARCState,
4410 cleanwin));
0f8a249a
BS
4411 break;
4412 case 13: // otherwin
7b9e066b
RH
4413 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4414 offsetof(CPUSPARCState,
4415 otherwin));
0f8a249a
BS
4416 break;
4417 case 14: // wstate
7b9e066b
RH
4418 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4419 offsetof(CPUSPARCState,
4420 wstate));
0f8a249a 4421 break;
e9ebed4d 4422 case 16: // UA2005 gl
fb79ceb9 4423 CHECK_IU_FEATURE(dc, GL);
7b9e066b
RH
4424 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4425 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
4426 break;
4427 case 26: // UA2005 strand status
fb79ceb9 4428 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
4429 if (!hypervisor(dc))
4430 goto priv_insn;
527067d8 4431 tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
e9ebed4d 4432 break;
0f8a249a
BS
4433 default:
4434 goto illegal_insn;
4435 }
3475187d 4436#else
7b9e066b
RH
4437 tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0);
4438 if (dc->def->nwindows != 32) {
4439 tcg_gen_andi_tl(cpu_wim, cpu_wim,
c93e7817 4440 (1 << dc->def->nwindows) - 1);
7b9e066b 4441 }
3475187d 4442#endif
e8af50a3
FB
4443 }
4444 break;
e9ebed4d 4445 case 0x33: /* wrtbr, UA2005 wrhpr */
e8af50a3 4446 {
e9ebed4d 4447#ifndef TARGET_SPARC64
0f8a249a
BS
4448 if (!supervisor(dc))
4449 goto priv_insn;
255e1fcb 4450 tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
e9ebed4d 4451#else
fb79ceb9 4452 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
4453 if (!hypervisor(dc))
4454 goto priv_insn;
de9e9d9f 4455 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 4456 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
e9ebed4d
BS
4457 switch (rd) {
4458 case 0: // hpstate
4459 // XXX gen_op_wrhpstate();
66442b07 4460 save_state(dc);
e9ebed4d 4461 gen_op_next_insn();
57fec1fe 4462 tcg_gen_exit_tb(0);
e9ebed4d
BS
4463 dc->is_br = 1;
4464 break;
4465 case 1: // htstate
4466 // XXX gen_op_wrhtstate();
4467 break;
4468 case 3: // hintp
255e1fcb 4469 tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
e9ebed4d
BS
4470 break;
4471 case 5: // htba
255e1fcb 4472 tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
e9ebed4d
BS
4473 break;
4474 case 31: // hstick_cmpr
ccd4a219 4475 {
a7812ae4 4476 TCGv_ptr r_tickptr;
ccd4a219 4477
255e1fcb 4478 tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
a7812ae4 4479 r_tickptr = tcg_temp_new_ptr();
ccd4a219 4480 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 4481 offsetof(CPUSPARCState, hstick));
a7812ae4
PB
4482 gen_helper_tick_set_limit(r_tickptr,
4483 cpu_hstick_cmpr);
4484 tcg_temp_free_ptr(r_tickptr);
ccd4a219 4485 }
e9ebed4d
BS
4486 break;
4487 case 6: // hver readonly
4488 default:
4489 goto illegal_insn;
4490 }
4491#endif
e8af50a3
FB
4492 }
4493 break;
4494#endif
3475187d 4495#ifdef TARGET_SPARC64
0f8a249a
BS
4496 case 0x2c: /* V9 movcc */
4497 {
4498 int cc = GET_FIELD_SP(insn, 11, 12);
4499 int cond = GET_FIELD_SP(insn, 14, 17);
f52879b4 4500 DisasCompare cmp;
97ea2859 4501 TCGv dst;
00f219bf 4502
0f8a249a 4503 if (insn & (1 << 18)) {
f52879b4
RH
4504 if (cc == 0) {
4505 gen_compare(&cmp, 0, cond, dc);
4506 } else if (cc == 2) {
4507 gen_compare(&cmp, 1, cond, dc);
4508 } else {
0f8a249a 4509 goto illegal_insn;
f52879b4 4510 }
0f8a249a 4511 } else {
f52879b4 4512 gen_fcompare(&cmp, cc, cond);
0f8a249a 4513 }
00f219bf 4514
f52879b4
RH
4515 /* The get_src2 above loaded the normal 13-bit
4516 immediate field, not the 11-bit field we have
4517 in movcc. But it did handle the reg case. */
4518 if (IS_IMM) {
67526b20 4519 simm = GET_FIELD_SPs(insn, 0, 10);
f52879b4 4520 tcg_gen_movi_tl(cpu_src2, simm);
00f219bf 4521 }
f52879b4 4522
97ea2859
RH
4523 dst = gen_load_gpr(dc, rd);
4524 tcg_gen_movcond_tl(cmp.cond, dst,
f52879b4 4525 cmp.c1, cmp.c2,
97ea2859 4526 cpu_src2, dst);
f52879b4 4527 free_compare(&cmp);
97ea2859 4528 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
4529 break;
4530 }
4531 case 0x2d: /* V9 sdivx */
c28ae41e 4532 gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
97ea2859 4533 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a
BS
4534 break;
4535 case 0x2e: /* V9 popc */
97ea2859
RH
4536 gen_helper_popc(cpu_dst, cpu_src2);
4537 gen_store_gpr(dc, rd, cpu_dst);
4538 break;
0f8a249a
BS
4539 case 0x2f: /* V9 movr */
4540 {
4541 int cond = GET_FIELD_SP(insn, 10, 12);
c33f80f5 4542 DisasCompare cmp;
97ea2859 4543 TCGv dst;
00f219bf 4544
c33f80f5 4545 gen_compare_reg(&cmp, cond, cpu_src1);
2ea815ca 4546
c33f80f5
RH
4547 /* The get_src2 above loaded the normal 13-bit
4548 immediate field, not the 10-bit field we have
4549 in movr. But it did handle the reg case. */
4550 if (IS_IMM) {
67526b20 4551 simm = GET_FIELD_SPs(insn, 0, 9);
c33f80f5 4552 tcg_gen_movi_tl(cpu_src2, simm);
0f8a249a 4553 }
c33f80f5 4554
97ea2859
RH
4555 dst = gen_load_gpr(dc, rd);
4556 tcg_gen_movcond_tl(cmp.cond, dst,
c33f80f5 4557 cmp.c1, cmp.c2,
97ea2859 4558 cpu_src2, dst);
c33f80f5 4559 free_compare(&cmp);
97ea2859 4560 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
4561 break;
4562 }
4563#endif
4564 default:
4565 goto illegal_insn;
4566 }
4567 }
3299908c
BS
4568 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4569#ifdef TARGET_SPARC64
4570 int opf = GET_FIELD_SP(insn, 5, 13);
4571 rs1 = GET_FIELD(insn, 13, 17);
4572 rs2 = GET_FIELD(insn, 27, 31);
5b12f1e8 4573 if (gen_trap_ifnofpu(dc)) {
e9ebed4d 4574 goto jmp_insn;
5b12f1e8 4575 }
3299908c
BS
4576
4577 switch (opf) {
e9ebed4d 4578 case 0x000: /* VIS I edge8cc */
6c073553 4579 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4580 cpu_src1 = gen_load_gpr(dc, rs1);
4581 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4582 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
97ea2859 4583 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4584 break;
e9ebed4d 4585 case 0x001: /* VIS II edge8n */
6c073553 4586 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4587 cpu_src1 = gen_load_gpr(dc, rs1);
4588 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4589 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
97ea2859 4590 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4591 break;
e9ebed4d 4592 case 0x002: /* VIS I edge8lcc */
6c073553 4593 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4594 cpu_src1 = gen_load_gpr(dc, rs1);
4595 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4596 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
97ea2859 4597 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4598 break;
e9ebed4d 4599 case 0x003: /* VIS II edge8ln */
6c073553 4600 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4601 cpu_src1 = gen_load_gpr(dc, rs1);
4602 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4603 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
97ea2859 4604 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4605 break;
e9ebed4d 4606 case 0x004: /* VIS I edge16cc */
6c073553 4607 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4608 cpu_src1 = gen_load_gpr(dc, rs1);
4609 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4610 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
97ea2859 4611 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4612 break;
e9ebed4d 4613 case 0x005: /* VIS II edge16n */
6c073553 4614 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4615 cpu_src1 = gen_load_gpr(dc, rs1);
4616 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4617 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
97ea2859 4618 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4619 break;
e9ebed4d 4620 case 0x006: /* VIS I edge16lcc */
6c073553 4621 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4622 cpu_src1 = gen_load_gpr(dc, rs1);
4623 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4624 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
97ea2859 4625 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4626 break;
e9ebed4d 4627 case 0x007: /* VIS II edge16ln */
6c073553 4628 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4629 cpu_src1 = gen_load_gpr(dc, rs1);
4630 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4631 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
97ea2859 4632 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4633 break;
e9ebed4d 4634 case 0x008: /* VIS I edge32cc */
6c073553 4635 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4636 cpu_src1 = gen_load_gpr(dc, rs1);
4637 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4638 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
97ea2859 4639 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4640 break;
e9ebed4d 4641 case 0x009: /* VIS II edge32n */
6c073553 4642 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4643 cpu_src1 = gen_load_gpr(dc, rs1);
4644 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4645 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
97ea2859 4646 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4647 break;
e9ebed4d 4648 case 0x00a: /* VIS I edge32lcc */
6c073553 4649 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4650 cpu_src1 = gen_load_gpr(dc, rs1);
4651 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4652 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
97ea2859 4653 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4654 break;
e9ebed4d 4655 case 0x00b: /* VIS II edge32ln */
6c073553 4656 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4657 cpu_src1 = gen_load_gpr(dc, rs1);
4658 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4659 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
97ea2859 4660 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4661 break;
e9ebed4d 4662 case 0x010: /* VIS I array8 */
64a88d5d 4663 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4664 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4665 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4666 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4667 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4668 break;
4669 case 0x012: /* VIS I array16 */
64a88d5d 4670 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4671 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4672 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4673 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4674 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
97ea2859 4675 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4676 break;
4677 case 0x014: /* VIS I array32 */
64a88d5d 4678 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4679 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4680 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4681 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4682 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
97ea2859 4683 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d 4684 break;
3299908c 4685 case 0x018: /* VIS I alignaddr */
64a88d5d 4686 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4687 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4688 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4689 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
97ea2859 4690 gen_store_gpr(dc, rd, cpu_dst);
3299908c
BS
4691 break;
4692 case 0x01a: /* VIS I alignaddrl */
add545ab 4693 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4694 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4695 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4696 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
97ea2859 4697 gen_store_gpr(dc, rd, cpu_dst);
add545ab
RH
4698 break;
4699 case 0x019: /* VIS II bmask */
793a137a 4700 CHECK_FPU_FEATURE(dc, VIS2);
9d1d4e34
RH
4701 cpu_src1 = gen_load_gpr(dc, rs1);
4702 cpu_src2 = gen_load_gpr(dc, rs2);
793a137a
RH
4703 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4704 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
97ea2859 4705 gen_store_gpr(dc, rd, cpu_dst);
793a137a 4706 break;
e9ebed4d 4707 case 0x020: /* VIS I fcmple16 */
64a88d5d 4708 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4709 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4710 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4711 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4712 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4713 break;
4714 case 0x022: /* VIS I fcmpne16 */
64a88d5d 4715 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4716 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4717 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4718 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4719 gen_store_gpr(dc, rd, cpu_dst);
3299908c 4720 break;
e9ebed4d 4721 case 0x024: /* VIS I fcmple32 */
64a88d5d 4722 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4723 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4724 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4725 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4726 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4727 break;
4728 case 0x026: /* VIS I fcmpne32 */
64a88d5d 4729 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4730 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4731 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4732 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4733 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4734 break;
4735 case 0x028: /* VIS I fcmpgt16 */
64a88d5d 4736 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4737 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4738 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4739 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4740 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4741 break;
4742 case 0x02a: /* VIS I fcmpeq16 */
64a88d5d 4743 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4744 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4745 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4746 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4747 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4748 break;
4749 case 0x02c: /* VIS I fcmpgt32 */
64a88d5d 4750 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4751 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4752 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4753 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4754 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4755 break;
4756 case 0x02e: /* VIS I fcmpeq32 */
64a88d5d 4757 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4758 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4759 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4760 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4761 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4762 break;
4763 case 0x031: /* VIS I fmul8x16 */
64a88d5d 4764 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4765 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
e9ebed4d
BS
4766 break;
4767 case 0x033: /* VIS I fmul8x16au */
64a88d5d 4768 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4769 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
e9ebed4d
BS
4770 break;
4771 case 0x035: /* VIS I fmul8x16al */
64a88d5d 4772 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4773 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
e9ebed4d
BS
4774 break;
4775 case 0x036: /* VIS I fmul8sux16 */
64a88d5d 4776 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4777 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
e9ebed4d
BS
4778 break;
4779 case 0x037: /* VIS I fmul8ulx16 */
64a88d5d 4780 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4781 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
e9ebed4d
BS
4782 break;
4783 case 0x038: /* VIS I fmuld8sux16 */
64a88d5d 4784 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4785 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
e9ebed4d
BS
4786 break;
4787 case 0x039: /* VIS I fmuld8ulx16 */
64a88d5d 4788 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4789 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
e9ebed4d
BS
4790 break;
4791 case 0x03a: /* VIS I fpack32 */
2dedf314
RH
4792 CHECK_FPU_FEATURE(dc, VIS1);
4793 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4794 break;
e9ebed4d 4795 case 0x03b: /* VIS I fpack16 */
2dedf314
RH
4796 CHECK_FPU_FEATURE(dc, VIS1);
4797 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4798 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4799 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4800 gen_store_fpr_F(dc, rd, cpu_dst_32);
4801 break;
e9ebed4d 4802 case 0x03d: /* VIS I fpackfix */
2dedf314
RH
4803 CHECK_FPU_FEATURE(dc, VIS1);
4804 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4805 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4806 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4807 gen_store_fpr_F(dc, rd, cpu_dst_32);
4808 break;
f888300b
RH
4809 case 0x03e: /* VIS I pdist */
4810 CHECK_FPU_FEATURE(dc, VIS1);
4811 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4812 break;
3299908c 4813 case 0x048: /* VIS I faligndata */
64a88d5d 4814 CHECK_FPU_FEATURE(dc, VIS1);
50c796f9 4815 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
3299908c 4816 break;
e9ebed4d 4817 case 0x04b: /* VIS I fpmerge */
64a88d5d 4818 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4819 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
e9ebed4d
BS
4820 break;
4821 case 0x04c: /* VIS II bshuffle */
793a137a
RH
4822 CHECK_FPU_FEATURE(dc, VIS2);
4823 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4824 break;
e9ebed4d 4825 case 0x04d: /* VIS I fexpand */
64a88d5d 4826 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4827 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
e9ebed4d
BS
4828 break;
4829 case 0x050: /* VIS I fpadd16 */
64a88d5d 4830 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4831 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
e9ebed4d
BS
4832 break;
4833 case 0x051: /* VIS I fpadd16s */
64a88d5d 4834 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4835 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
e9ebed4d
BS
4836 break;
4837 case 0x052: /* VIS I fpadd32 */
64a88d5d 4838 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4839 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
e9ebed4d
BS
4840 break;
4841 case 0x053: /* VIS I fpadd32s */
64a88d5d 4842 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4843 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
e9ebed4d
BS
4844 break;
4845 case 0x054: /* VIS I fpsub16 */
64a88d5d 4846 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4847 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
e9ebed4d
BS
4848 break;
4849 case 0x055: /* VIS I fpsub16s */
64a88d5d 4850 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4851 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
e9ebed4d
BS
4852 break;
4853 case 0x056: /* VIS I fpsub32 */
64a88d5d 4854 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4855 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
e9ebed4d
BS
4856 break;
4857 case 0x057: /* VIS I fpsub32s */
64a88d5d 4858 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4859 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
e9ebed4d 4860 break;
3299908c 4861 case 0x060: /* VIS I fzero */
64a88d5d 4862 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4863 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4864 tcg_gen_movi_i64(cpu_dst_64, 0);
4865 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4866 break;
4867 case 0x061: /* VIS I fzeros */
64a88d5d 4868 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4869 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4870 tcg_gen_movi_i32(cpu_dst_32, 0);
4871 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4872 break;
e9ebed4d 4873 case 0x062: /* VIS I fnor */
64a88d5d 4874 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4875 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
e9ebed4d
BS
4876 break;
4877 case 0x063: /* VIS I fnors */
64a88d5d 4878 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4879 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
e9ebed4d
BS
4880 break;
4881 case 0x064: /* VIS I fandnot2 */
64a88d5d 4882 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4883 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
e9ebed4d
BS
4884 break;
4885 case 0x065: /* VIS I fandnot2s */
64a88d5d 4886 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4887 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
e9ebed4d
BS
4888 break;
4889 case 0x066: /* VIS I fnot2 */
64a88d5d 4890 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4891 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
e9ebed4d
BS
4892 break;
4893 case 0x067: /* VIS I fnot2s */
64a88d5d 4894 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4895 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
e9ebed4d
BS
4896 break;
4897 case 0x068: /* VIS I fandnot1 */
64a88d5d 4898 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4899 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
e9ebed4d
BS
4900 break;
4901 case 0x069: /* VIS I fandnot1s */
64a88d5d 4902 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4903 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
e9ebed4d
BS
4904 break;
4905 case 0x06a: /* VIS I fnot1 */
64a88d5d 4906 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4907 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
e9ebed4d
BS
4908 break;
4909 case 0x06b: /* VIS I fnot1s */
64a88d5d 4910 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4911 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
e9ebed4d
BS
4912 break;
4913 case 0x06c: /* VIS I fxor */
64a88d5d 4914 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4915 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
e9ebed4d
BS
4916 break;
4917 case 0x06d: /* VIS I fxors */
64a88d5d 4918 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4919 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
e9ebed4d
BS
4920 break;
4921 case 0x06e: /* VIS I fnand */
64a88d5d 4922 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4923 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
e9ebed4d
BS
4924 break;
4925 case 0x06f: /* VIS I fnands */
64a88d5d 4926 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4927 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
e9ebed4d
BS
4928 break;
4929 case 0x070: /* VIS I fand */
64a88d5d 4930 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4931 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
e9ebed4d
BS
4932 break;
4933 case 0x071: /* VIS I fands */
64a88d5d 4934 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4935 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
e9ebed4d
BS
4936 break;
4937 case 0x072: /* VIS I fxnor */
64a88d5d 4938 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4939 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
e9ebed4d
BS
4940 break;
4941 case 0x073: /* VIS I fxnors */
64a88d5d 4942 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4943 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
e9ebed4d 4944 break;
3299908c 4945 case 0x074: /* VIS I fsrc1 */
64a88d5d 4946 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4947 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4948 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4949 break;
4950 case 0x075: /* VIS I fsrc1s */
64a88d5d 4951 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4952 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4953 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4954 break;
e9ebed4d 4955 case 0x076: /* VIS I fornot2 */
64a88d5d 4956 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4957 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
e9ebed4d
BS
4958 break;
4959 case 0x077: /* VIS I fornot2s */
64a88d5d 4960 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4961 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
e9ebed4d 4962 break;
3299908c 4963 case 0x078: /* VIS I fsrc2 */
64a88d5d 4964 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4965 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4966 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4967 break;
4968 case 0x079: /* VIS I fsrc2s */
64a88d5d 4969 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4970 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4971 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4972 break;
e9ebed4d 4973 case 0x07a: /* VIS I fornot1 */
64a88d5d 4974 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4975 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
e9ebed4d
BS
4976 break;
4977 case 0x07b: /* VIS I fornot1s */
64a88d5d 4978 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4979 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
e9ebed4d
BS
4980 break;
4981 case 0x07c: /* VIS I for */
64a88d5d 4982 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4983 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
e9ebed4d
BS
4984 break;
4985 case 0x07d: /* VIS I fors */
64a88d5d 4986 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4987 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
e9ebed4d 4988 break;
3299908c 4989 case 0x07e: /* VIS I fone */
64a88d5d 4990 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4991 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4992 tcg_gen_movi_i64(cpu_dst_64, -1);
4993 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4994 break;
4995 case 0x07f: /* VIS I fones */
64a88d5d 4996 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4997 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4998 tcg_gen_movi_i32(cpu_dst_32, -1);
4999 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 5000 break;
e9ebed4d
BS
5001 case 0x080: /* VIS I shutdown */
5002 case 0x081: /* VIS II siam */
5003 // XXX
5004 goto illegal_insn;
3299908c
BS
5005 default:
5006 goto illegal_insn;
5007 }
5008#else
0f8a249a 5009 goto ncp_insn;
3299908c
BS
5010#endif
5011 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
fcc72045 5012#ifdef TARGET_SPARC64
0f8a249a 5013 goto illegal_insn;
fcc72045 5014#else
0f8a249a 5015 goto ncp_insn;
fcc72045 5016#endif
3475187d 5017#ifdef TARGET_SPARC64
0f8a249a 5018 } else if (xop == 0x39) { /* V9 return */
66442b07 5019 save_state(dc);
9d1d4e34 5020 cpu_src1 = get_src1(dc, insn);
de9e9d9f 5021 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 5022 if (IS_IMM) { /* immediate */
67526b20 5023 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 5024 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 5025 } else { /* register */
3475187d 5026 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 5027 if (rs2) {
97ea2859 5028 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 5029 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 5030 } else {
7b04bd5c 5031 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 5032 }
3475187d 5033 }
063c3675 5034 gen_helper_restore(cpu_env);
13a6dd00 5035 gen_mov_pc_npc(dc);
35e94905 5036 gen_check_align(cpu_tmp0, 3);
7b04bd5c 5037 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
5038 dc->npc = DYNAMIC_PC;
5039 goto jmp_insn;
3475187d 5040#endif
0f8a249a 5041 } else {
9d1d4e34 5042 cpu_src1 = get_src1(dc, insn);
de9e9d9f 5043 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 5044 if (IS_IMM) { /* immediate */
67526b20 5045 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 5046 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 5047 } else { /* register */
e80cfcfc 5048 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 5049 if (rs2) {
97ea2859 5050 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 5051 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 5052 } else {
7b04bd5c 5053 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 5054 }
cf495bcf 5055 }
0f8a249a
BS
5056 switch (xop) {
5057 case 0x38: /* jmpl */
5058 {
35e94905 5059 TCGv t = gen_dest_gpr(dc, rd);
97ea2859
RH
5060 tcg_gen_movi_tl(t, dc->pc);
5061 gen_store_gpr(dc, rd, t);
35e94905 5062
13a6dd00 5063 gen_mov_pc_npc(dc);
35e94905 5064 gen_check_align(cpu_tmp0, 3);
7b04bd5c
RH
5065 gen_address_mask(dc, cpu_tmp0);
5066 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
5067 dc->npc = DYNAMIC_PC;
5068 }
5069 goto jmp_insn;
3475187d 5070#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
0f8a249a
BS
5071 case 0x39: /* rett, V9 return */
5072 {
5073 if (!supervisor(dc))
5074 goto priv_insn;
13a6dd00 5075 gen_mov_pc_npc(dc);
35e94905 5076 gen_check_align(cpu_tmp0, 3);
7b04bd5c 5077 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a 5078 dc->npc = DYNAMIC_PC;
063c3675 5079 gen_helper_rett(cpu_env);
0f8a249a
BS
5080 }
5081 goto jmp_insn;
5082#endif
5083 case 0x3b: /* flush */
5578ceab 5084 if (!((dc)->def->features & CPU_FEATURE_FLUSH))
64a88d5d 5085 goto unimp_flush;
dcfd14b3 5086 /* nop */
0f8a249a
BS
5087 break;
5088 case 0x3c: /* save */
063c3675 5089 gen_helper_save(cpu_env);
7b04bd5c 5090 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a
BS
5091 break;
5092 case 0x3d: /* restore */
063c3675 5093 gen_helper_restore(cpu_env);
7b04bd5c 5094 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a 5095 break;
3475187d 5096#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
0f8a249a
BS
5097 case 0x3e: /* V9 done/retry */
5098 {
5099 switch (rd) {
5100 case 0:
5101 if (!supervisor(dc))
5102 goto priv_insn;
5103 dc->npc = DYNAMIC_PC;
5104 dc->pc = DYNAMIC_PC;
063c3675 5105 gen_helper_done(cpu_env);
0f8a249a
BS
5106 goto jmp_insn;
5107 case 1:
5108 if (!supervisor(dc))
5109 goto priv_insn;
5110 dc->npc = DYNAMIC_PC;
5111 dc->pc = DYNAMIC_PC;
063c3675 5112 gen_helper_retry(cpu_env);
0f8a249a
BS
5113 goto jmp_insn;
5114 default:
5115 goto illegal_insn;
5116 }
5117 }
5118 break;
5119#endif
5120 default:
5121 goto illegal_insn;
5122 }
cf495bcf 5123 }
0f8a249a
BS
5124 break;
5125 }
5126 break;
5127 case 3: /* load/store instructions */
5128 {
5129 unsigned int xop = GET_FIELD(insn, 7, 12);
5e6ed439
RH
5130 /* ??? gen_address_mask prevents us from using a source
5131 register directly. Always generate a temporary. */
5132 TCGv cpu_addr = get_temp_tl(dc);
9322a4bf 5133
5e6ed439
RH
5134 tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
5135 if (xop == 0x3c || xop == 0x3e) {
5136 /* V9 casa/casxa : no offset */
71817e48 5137 } else if (IS_IMM) { /* immediate */
67526b20 5138 simm = GET_FIELDs(insn, 19, 31);
5e6ed439
RH
5139 if (simm != 0) {
5140 tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
5141 }
0f8a249a
BS
5142 } else { /* register */
5143 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 5144 if (rs2 != 0) {
5e6ed439 5145 tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
97ea2859 5146 }
0f8a249a 5147 }
2f2ecb83
BS
5148 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
5149 (xop > 0x17 && xop <= 0x1d ) ||
5150 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
81634eea
RH
5151 TCGv cpu_val = gen_dest_gpr(dc, rd);
5152
0f8a249a 5153 switch (xop) {
b89e94af 5154 case 0x0: /* ld, V9 lduw, load unsigned word */
2cade6a3 5155 gen_address_mask(dc, cpu_addr);
6ae20372 5156 tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5157 break;
b89e94af 5158 case 0x1: /* ldub, load unsigned byte */
2cade6a3 5159 gen_address_mask(dc, cpu_addr);
6ae20372 5160 tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5161 break;
b89e94af 5162 case 0x2: /* lduh, load unsigned halfword */
2cade6a3 5163 gen_address_mask(dc, cpu_addr);
6ae20372 5164 tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5165 break;
b89e94af 5166 case 0x3: /* ldd, load double word */
0f8a249a 5167 if (rd & 1)
d4218d99 5168 goto illegal_insn;
1a2fb1c0 5169 else {
abcc7191 5170 TCGv_i64 t64;
2ea815ca 5171
2cade6a3 5172 gen_address_mask(dc, cpu_addr);
abcc7191
RH
5173 t64 = tcg_temp_new_i64();
5174 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
de9e9d9f
RH
5175 tcg_gen_trunc_i64_tl(cpu_val, t64);
5176 tcg_gen_ext32u_tl(cpu_val, cpu_val);
5177 gen_store_gpr(dc, rd + 1, cpu_val);
abcc7191
RH
5178 tcg_gen_shri_i64(t64, t64, 32);
5179 tcg_gen_trunc_i64_tl(cpu_val, t64);
5180 tcg_temp_free_i64(t64);
de9e9d9f 5181 tcg_gen_ext32u_tl(cpu_val, cpu_val);
1a2fb1c0 5182 }
0f8a249a 5183 break;
b89e94af 5184 case 0x9: /* ldsb, load signed byte */
2cade6a3 5185 gen_address_mask(dc, cpu_addr);
6ae20372 5186 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5187 break;
b89e94af 5188 case 0xa: /* ldsh, load signed halfword */
2cade6a3 5189 gen_address_mask(dc, cpu_addr);
6ae20372 5190 tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5191 break;
5192 case 0xd: /* ldstub -- XXX: should be atomically */
2ea815ca
BS
5193 {
5194 TCGv r_const;
b64d2e57 5195 TCGv tmp = tcg_temp_new();
2ea815ca 5196
2cade6a3 5197 gen_address_mask(dc, cpu_addr);
b64d2e57 5198 tcg_gen_qemu_ld8u(tmp, cpu_addr, dc->mem_idx);
2ea815ca
BS
5199 r_const = tcg_const_tl(0xff);
5200 tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
b64d2e57 5201 tcg_gen_mov_tl(cpu_val, tmp);
2ea815ca 5202 tcg_temp_free(r_const);
b64d2e57 5203 tcg_temp_free(tmp);
2ea815ca 5204 }
0f8a249a 5205 break;
de9e9d9f
RH
5206 case 0x0f:
5207 /* swap, swap register with memory. Also atomically */
4fb554bc
RH
5208 CHECK_IU_FEATURE(dc, SWAP);
5209 cpu_src1 = gen_load_gpr(dc, rd);
5210 gen_swap(dc, cpu_val, cpu_src1, cpu_addr,
5211 dc->mem_idx, MO_TEUL);
0f8a249a 5212 break;
3475187d 5213#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 5214 case 0x10: /* lda, V9 lduwa, load word alternate */
1d65b0f5 5215 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
0f8a249a 5216 break;
b89e94af 5217 case 0x11: /* lduba, load unsigned byte alternate */
1d65b0f5 5218 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
0f8a249a 5219 break;
b89e94af 5220 case 0x12: /* lduha, load unsigned halfword alternate */
1d65b0f5 5221 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
0f8a249a 5222 break;
b89e94af 5223 case 0x13: /* ldda, load double word alternate */
7ec1e5ea 5224 if (rd & 1) {
d4218d99 5225 goto illegal_insn;
7ec1e5ea 5226 }
e4dc0052 5227 gen_ldda_asi(dc, cpu_addr, insn, rd);
db166940 5228 goto skip_move;
b89e94af 5229 case 0x19: /* ldsba, load signed byte alternate */
1d65b0f5 5230 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
0f8a249a 5231 break;
b89e94af 5232 case 0x1a: /* ldsha, load signed halfword alternate */
1d65b0f5 5233 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESW);
0f8a249a
BS
5234 break;
5235 case 0x1d: /* ldstuba -- XXX: should be atomically */
22e70060 5236 gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
0f8a249a 5237 break;
b89e94af 5238 case 0x1f: /* swapa, swap reg with alt. memory. Also
77f193da 5239 atomically */
64a88d5d 5240 CHECK_IU_FEATURE(dc, SWAP);
06828032 5241 cpu_src1 = gen_load_gpr(dc, rd);
22e70060 5242 gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
0f8a249a 5243 break;
3475187d
FB
5244
5245#ifndef TARGET_SPARC64
0f8a249a
BS
5246 case 0x30: /* ldc */
5247 case 0x31: /* ldcsr */
5248 case 0x33: /* lddc */
5249 goto ncp_insn;
3475187d
FB
5250#endif
5251#endif
5252#ifdef TARGET_SPARC64
0f8a249a 5253 case 0x08: /* V9 ldsw */
2cade6a3 5254 gen_address_mask(dc, cpu_addr);
6ae20372 5255 tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5256 break;
5257 case 0x0b: /* V9 ldx */
2cade6a3 5258 gen_address_mask(dc, cpu_addr);
6ae20372 5259 tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5260 break;
5261 case 0x18: /* V9 ldswa */
1d65b0f5 5262 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
0f8a249a
BS
5263 break;
5264 case 0x1b: /* V9 ldxa */
1d65b0f5 5265 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
0f8a249a
BS
5266 break;
5267 case 0x2d: /* V9 prefetch, no effect */
5268 goto skip_move;
5269 case 0x30: /* V9 ldfa */
5b12f1e8 5270 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5271 goto jmp_insn;
5272 }
22e70060 5273 gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
f9c816c0 5274 gen_update_fprs_dirty(dc, rd);
81ad8ba2 5275 goto skip_move;
0f8a249a 5276 case 0x33: /* V9 lddfa */
5b12f1e8 5277 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5278 goto jmp_insn;
5279 }
22e70060 5280 gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
f9c816c0 5281 gen_update_fprs_dirty(dc, DFPREG(rd));
81ad8ba2 5282 goto skip_move;
0f8a249a
BS
5283 case 0x3d: /* V9 prefetcha, no effect */
5284 goto skip_move;
5285 case 0x32: /* V9 ldqfa */
64a88d5d 5286 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5287 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
5288 goto jmp_insn;
5289 }
22e70060 5290 gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
f9c816c0 5291 gen_update_fprs_dirty(dc, QFPREG(rd));
1f587329 5292 goto skip_move;
0f8a249a
BS
5293#endif
5294 default:
5295 goto illegal_insn;
5296 }
97ea2859 5297 gen_store_gpr(dc, rd, cpu_val);
db166940 5298#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 5299 skip_move: ;
3475187d 5300#endif
0f8a249a 5301 } else if (xop >= 0x20 && xop < 0x24) {
de9e9d9f
RH
5302 TCGv t0;
5303
5b12f1e8 5304 if (gen_trap_ifnofpu(dc)) {
a80dde08 5305 goto jmp_insn;
5b12f1e8 5306 }
0f8a249a 5307 switch (xop) {
b89e94af 5308 case 0x20: /* ldf, load fpreg */
2cade6a3 5309 gen_address_mask(dc, cpu_addr);
de9e9d9f
RH
5310 t0 = get_temp_tl(dc);
5311 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
ba5f5179 5312 cpu_dst_32 = gen_dest_fpr_F(dc);
de9e9d9f 5313 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
208ae657 5314 gen_store_fpr_F(dc, rd, cpu_dst_32);
0f8a249a 5315 break;
3a3b925d
BS
5316 case 0x21: /* ldfsr, V9 ldxfsr */
5317#ifdef TARGET_SPARC64
2cade6a3 5318 gen_address_mask(dc, cpu_addr);
3a3b925d 5319 if (rd == 1) {
abcc7191
RH
5320 TCGv_i64 t64 = tcg_temp_new_i64();
5321 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
7385aed2 5322 gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64);
abcc7191 5323 tcg_temp_free_i64(t64);
f8641947 5324 break;
fe987e23 5325 }
f8641947 5326#endif
de9e9d9f
RH
5327 cpu_dst_32 = get_temp_i32(dc);
5328 t0 = get_temp_tl(dc);
5329 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
5330 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
7385aed2 5331 gen_helper_ldfsr(cpu_fsr, cpu_env, cpu_fsr, cpu_dst_32);
0f8a249a 5332 break;
b89e94af 5333 case 0x22: /* ldqf, load quad fpreg */
2ea815ca 5334 {
a7812ae4 5335 TCGv_i32 r_const;
2ea815ca
BS
5336
5337 CHECK_FPU_FEATURE(dc, FLOAT128);
5338 r_const = tcg_const_i32(dc->mem_idx);
1295001c 5339 gen_address_mask(dc, cpu_addr);
fe8d8f0f 5340 gen_helper_ldqf(cpu_env, cpu_addr, r_const);
a7812ae4 5341 tcg_temp_free_i32(r_const);
2ea815ca 5342 gen_op_store_QT0_fpr(QFPREG(rd));
f9c816c0 5343 gen_update_fprs_dirty(dc, QFPREG(rd));
2ea815ca 5344 }
1f587329 5345 break;
b89e94af 5346 case 0x23: /* lddf, load double fpreg */
03fb8cfc 5347 gen_address_mask(dc, cpu_addr);
3886b8a3 5348 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
03fb8cfc
RH
5349 tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
5350 gen_store_fpr_D(dc, rd, cpu_dst_64);
0f8a249a
BS
5351 break;
5352 default:
5353 goto illegal_insn;
5354 }
dc1a6971 5355 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
0f8a249a 5356 xop == 0xe || xop == 0x1e) {
81634eea
RH
5357 TCGv cpu_val = gen_load_gpr(dc, rd);
5358
0f8a249a 5359 switch (xop) {
b89e94af 5360 case 0x4: /* st, store word */
2cade6a3 5361 gen_address_mask(dc, cpu_addr);
6ae20372 5362 tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5363 break;
b89e94af 5364 case 0x5: /* stb, store byte */
2cade6a3 5365 gen_address_mask(dc, cpu_addr);
6ae20372 5366 tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5367 break;
b89e94af 5368 case 0x6: /* sth, store halfword */
2cade6a3 5369 gen_address_mask(dc, cpu_addr);
6ae20372 5370 tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5371 break;
b89e94af 5372 case 0x7: /* std, store double word */
0f8a249a 5373 if (rd & 1)
d4218d99 5374 goto illegal_insn;
1a2fb1c0 5375 else {
abcc7191 5376 TCGv_i64 t64;
81634eea 5377 TCGv lo;
1a2fb1c0 5378
2cade6a3 5379 gen_address_mask(dc, cpu_addr);
81634eea 5380 lo = gen_load_gpr(dc, rd + 1);
abcc7191
RH
5381 t64 = tcg_temp_new_i64();
5382 tcg_gen_concat_tl_i64(t64, lo, cpu_val);
5383 tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx);
5384 tcg_temp_free_i64(t64);
7fa76c0b 5385 }
0f8a249a 5386 break;
3475187d 5387#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 5388 case 0x14: /* sta, V9 stwa, store word alternate */
1d65b0f5 5389 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
d39c0b99 5390 break;
b89e94af 5391 case 0x15: /* stba, store byte alternate */
1d65b0f5 5392 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
d39c0b99 5393 break;
b89e94af 5394 case 0x16: /* stha, store halfword alternate */
1d65b0f5 5395 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
d39c0b99 5396 break;
b89e94af 5397 case 0x17: /* stda, store double word alternate */
7ec1e5ea 5398 if (rd & 1) {
0f8a249a 5399 goto illegal_insn;
1a2fb1c0 5400 }
7ec1e5ea 5401 gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
d39c0b99 5402 break;
e80cfcfc 5403#endif
3475187d 5404#ifdef TARGET_SPARC64
0f8a249a 5405 case 0x0e: /* V9 stx */
2cade6a3 5406 gen_address_mask(dc, cpu_addr);
6ae20372 5407 tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5408 break;
5409 case 0x1e: /* V9 stxa */
1d65b0f5 5410 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
0f8a249a 5411 break;
3475187d 5412#endif
0f8a249a
BS
5413 default:
5414 goto illegal_insn;
5415 }
5416 } else if (xop > 0x23 && xop < 0x28) {
5b12f1e8 5417 if (gen_trap_ifnofpu(dc)) {
a80dde08 5418 goto jmp_insn;
5b12f1e8 5419 }
0f8a249a 5420 switch (xop) {
b89e94af 5421 case 0x24: /* stf, store fpreg */
de9e9d9f
RH
5422 {
5423 TCGv t = get_temp_tl(dc);
5424 gen_address_mask(dc, cpu_addr);
5425 cpu_src1_32 = gen_load_fpr_F(dc, rd);
5426 tcg_gen_ext_i32_tl(t, cpu_src1_32);
5427 tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
5428 }
0f8a249a
BS
5429 break;
5430 case 0x25: /* stfsr, V9 stxfsr */
f8641947 5431 {
3a3b925d 5432#ifdef TARGET_SPARC64
f8641947
RH
5433 gen_address_mask(dc, cpu_addr);
5434 if (rd == 1) {
ba2397d1 5435 tcg_gen_qemu_st64(cpu_fsr, cpu_addr, dc->mem_idx);
f8641947
RH
5436 break;
5437 }
3a3b925d 5438#endif
ba2397d1 5439 tcg_gen_qemu_st32(cpu_fsr, cpu_addr, dc->mem_idx);
f8641947 5440 }
0f8a249a 5441 break;
1f587329
BS
5442 case 0x26:
5443#ifdef TARGET_SPARC64
1f587329 5444 /* V9 stqf, store quad fpreg */
2ea815ca 5445 {
a7812ae4 5446 TCGv_i32 r_const;
2ea815ca
BS
5447
5448 CHECK_FPU_FEATURE(dc, FLOAT128);
5449 gen_op_load_fpr_QT0(QFPREG(rd));
5450 r_const = tcg_const_i32(dc->mem_idx);
1295001c 5451 gen_address_mask(dc, cpu_addr);
fe8d8f0f 5452 gen_helper_stqf(cpu_env, cpu_addr, r_const);
a7812ae4 5453 tcg_temp_free_i32(r_const);
2ea815ca 5454 }
1f587329 5455 break;
1f587329
BS
5456#else /* !TARGET_SPARC64 */
5457 /* stdfq, store floating point queue */
5458#if defined(CONFIG_USER_ONLY)
5459 goto illegal_insn;
5460#else
0f8a249a
BS
5461 if (!supervisor(dc))
5462 goto priv_insn;
5b12f1e8 5463 if (gen_trap_ifnofpu(dc)) {
0f8a249a 5464 goto jmp_insn;
5b12f1e8 5465 }
0f8a249a 5466 goto nfq_insn;
1f587329 5467#endif
0f8a249a 5468#endif
b89e94af 5469 case 0x27: /* stdf, store double fpreg */
03fb8cfc
RH
5470 gen_address_mask(dc, cpu_addr);
5471 cpu_src1_64 = gen_load_fpr_D(dc, rd);
5472 tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
0f8a249a
BS
5473 break;
5474 default:
5475 goto illegal_insn;
5476 }
5477 } else if (xop > 0x33 && xop < 0x3f) {
5478 switch (xop) {
a4d17f19 5479#ifdef TARGET_SPARC64
0f8a249a 5480 case 0x34: /* V9 stfa */
5b12f1e8 5481 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5482 goto jmp_insn;
5483 }
22e70060 5484 gen_stf_asi(dc, cpu_addr, insn, 4, rd);
0f8a249a 5485 break;
1f587329 5486 case 0x36: /* V9 stqfa */
2ea815ca 5487 {
2ea815ca 5488 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5489 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5490 goto jmp_insn;
5491 }
22e70060 5492 gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
2ea815ca 5493 }
1f587329 5494 break;
0f8a249a 5495 case 0x37: /* V9 stdfa */
5b12f1e8 5496 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5497 goto jmp_insn;
5498 }
22e70060 5499 gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
0f8a249a 5500 break;
0f8a249a 5501 case 0x3e: /* V9 casxa */
a4273524
RH
5502 rs2 = GET_FIELD(insn, 27, 31);
5503 cpu_src2 = gen_load_gpr(dc, rs2);
81634eea 5504 gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd);
0f8a249a 5505 break;
a4d17f19 5506#else
0f8a249a
BS
5507 case 0x34: /* stc */
5508 case 0x35: /* stcsr */
5509 case 0x36: /* stdcq */
5510 case 0x37: /* stdc */
5511 goto ncp_insn;
16c358e9
SH
5512#endif
5513#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5514 case 0x3c: /* V9 or LEON3 casa */
5515#ifndef TARGET_SPARC64
5516 CHECK_IU_FEATURE(dc, CASA);
16c358e9
SH
5517#endif
5518 rs2 = GET_FIELD(insn, 27, 31);
5519 cpu_src2 = gen_load_gpr(dc, rs2);
5520 gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
5521 break;
0f8a249a
BS
5522#endif
5523 default:
5524 goto illegal_insn;
5525 }
a4273524 5526 } else {
0f8a249a 5527 goto illegal_insn;
a4273524 5528 }
0f8a249a
BS
5529 }
5530 break;
cf495bcf
FB
5531 }
5532 /* default case for non jump instructions */
72cbca10 5533 if (dc->npc == DYNAMIC_PC) {
0f8a249a
BS
5534 dc->pc = DYNAMIC_PC;
5535 gen_op_next_insn();
72cbca10
FB
5536 } else if (dc->npc == JUMP_PC) {
5537 /* we can do a static jump */
6ae20372 5538 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
72cbca10
FB
5539 dc->is_br = 1;
5540 } else {
0f8a249a
BS
5541 dc->pc = dc->npc;
5542 dc->npc = dc->npc + 4;
cf495bcf 5543 }
e80cfcfc 5544 jmp_insn:
42a8aa83 5545 goto egress;
cf495bcf 5546 illegal_insn:
4fbe0067 5547 gen_exception(dc, TT_ILL_INSN);
42a8aa83 5548 goto egress;
64a88d5d 5549 unimp_flush:
4fbe0067 5550 gen_exception(dc, TT_UNIMP_FLUSH);
42a8aa83 5551 goto egress;
e80cfcfc 5552#if !defined(CONFIG_USER_ONLY)
e8af50a3 5553 priv_insn:
4fbe0067 5554 gen_exception(dc, TT_PRIV_INSN);
42a8aa83 5555 goto egress;
64a88d5d 5556#endif
e80cfcfc 5557 nfpu_insn:
4fbe0067 5558 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
42a8aa83 5559 goto egress;
64a88d5d 5560#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
9143e598 5561 nfq_insn:
4fbe0067 5562 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
42a8aa83 5563 goto egress;
9143e598 5564#endif
fcc72045
BS
5565#ifndef TARGET_SPARC64
5566 ncp_insn:
4fbe0067 5567 gen_exception(dc, TT_NCP_INSN);
42a8aa83 5568 goto egress;
fcc72045 5569#endif
42a8aa83 5570 egress:
30038fd8
RH
5571 if (dc->n_t32 != 0) {
5572 int i;
5573 for (i = dc->n_t32 - 1; i >= 0; --i) {
5574 tcg_temp_free_i32(dc->t32[i]);
5575 }
5576 dc->n_t32 = 0;
5577 }
88023616
RH
5578 if (dc->n_ttl != 0) {
5579 int i;
5580 for (i = dc->n_ttl - 1; i >= 0; --i) {
5581 tcg_temp_free(dc->ttl[i]);
5582 }
5583 dc->n_ttl = 0;
5584 }
7a3f1944
FB
5585}
5586
4e5e1215 5587void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5588{
4e5e1215 5589 SPARCCPU *cpu = sparc_env_get_cpu(env);
ed2803da 5590 CPUState *cs = CPU(cpu);
72cbca10 5591 target_ulong pc_start, last_pc;
cf495bcf 5592 DisasContext dc1, *dc = &dc1;
2e70f6ef
PB
5593 int num_insns;
5594 int max_insns;
0184e266 5595 unsigned int insn;
cf495bcf
FB
5596
5597 memset(dc, 0, sizeof(DisasContext));
cf495bcf 5598 dc->tb = tb;
72cbca10 5599 pc_start = tb->pc;
cf495bcf 5600 dc->pc = pc_start;
e80cfcfc 5601 last_pc = dc->pc;
72cbca10 5602 dc->npc = (target_ulong) tb->cs_base;
8393617c 5603 dc->cc_op = CC_OP_DYNAMIC;
99a23063 5604 dc->mem_idx = tb->flags & TB_FLAG_MMU_MASK;
5578ceab 5605 dc->def = env->def;
f838e2c5
BS
5606 dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5607 dc->address_mask_32bit = tb_am_enabled(tb->flags);
ed2803da 5608 dc->singlestep = (cs->singlestep_enabled || singlestep);
a6d567e5 5609#ifdef TARGET_SPARC64
f9c816c0 5610 dc->fprs_dirty = 0;
a6d567e5
RH
5611 dc->asi = (tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5612#endif
cf495bcf 5613
2e70f6ef
PB
5614 num_insns = 0;
5615 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 5616 if (max_insns == 0) {
2e70f6ef 5617 max_insns = CF_COUNT_MASK;
190ce7fb
RH
5618 }
5619 if (max_insns > TCG_MAX_INSNS) {
5620 max_insns = TCG_MAX_INSNS;
5621 }
5622
cd42d5b2 5623 gen_tb_start(tb);
cf495bcf 5624 do {
a3d5ad76
RH
5625 if (dc->npc & JUMP_PC) {
5626 assert(dc->jump_pc[1] == dc->pc + 4);
5627 tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
5628 } else {
5629 tcg_gen_insn_start(dc->pc, dc->npc);
5630 }
959082fc 5631 num_insns++;
522a0d4e 5632 last_pc = dc->pc;
667b8e29 5633
b933066a
RH
5634 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
5635 if (dc->pc != pc_start) {
5636 save_state(dc);
5637 }
5638 gen_helper_debug(cpu_env);
5639 tcg_gen_exit_tb(0);
5640 dc->is_br = 1;
5641 goto exit_gen_loop;
5642 }
5643
959082fc 5644 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
2e70f6ef 5645 gen_io_start();
667b8e29
RH
5646 }
5647
0184e266 5648 insn = cpu_ldl_code(env, dc->pc);
b09b2fd3 5649
0184e266 5650 disas_sparc_insn(dc, insn);
0f8a249a
BS
5651
5652 if (dc->is_br)
5653 break;
5654 /* if the next PC is different, we abort now */
5655 if (dc->pc != (last_pc + 4))
5656 break;
d39c0b99
FB
5657 /* if we reach a page boundary, we stop generation so that the
5658 PC of a TT_TFAULT exception is always in the right page */
5659 if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5660 break;
e80cfcfc
FB
5661 /* if single step mode, we generate only one instruction and
5662 generate an exception */
060718c1 5663 if (dc->singlestep) {
e80cfcfc
FB
5664 break;
5665 }
fe700adb 5666 } while (!tcg_op_buf_full() &&
2e70f6ef
PB
5667 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5668 num_insns < max_insns);
e80cfcfc
FB
5669
5670 exit_gen_loop:
b09b2fd3 5671 if (tb->cflags & CF_LAST_IO) {
2e70f6ef 5672 gen_io_end();
b09b2fd3 5673 }
72cbca10 5674 if (!dc->is_br) {
5fafdf24 5675 if (dc->pc != DYNAMIC_PC &&
72cbca10
FB
5676 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5677 /* static PC and NPC: we can use direct chaining */
2f5680ee 5678 gen_goto_tb(dc, 0, dc->pc, dc->npc);
72cbca10 5679 } else {
b09b2fd3 5680 if (dc->pc != DYNAMIC_PC) {
2f5680ee 5681 tcg_gen_movi_tl(cpu_pc, dc->pc);
b09b2fd3 5682 }
934da7ee 5683 save_npc(dc);
57fec1fe 5684 tcg_gen_exit_tb(0);
72cbca10
FB
5685 }
5686 }
806f352d 5687 gen_tb_end(tb, num_insns);
0a7df5da 5688
4e5e1215
RH
5689 tb->size = last_pc + 4 - pc_start;
5690 tb->icount = num_insns;
5691
7a3f1944 5692#ifdef DEBUG_DISAS
4910e6e4
RH
5693 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
5694 && qemu_log_in_addr_range(pc_start)) {
93fcfe39
AL
5695 qemu_log("--------------\n");
5696 qemu_log("IN: %s\n", lookup_symbol(pc_start));
d49190c4 5697 log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
93fcfe39 5698 qemu_log("\n");
cf495bcf 5699 }
7a3f1944 5700#endif
7a3f1944
FB
5701}
5702
c48fcb47 5703void gen_intermediate_code_init(CPUSPARCState *env)
e80cfcfc 5704{
c48fcb47 5705 static int inited;
d2dc4069 5706 static const char gregnames[32][4] = {
0ea63844 5707 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
d2dc4069
RH
5708 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5709 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5710 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
f5069b26 5711 };
0ea63844 5712 static const char fregnames[32][4] = {
30038fd8
RH
5713 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5714 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5715 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5716 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5717 };
aaed909a 5718
0ea63844 5719 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
1a2fb1c0 5720#ifdef TARGET_SPARC64
0ea63844 5721 { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
0ea63844 5722 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
255e1fcb 5723#else
0ea63844
RH
5724 { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
5725#endif
5726 { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" },
5727 { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" },
5728 };
5729
5730 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5731#ifdef TARGET_SPARC64
5732 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
5733 { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" },
5734 { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" },
5735 { &cpu_hstick_cmpr, offsetof(CPUSPARCState, hstick_cmpr),
5736 "hstick_cmpr" },
5737 { &cpu_hintp, offsetof(CPUSPARCState, hintp), "hintp" },
5738 { &cpu_htba, offsetof(CPUSPARCState, htba), "htba" },
5739 { &cpu_hver, offsetof(CPUSPARCState, hver), "hver" },
5740 { &cpu_ssr, offsetof(CPUSPARCState, ssr), "ssr" },
5741 { &cpu_ver, offsetof(CPUSPARCState, version), "ver" },
1a2fb1c0 5742#endif
0ea63844
RH
5743 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5744 { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" },
5745 { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" },
5746 { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" },
5747 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
5748 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5749 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5750 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
255e1fcb 5751#ifndef CONFIG_USER_ONLY
0ea63844 5752 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
255e1fcb 5753#endif
0ea63844
RH
5754 };
5755
5756 unsigned int i;
5757
5758 /* init various static tables */
5759 if (inited) {
5760 return;
5761 }
5762 inited = 1;
5763
5764 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7c255043 5765 tcg_ctx.tcg_env = cpu_env;
0ea63844
RH
5766
5767 cpu_regwptr = tcg_global_mem_new_ptr(cpu_env,
5768 offsetof(CPUSPARCState, regwptr),
5769 "regwptr");
5770
5771 for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5772 *r32[i].ptr = tcg_global_mem_new_i32(cpu_env, r32[i].off, r32[i].name);
5773 }
5774
5775 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5776 *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
5777 }
5778
d2dc4069 5779 TCGV_UNUSED(cpu_regs[0]);
0ea63844 5780 for (i = 1; i < 8; ++i) {
d2dc4069
RH
5781 cpu_regs[i] = tcg_global_mem_new(cpu_env,
5782 offsetof(CPUSPARCState, gregs[i]),
5783 gregnames[i]);
5784 }
5785
5786 for (i = 8; i < 32; ++i) {
5787 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5788 (i - 8) * sizeof(target_ulong),
5789 gregnames[i]);
0ea63844
RH
5790 }
5791
5792 for (i = 0; i < TARGET_DPREGS; i++) {
5793 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
5794 offsetof(CPUSPARCState, fpr[i]),
5795 fregnames[i]);
1a2fb1c0 5796 }
658138bc 5797}
d2856f1a 5798
bad729e2
RH
5799void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
5800 target_ulong *data)
d2856f1a 5801{
bad729e2
RH
5802 target_ulong pc = data[0];
5803 target_ulong npc = data[1];
5804
5805 env->pc = pc;
6c42444f 5806 if (npc == DYNAMIC_PC) {
d2856f1a 5807 /* dynamic NPC: already stored */
6c42444f 5808 } else if (npc & JUMP_PC) {
d7da2a10
BS
5809 /* jump PC: use 'cond' and the jump targets of the translation */
5810 if (env->cond) {
6c42444f 5811 env->npc = npc & ~3;
d7da2a10 5812 } else {
6c42444f 5813 env->npc = pc + 4;
d7da2a10 5814 }
d2856f1a
AJ
5815 } else {
5816 env->npc = npc;
5817 }
5818}