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