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