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