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