]> git.ipfire.org Git - thirdparty/qemu.git/blame - target-sparc/translate.c
target-sparc: Use DisasCompare and movcond in MOVR
[thirdparty/qemu.git] / target-sparc / translate.c
CommitLineData
7a3f1944
FB
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
3475187d 5 Copyright (C) 2003-2005 Fabrice Bellard
7a3f1944
FB
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
8167ee88 18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
7a3f1944
FB
19 */
20
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);
c33f80f5 4121 DisasCompare cmp;
00f219bf 4122
c33f80f5 4123 gen_compare_reg(&cmp, cond, cpu_src1);
2ea815ca 4124
c33f80f5
RH
4125 /* The get_src2 above loaded the normal 13-bit
4126 immediate field, not the 10-bit field we have
4127 in movr. But it did handle the reg case. */
4128 if (IS_IMM) {
67526b20 4129 simm = GET_FIELD_SPs(insn, 0, 9);
c33f80f5 4130 tcg_gen_movi_tl(cpu_src2, simm);
0f8a249a 4131 }
c33f80f5
RH
4132
4133 gen_movl_reg_TN(rd, cpu_dst);
4134 tcg_gen_movcond_tl(cmp.cond, cpu_dst,
4135 cmp.c1, cmp.c2,
4136 cpu_src2, cpu_dst);
4137 free_compare(&cmp);
4138 gen_movl_TN_reg(rd, cpu_dst);
0f8a249a
BS
4139 break;
4140 }
4141#endif
4142 default:
4143 goto illegal_insn;
4144 }
4145 }
3299908c
BS
4146 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4147#ifdef TARGET_SPARC64
4148 int opf = GET_FIELD_SP(insn, 5, 13);
4149 rs1 = GET_FIELD(insn, 13, 17);
4150 rs2 = GET_FIELD(insn, 27, 31);
5b12f1e8 4151 if (gen_trap_ifnofpu(dc)) {
e9ebed4d 4152 goto jmp_insn;
5b12f1e8 4153 }
3299908c
BS
4154
4155 switch (opf) {
e9ebed4d 4156 case 0x000: /* VIS I edge8cc */
6c073553
RH
4157 CHECK_FPU_FEATURE(dc, VIS1);
4158 gen_movl_reg_TN(rs1, cpu_src1);
4159 gen_movl_reg_TN(rs2, cpu_src2);
4160 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
4161 gen_movl_TN_reg(rd, cpu_dst);
4162 break;
e9ebed4d 4163 case 0x001: /* VIS II edge8n */
6c073553
RH
4164 CHECK_FPU_FEATURE(dc, VIS2);
4165 gen_movl_reg_TN(rs1, cpu_src1);
4166 gen_movl_reg_TN(rs2, cpu_src2);
4167 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
4168 gen_movl_TN_reg(rd, cpu_dst);
4169 break;
e9ebed4d 4170 case 0x002: /* VIS I edge8lcc */
6c073553
RH
4171 CHECK_FPU_FEATURE(dc, VIS1);
4172 gen_movl_reg_TN(rs1, cpu_src1);
4173 gen_movl_reg_TN(rs2, cpu_src2);
4174 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
4175 gen_movl_TN_reg(rd, cpu_dst);
4176 break;
e9ebed4d 4177 case 0x003: /* VIS II edge8ln */
6c073553
RH
4178 CHECK_FPU_FEATURE(dc, VIS2);
4179 gen_movl_reg_TN(rs1, cpu_src1);
4180 gen_movl_reg_TN(rs2, cpu_src2);
4181 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
4182 gen_movl_TN_reg(rd, cpu_dst);
4183 break;
e9ebed4d 4184 case 0x004: /* VIS I edge16cc */
6c073553
RH
4185 CHECK_FPU_FEATURE(dc, VIS1);
4186 gen_movl_reg_TN(rs1, cpu_src1);
4187 gen_movl_reg_TN(rs2, cpu_src2);
4188 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
4189 gen_movl_TN_reg(rd, cpu_dst);
4190 break;
e9ebed4d 4191 case 0x005: /* VIS II edge16n */
6c073553
RH
4192 CHECK_FPU_FEATURE(dc, VIS2);
4193 gen_movl_reg_TN(rs1, cpu_src1);
4194 gen_movl_reg_TN(rs2, cpu_src2);
4195 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
4196 gen_movl_TN_reg(rd, cpu_dst);
4197 break;
e9ebed4d 4198 case 0x006: /* VIS I edge16lcc */
6c073553
RH
4199 CHECK_FPU_FEATURE(dc, VIS1);
4200 gen_movl_reg_TN(rs1, cpu_src1);
4201 gen_movl_reg_TN(rs2, cpu_src2);
4202 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
4203 gen_movl_TN_reg(rd, cpu_dst);
4204 break;
e9ebed4d 4205 case 0x007: /* VIS II edge16ln */
6c073553
RH
4206 CHECK_FPU_FEATURE(dc, VIS2);
4207 gen_movl_reg_TN(rs1, cpu_src1);
4208 gen_movl_reg_TN(rs2, cpu_src2);
4209 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
4210 gen_movl_TN_reg(rd, cpu_dst);
4211 break;
e9ebed4d 4212 case 0x008: /* VIS I edge32cc */
6c073553
RH
4213 CHECK_FPU_FEATURE(dc, VIS1);
4214 gen_movl_reg_TN(rs1, cpu_src1);
4215 gen_movl_reg_TN(rs2, cpu_src2);
4216 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
4217 gen_movl_TN_reg(rd, cpu_dst);
4218 break;
e9ebed4d 4219 case 0x009: /* VIS II edge32n */
6c073553
RH
4220 CHECK_FPU_FEATURE(dc, VIS2);
4221 gen_movl_reg_TN(rs1, cpu_src1);
4222 gen_movl_reg_TN(rs2, cpu_src2);
4223 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
4224 gen_movl_TN_reg(rd, cpu_dst);
4225 break;
e9ebed4d 4226 case 0x00a: /* VIS I edge32lcc */
6c073553
RH
4227 CHECK_FPU_FEATURE(dc, VIS1);
4228 gen_movl_reg_TN(rs1, cpu_src1);
4229 gen_movl_reg_TN(rs2, cpu_src2);
4230 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
4231 gen_movl_TN_reg(rd, cpu_dst);
4232 break;
e9ebed4d 4233 case 0x00b: /* VIS II edge32ln */
6c073553
RH
4234 CHECK_FPU_FEATURE(dc, VIS2);
4235 gen_movl_reg_TN(rs1, cpu_src1);
4236 gen_movl_reg_TN(rs2, cpu_src2);
4237 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
4238 gen_movl_TN_reg(rd, cpu_dst);
4239 break;
e9ebed4d 4240 case 0x010: /* VIS I array8 */
64a88d5d 4241 CHECK_FPU_FEATURE(dc, VIS1);
9322a4bf 4242 cpu_src1 = get_src1(insn, cpu_src1);
6ae20372 4243 gen_movl_reg_TN(rs2, cpu_src2);
f027c3b1 4244 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4245 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4246 break;
4247 case 0x012: /* VIS I array16 */
64a88d5d 4248 CHECK_FPU_FEATURE(dc, VIS1);
9322a4bf 4249 cpu_src1 = get_src1(insn, cpu_src1);
6ae20372 4250 gen_movl_reg_TN(rs2, cpu_src2);
f027c3b1 4251 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372
BS
4252 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
4253 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4254 break;
4255 case 0x014: /* VIS I array32 */
64a88d5d 4256 CHECK_FPU_FEATURE(dc, VIS1);
9322a4bf 4257 cpu_src1 = get_src1(insn, cpu_src1);
6ae20372 4258 gen_movl_reg_TN(rs2, cpu_src2);
f027c3b1 4259 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372
BS
4260 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
4261 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d 4262 break;
3299908c 4263 case 0x018: /* VIS I alignaddr */
64a88d5d 4264 CHECK_FPU_FEATURE(dc, VIS1);
9322a4bf 4265 cpu_src1 = get_src1(insn, cpu_src1);
6ae20372 4266 gen_movl_reg_TN(rs2, cpu_src2);
add545ab 4267 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
6ae20372 4268 gen_movl_TN_reg(rd, cpu_dst);
3299908c
BS
4269 break;
4270 case 0x01a: /* VIS I alignaddrl */
add545ab
RH
4271 CHECK_FPU_FEATURE(dc, VIS1);
4272 cpu_src1 = get_src1(insn, cpu_src1);
4273 gen_movl_reg_TN(rs2, cpu_src2);
4274 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
4275 gen_movl_TN_reg(rd, cpu_dst);
4276 break;
4277 case 0x019: /* VIS II bmask */
793a137a
RH
4278 CHECK_FPU_FEATURE(dc, VIS2);
4279 cpu_src1 = get_src1(insn, cpu_src1);
4280 cpu_src2 = get_src1(insn, cpu_src2);
4281 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4282 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
4283 gen_movl_TN_reg(rd, cpu_dst);
4284 break;
e9ebed4d 4285 case 0x020: /* VIS I fcmple16 */
64a88d5d 4286 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4287 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4288 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4289 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4290 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4291 break;
4292 case 0x022: /* VIS I fcmpne16 */
64a88d5d 4293 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4294 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4295 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4296 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4297 gen_movl_TN_reg(rd, cpu_dst);
3299908c 4298 break;
e9ebed4d 4299 case 0x024: /* VIS I fcmple32 */
64a88d5d 4300 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4301 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4302 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4303 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4304 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4305 break;
4306 case 0x026: /* VIS I fcmpne32 */
64a88d5d 4307 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4308 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4309 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4310 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4311 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4312 break;
4313 case 0x028: /* VIS I fcmpgt16 */
64a88d5d 4314 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4315 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4316 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4317 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4318 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4319 break;
4320 case 0x02a: /* VIS I fcmpeq16 */
64a88d5d 4321 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4322 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4323 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4324 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4325 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4326 break;
4327 case 0x02c: /* VIS I fcmpgt32 */
64a88d5d 4328 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4329 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4330 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4331 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4332 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4333 break;
4334 case 0x02e: /* VIS I fcmpeq32 */
64a88d5d 4335 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4336 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4337 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4338 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
afcb7375 4339 gen_movl_TN_reg(rd, cpu_dst);
e9ebed4d
BS
4340 break;
4341 case 0x031: /* VIS I fmul8x16 */
64a88d5d 4342 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4343 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
e9ebed4d
BS
4344 break;
4345 case 0x033: /* VIS I fmul8x16au */
64a88d5d 4346 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4347 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
e9ebed4d
BS
4348 break;
4349 case 0x035: /* VIS I fmul8x16al */
64a88d5d 4350 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4351 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
e9ebed4d
BS
4352 break;
4353 case 0x036: /* VIS I fmul8sux16 */
64a88d5d 4354 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4355 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
e9ebed4d
BS
4356 break;
4357 case 0x037: /* VIS I fmul8ulx16 */
64a88d5d 4358 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4359 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
e9ebed4d
BS
4360 break;
4361 case 0x038: /* VIS I fmuld8sux16 */
64a88d5d 4362 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4363 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
e9ebed4d
BS
4364 break;
4365 case 0x039: /* VIS I fmuld8ulx16 */
64a88d5d 4366 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4367 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
e9ebed4d
BS
4368 break;
4369 case 0x03a: /* VIS I fpack32 */
2dedf314
RH
4370 CHECK_FPU_FEATURE(dc, VIS1);
4371 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4372 break;
e9ebed4d 4373 case 0x03b: /* VIS I fpack16 */
2dedf314
RH
4374 CHECK_FPU_FEATURE(dc, VIS1);
4375 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4376 cpu_dst_32 = gen_dest_fpr_F();
4377 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4378 gen_store_fpr_F(dc, rd, cpu_dst_32);
4379 break;
e9ebed4d 4380 case 0x03d: /* VIS I fpackfix */
2dedf314
RH
4381 CHECK_FPU_FEATURE(dc, VIS1);
4382 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4383 cpu_dst_32 = gen_dest_fpr_F();
4384 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4385 gen_store_fpr_F(dc, rd, cpu_dst_32);
4386 break;
f888300b
RH
4387 case 0x03e: /* VIS I pdist */
4388 CHECK_FPU_FEATURE(dc, VIS1);
4389 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4390 break;
3299908c 4391 case 0x048: /* VIS I faligndata */
64a88d5d 4392 CHECK_FPU_FEATURE(dc, VIS1);
50c796f9 4393 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
3299908c 4394 break;
e9ebed4d 4395 case 0x04b: /* VIS I fpmerge */
64a88d5d 4396 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4397 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
e9ebed4d
BS
4398 break;
4399 case 0x04c: /* VIS II bshuffle */
793a137a
RH
4400 CHECK_FPU_FEATURE(dc, VIS2);
4401 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4402 break;
e9ebed4d 4403 case 0x04d: /* VIS I fexpand */
64a88d5d 4404 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4405 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
e9ebed4d
BS
4406 break;
4407 case 0x050: /* VIS I fpadd16 */
64a88d5d 4408 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4409 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
e9ebed4d
BS
4410 break;
4411 case 0x051: /* VIS I fpadd16s */
64a88d5d 4412 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4413 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
e9ebed4d
BS
4414 break;
4415 case 0x052: /* VIS I fpadd32 */
64a88d5d 4416 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4417 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
e9ebed4d
BS
4418 break;
4419 case 0x053: /* VIS I fpadd32s */
64a88d5d 4420 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4421 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
e9ebed4d
BS
4422 break;
4423 case 0x054: /* VIS I fpsub16 */
64a88d5d 4424 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4425 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
e9ebed4d
BS
4426 break;
4427 case 0x055: /* VIS I fpsub16s */
64a88d5d 4428 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4429 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
e9ebed4d
BS
4430 break;
4431 case 0x056: /* VIS I fpsub32 */
64a88d5d 4432 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4433 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
e9ebed4d
BS
4434 break;
4435 case 0x057: /* VIS I fpsub32s */
64a88d5d 4436 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4437 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
e9ebed4d 4438 break;
3299908c 4439 case 0x060: /* VIS I fzero */
64a88d5d 4440 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4441 cpu_dst_64 = gen_dest_fpr_D();
4442 tcg_gen_movi_i64(cpu_dst_64, 0);
4443 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4444 break;
4445 case 0x061: /* VIS I fzeros */
64a88d5d 4446 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4447 cpu_dst_32 = gen_dest_fpr_F();
4448 tcg_gen_movi_i32(cpu_dst_32, 0);
4449 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4450 break;
e9ebed4d 4451 case 0x062: /* VIS I fnor */
64a88d5d 4452 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4453 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
e9ebed4d
BS
4454 break;
4455 case 0x063: /* VIS I fnors */
64a88d5d 4456 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4457 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
e9ebed4d
BS
4458 break;
4459 case 0x064: /* VIS I fandnot2 */
64a88d5d 4460 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4461 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
e9ebed4d
BS
4462 break;
4463 case 0x065: /* VIS I fandnot2s */
64a88d5d 4464 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4465 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
e9ebed4d
BS
4466 break;
4467 case 0x066: /* VIS I fnot2 */
64a88d5d 4468 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4469 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
e9ebed4d
BS
4470 break;
4471 case 0x067: /* VIS I fnot2s */
64a88d5d 4472 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4473 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
e9ebed4d
BS
4474 break;
4475 case 0x068: /* VIS I fandnot1 */
64a88d5d 4476 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4477 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
e9ebed4d
BS
4478 break;
4479 case 0x069: /* VIS I fandnot1s */
64a88d5d 4480 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4481 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
e9ebed4d
BS
4482 break;
4483 case 0x06a: /* VIS I fnot1 */
64a88d5d 4484 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4485 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
e9ebed4d
BS
4486 break;
4487 case 0x06b: /* VIS I fnot1s */
64a88d5d 4488 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4489 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
e9ebed4d
BS
4490 break;
4491 case 0x06c: /* VIS I fxor */
64a88d5d 4492 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4493 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
e9ebed4d
BS
4494 break;
4495 case 0x06d: /* VIS I fxors */
64a88d5d 4496 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4497 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
e9ebed4d
BS
4498 break;
4499 case 0x06e: /* VIS I fnand */
64a88d5d 4500 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4501 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
e9ebed4d
BS
4502 break;
4503 case 0x06f: /* VIS I fnands */
64a88d5d 4504 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4505 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
e9ebed4d
BS
4506 break;
4507 case 0x070: /* VIS I fand */
64a88d5d 4508 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4509 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
e9ebed4d
BS
4510 break;
4511 case 0x071: /* VIS I fands */
64a88d5d 4512 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4513 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
e9ebed4d
BS
4514 break;
4515 case 0x072: /* VIS I fxnor */
64a88d5d 4516 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4517 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
e9ebed4d
BS
4518 break;
4519 case 0x073: /* VIS I fxnors */
64a88d5d 4520 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4521 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
e9ebed4d 4522 break;
3299908c 4523 case 0x074: /* VIS I fsrc1 */
64a88d5d 4524 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4525 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4526 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4527 break;
4528 case 0x075: /* VIS I fsrc1s */
64a88d5d 4529 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4530 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4531 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4532 break;
e9ebed4d 4533 case 0x076: /* VIS I fornot2 */
64a88d5d 4534 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4535 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
e9ebed4d
BS
4536 break;
4537 case 0x077: /* VIS I fornot2s */
64a88d5d 4538 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4539 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
e9ebed4d 4540 break;
3299908c 4541 case 0x078: /* VIS I fsrc2 */
64a88d5d 4542 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4543 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4544 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4545 break;
4546 case 0x079: /* VIS I fsrc2s */
64a88d5d 4547 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4548 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4549 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4550 break;
e9ebed4d 4551 case 0x07a: /* VIS I fornot1 */
64a88d5d 4552 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4553 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
e9ebed4d
BS
4554 break;
4555 case 0x07b: /* VIS I fornot1s */
64a88d5d 4556 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4557 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
e9ebed4d
BS
4558 break;
4559 case 0x07c: /* VIS I for */
64a88d5d 4560 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4561 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
e9ebed4d
BS
4562 break;
4563 case 0x07d: /* VIS I fors */
64a88d5d 4564 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4565 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
e9ebed4d 4566 break;
3299908c 4567 case 0x07e: /* VIS I fone */
64a88d5d 4568 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4569 cpu_dst_64 = gen_dest_fpr_D();
4570 tcg_gen_movi_i64(cpu_dst_64, -1);
4571 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4572 break;
4573 case 0x07f: /* VIS I fones */
64a88d5d 4574 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4575 cpu_dst_32 = gen_dest_fpr_F();
4576 tcg_gen_movi_i32(cpu_dst_32, -1);
4577 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4578 break;
e9ebed4d
BS
4579 case 0x080: /* VIS I shutdown */
4580 case 0x081: /* VIS II siam */
4581 // XXX
4582 goto illegal_insn;
3299908c
BS
4583 default:
4584 goto illegal_insn;
4585 }
4586#else
0f8a249a 4587 goto ncp_insn;
3299908c
BS
4588#endif
4589 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
fcc72045 4590#ifdef TARGET_SPARC64
0f8a249a 4591 goto illegal_insn;
fcc72045 4592#else
0f8a249a 4593 goto ncp_insn;
fcc72045 4594#endif
3475187d 4595#ifdef TARGET_SPARC64
0f8a249a 4596 } else if (xop == 0x39) { /* V9 return */
a7812ae4 4597 TCGv_i32 r_const;
2ea815ca 4598
66442b07 4599 save_state(dc);
9322a4bf 4600 cpu_src1 = get_src1(insn, cpu_src1);
0f8a249a 4601 if (IS_IMM) { /* immediate */
67526b20
BS
4602 simm = GET_FIELDs(insn, 19, 31);
4603 tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
0f8a249a 4604 } else { /* register */
3475187d 4605 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4606 if (rs2) {
6ae20372
BS
4607 gen_movl_reg_TN(rs2, cpu_src2);
4608 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
6f551262
BS
4609 } else
4610 tcg_gen_mov_tl(cpu_dst, cpu_src1);
3475187d 4611 }
063c3675 4612 gen_helper_restore(cpu_env);
13a6dd00 4613 gen_mov_pc_npc(dc);
2ea815ca 4614 r_const = tcg_const_i32(3);
fe8d8f0f 4615 gen_helper_check_align(cpu_env, cpu_dst, r_const);
a7812ae4 4616 tcg_temp_free_i32(r_const);
6ae20372 4617 tcg_gen_mov_tl(cpu_npc, cpu_dst);
0f8a249a
BS
4618 dc->npc = DYNAMIC_PC;
4619 goto jmp_insn;
3475187d 4620#endif
0f8a249a 4621 } else {
9322a4bf 4622 cpu_src1 = get_src1(insn, cpu_src1);
0f8a249a 4623 if (IS_IMM) { /* immediate */
67526b20
BS
4624 simm = GET_FIELDs(insn, 19, 31);
4625 tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
0f8a249a 4626 } else { /* register */
e80cfcfc 4627 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4628 if (rs2) {
6ae20372
BS
4629 gen_movl_reg_TN(rs2, cpu_src2);
4630 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
6f551262
BS
4631 } else
4632 tcg_gen_mov_tl(cpu_dst, cpu_src1);
cf495bcf 4633 }
0f8a249a
BS
4634 switch (xop) {
4635 case 0x38: /* jmpl */
4636 {
a7812ae4
PB
4637 TCGv r_pc;
4638 TCGv_i32 r_const;
2ea815ca 4639
a7812ae4
PB
4640 r_pc = tcg_const_tl(dc->pc);
4641 gen_movl_TN_reg(rd, r_pc);
4642 tcg_temp_free(r_pc);
13a6dd00 4643 gen_mov_pc_npc(dc);
2ea815ca 4644 r_const = tcg_const_i32(3);
fe8d8f0f 4645 gen_helper_check_align(cpu_env, cpu_dst, r_const);
a7812ae4 4646 tcg_temp_free_i32(r_const);
22036a49 4647 gen_address_mask(dc, cpu_dst);
6ae20372 4648 tcg_gen_mov_tl(cpu_npc, cpu_dst);
0f8a249a
BS
4649 dc->npc = DYNAMIC_PC;
4650 }
4651 goto jmp_insn;
3475187d 4652#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
0f8a249a
BS
4653 case 0x39: /* rett, V9 return */
4654 {
a7812ae4 4655 TCGv_i32 r_const;
2ea815ca 4656
0f8a249a
BS
4657 if (!supervisor(dc))
4658 goto priv_insn;
13a6dd00 4659 gen_mov_pc_npc(dc);
2ea815ca 4660 r_const = tcg_const_i32(3);
fe8d8f0f 4661 gen_helper_check_align(cpu_env, cpu_dst, r_const);
a7812ae4 4662 tcg_temp_free_i32(r_const);
6ae20372 4663 tcg_gen_mov_tl(cpu_npc, cpu_dst);
0f8a249a 4664 dc->npc = DYNAMIC_PC;
063c3675 4665 gen_helper_rett(cpu_env);
0f8a249a
BS
4666 }
4667 goto jmp_insn;
4668#endif
4669 case 0x3b: /* flush */
5578ceab 4670 if (!((dc)->def->features & CPU_FEATURE_FLUSH))
64a88d5d 4671 goto unimp_flush;
dcfd14b3 4672 /* nop */
0f8a249a
BS
4673 break;
4674 case 0x3c: /* save */
66442b07 4675 save_state(dc);
063c3675 4676 gen_helper_save(cpu_env);
6ae20372 4677 gen_movl_TN_reg(rd, cpu_dst);
0f8a249a
BS
4678 break;
4679 case 0x3d: /* restore */
66442b07 4680 save_state(dc);
063c3675 4681 gen_helper_restore(cpu_env);
6ae20372 4682 gen_movl_TN_reg(rd, cpu_dst);
0f8a249a 4683 break;
3475187d 4684#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
0f8a249a
BS
4685 case 0x3e: /* V9 done/retry */
4686 {
4687 switch (rd) {
4688 case 0:
4689 if (!supervisor(dc))
4690 goto priv_insn;
4691 dc->npc = DYNAMIC_PC;
4692 dc->pc = DYNAMIC_PC;
063c3675 4693 gen_helper_done(cpu_env);
0f8a249a
BS
4694 goto jmp_insn;
4695 case 1:
4696 if (!supervisor(dc))
4697 goto priv_insn;
4698 dc->npc = DYNAMIC_PC;
4699 dc->pc = DYNAMIC_PC;
063c3675 4700 gen_helper_retry(cpu_env);
0f8a249a
BS
4701 goto jmp_insn;
4702 default:
4703 goto illegal_insn;
4704 }
4705 }
4706 break;
4707#endif
4708 default:
4709 goto illegal_insn;
4710 }
cf495bcf 4711 }
0f8a249a
BS
4712 break;
4713 }
4714 break;
4715 case 3: /* load/store instructions */
4716 {
4717 unsigned int xop = GET_FIELD(insn, 7, 12);
9322a4bf 4718
cfa90513
BS
4719 /* flush pending conditional evaluations before exposing
4720 cpu state */
4721 if (dc->cc_op != CC_OP_FLAGS) {
4722 dc->cc_op = CC_OP_FLAGS;
2ffd9176 4723 gen_helper_compute_psr(cpu_env);
cfa90513 4724 }
9322a4bf 4725 cpu_src1 = get_src1(insn, cpu_src1);
71817e48 4726 if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
81ad8ba2 4727 rs2 = GET_FIELD(insn, 27, 31);
6ae20372 4728 gen_movl_reg_TN(rs2, cpu_src2);
71817e48
BS
4729 tcg_gen_mov_tl(cpu_addr, cpu_src1);
4730 } else if (IS_IMM) { /* immediate */
67526b20
BS
4731 simm = GET_FIELDs(insn, 19, 31);
4732 tcg_gen_addi_tl(cpu_addr, cpu_src1, simm);
0f8a249a
BS
4733 } else { /* register */
4734 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4735 if (rs2 != 0) {
6ae20372
BS
4736 gen_movl_reg_TN(rs2, cpu_src2);
4737 tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2);
6f551262
BS
4738 } else
4739 tcg_gen_mov_tl(cpu_addr, cpu_src1);
0f8a249a 4740 }
2f2ecb83
BS
4741 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
4742 (xop > 0x17 && xop <= 0x1d ) ||
4743 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
0f8a249a 4744 switch (xop) {
b89e94af 4745 case 0x0: /* ld, V9 lduw, load unsigned word */
2cade6a3 4746 gen_address_mask(dc, cpu_addr);
6ae20372 4747 tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4748 break;
b89e94af 4749 case 0x1: /* ldub, load unsigned byte */
2cade6a3 4750 gen_address_mask(dc, cpu_addr);
6ae20372 4751 tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4752 break;
b89e94af 4753 case 0x2: /* lduh, load unsigned halfword */
2cade6a3 4754 gen_address_mask(dc, cpu_addr);
6ae20372 4755 tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4756 break;
b89e94af 4757 case 0x3: /* ldd, load double word */
0f8a249a 4758 if (rd & 1)
d4218d99 4759 goto illegal_insn;
1a2fb1c0 4760 else {
a7812ae4 4761 TCGv_i32 r_const;
2ea815ca 4762
66442b07 4763 save_state(dc);
2ea815ca 4764 r_const = tcg_const_i32(7);
fe8d8f0f
BS
4765 /* XXX remove alignment check */
4766 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 4767 tcg_temp_free_i32(r_const);
2cade6a3 4768 gen_address_mask(dc, cpu_addr);
6ae20372 4769 tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
32b6c812
BS
4770 tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
4771 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL);
4772 gen_movl_TN_reg(rd + 1, cpu_tmp0);
8911f501 4773 tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
6ae20372
BS
4774 tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64);
4775 tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL);
1a2fb1c0 4776 }
0f8a249a 4777 break;
b89e94af 4778 case 0x9: /* ldsb, load signed byte */
2cade6a3 4779 gen_address_mask(dc, cpu_addr);
6ae20372 4780 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4781 break;
b89e94af 4782 case 0xa: /* ldsh, load signed halfword */
2cade6a3 4783 gen_address_mask(dc, cpu_addr);
6ae20372 4784 tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4785 break;
4786 case 0xd: /* ldstub -- XXX: should be atomically */
2ea815ca
BS
4787 {
4788 TCGv r_const;
4789
2cade6a3 4790 gen_address_mask(dc, cpu_addr);
2ea815ca
BS
4791 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
4792 r_const = tcg_const_tl(0xff);
4793 tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
4794 tcg_temp_free(r_const);
4795 }
0f8a249a 4796 break;
b89e94af 4797 case 0x0f: /* swap, swap register with memory. Also
77f193da 4798 atomically */
64a88d5d 4799 CHECK_IU_FEATURE(dc, SWAP);
6ae20372 4800 gen_movl_reg_TN(rd, cpu_val);
2cade6a3 4801 gen_address_mask(dc, cpu_addr);
527067d8 4802 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
6ae20372 4803 tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
527067d8 4804 tcg_gen_mov_tl(cpu_val, cpu_tmp0);
0f8a249a 4805 break;
3475187d 4806#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 4807 case 0x10: /* lda, V9 lduwa, load word alternate */
3475187d 4808#ifndef TARGET_SPARC64
0f8a249a
BS
4809 if (IS_IMM)
4810 goto illegal_insn;
4811 if (!supervisor(dc))
4812 goto priv_insn;
6ea4a6c8 4813#endif
66442b07 4814 save_state(dc);
6ae20372 4815 gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
0f8a249a 4816 break;
b89e94af 4817 case 0x11: /* lduba, load unsigned byte alternate */
3475187d 4818#ifndef TARGET_SPARC64
0f8a249a
BS
4819 if (IS_IMM)
4820 goto illegal_insn;
4821 if (!supervisor(dc))
4822 goto priv_insn;
4823#endif
66442b07 4824 save_state(dc);
6ae20372 4825 gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
0f8a249a 4826 break;
b89e94af 4827 case 0x12: /* lduha, load unsigned halfword alternate */
3475187d 4828#ifndef TARGET_SPARC64
0f8a249a
BS
4829 if (IS_IMM)
4830 goto illegal_insn;
4831 if (!supervisor(dc))
4832 goto priv_insn;
3475187d 4833#endif
66442b07 4834 save_state(dc);
6ae20372 4835 gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
0f8a249a 4836 break;
b89e94af 4837 case 0x13: /* ldda, load double word alternate */
3475187d 4838#ifndef TARGET_SPARC64
0f8a249a
BS
4839 if (IS_IMM)
4840 goto illegal_insn;
4841 if (!supervisor(dc))
4842 goto priv_insn;
3475187d 4843#endif
0f8a249a 4844 if (rd & 1)
d4218d99 4845 goto illegal_insn;
66442b07 4846 save_state(dc);
db166940
BS
4847 gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
4848 goto skip_move;
b89e94af 4849 case 0x19: /* ldsba, load signed byte alternate */
3475187d 4850#ifndef TARGET_SPARC64
0f8a249a
BS
4851 if (IS_IMM)
4852 goto illegal_insn;
4853 if (!supervisor(dc))
4854 goto priv_insn;
4855#endif
66442b07 4856 save_state(dc);
6ae20372 4857 gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
0f8a249a 4858 break;
b89e94af 4859 case 0x1a: /* ldsha, load signed halfword alternate */
3475187d 4860#ifndef TARGET_SPARC64
0f8a249a
BS
4861 if (IS_IMM)
4862 goto illegal_insn;
4863 if (!supervisor(dc))
4864 goto priv_insn;
3475187d 4865#endif
66442b07 4866 save_state(dc);
6ae20372 4867 gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
0f8a249a
BS
4868 break;
4869 case 0x1d: /* ldstuba -- XXX: should be atomically */
3475187d 4870#ifndef TARGET_SPARC64
0f8a249a
BS
4871 if (IS_IMM)
4872 goto illegal_insn;
4873 if (!supervisor(dc))
4874 goto priv_insn;
4875#endif
66442b07 4876 save_state(dc);
6ae20372 4877 gen_ldstub_asi(cpu_val, cpu_addr, insn);
0f8a249a 4878 break;
b89e94af 4879 case 0x1f: /* swapa, swap reg with alt. memory. Also
77f193da 4880 atomically */
64a88d5d 4881 CHECK_IU_FEATURE(dc, SWAP);
3475187d 4882#ifndef TARGET_SPARC64
0f8a249a
BS
4883 if (IS_IMM)
4884 goto illegal_insn;
4885 if (!supervisor(dc))
4886 goto priv_insn;
6ea4a6c8 4887#endif
66442b07 4888 save_state(dc);
6ae20372
BS
4889 gen_movl_reg_TN(rd, cpu_val);
4890 gen_swap_asi(cpu_val, cpu_addr, insn);
0f8a249a 4891 break;
3475187d
FB
4892
4893#ifndef TARGET_SPARC64
0f8a249a
BS
4894 case 0x30: /* ldc */
4895 case 0x31: /* ldcsr */
4896 case 0x33: /* lddc */
4897 goto ncp_insn;
3475187d
FB
4898#endif
4899#endif
4900#ifdef TARGET_SPARC64
0f8a249a 4901 case 0x08: /* V9 ldsw */
2cade6a3 4902 gen_address_mask(dc, cpu_addr);
6ae20372 4903 tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4904 break;
4905 case 0x0b: /* V9 ldx */
2cade6a3 4906 gen_address_mask(dc, cpu_addr);
6ae20372 4907 tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4908 break;
4909 case 0x18: /* V9 ldswa */
66442b07 4910 save_state(dc);
6ae20372 4911 gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
0f8a249a
BS
4912 break;
4913 case 0x1b: /* V9 ldxa */
66442b07 4914 save_state(dc);
6ae20372 4915 gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
0f8a249a
BS
4916 break;
4917 case 0x2d: /* V9 prefetch, no effect */
4918 goto skip_move;
4919 case 0x30: /* V9 ldfa */
5b12f1e8 4920 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4921 goto jmp_insn;
4922 }
66442b07 4923 save_state(dc);
6ae20372 4924 gen_ldf_asi(cpu_addr, insn, 4, rd);
638737ad 4925 gen_update_fprs_dirty(rd);
81ad8ba2 4926 goto skip_move;
0f8a249a 4927 case 0x33: /* V9 lddfa */
5b12f1e8 4928 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4929 goto jmp_insn;
4930 }
66442b07 4931 save_state(dc);
6ae20372 4932 gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
638737ad 4933 gen_update_fprs_dirty(DFPREG(rd));
81ad8ba2 4934 goto skip_move;
0f8a249a
BS
4935 case 0x3d: /* V9 prefetcha, no effect */
4936 goto skip_move;
4937 case 0x32: /* V9 ldqfa */
64a88d5d 4938 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 4939 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4940 goto jmp_insn;
4941 }
66442b07 4942 save_state(dc);
6ae20372 4943 gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
638737ad 4944 gen_update_fprs_dirty(QFPREG(rd));
1f587329 4945 goto skip_move;
0f8a249a
BS
4946#endif
4947 default:
4948 goto illegal_insn;
4949 }
6ae20372 4950 gen_movl_TN_reg(rd, cpu_val);
db166940 4951#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 4952 skip_move: ;
3475187d 4953#endif
0f8a249a 4954 } else if (xop >= 0x20 && xop < 0x24) {
5b12f1e8 4955 if (gen_trap_ifnofpu(dc)) {
a80dde08 4956 goto jmp_insn;
5b12f1e8 4957 }
66442b07 4958 save_state(dc);
0f8a249a 4959 switch (xop) {
b89e94af 4960 case 0x20: /* ldf, load fpreg */
2cade6a3 4961 gen_address_mask(dc, cpu_addr);
527067d8 4962 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
208ae657
RH
4963 cpu_dst_32 = gen_dest_fpr_F();
4964 tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0);
4965 gen_store_fpr_F(dc, rd, cpu_dst_32);
0f8a249a 4966 break;
3a3b925d
BS
4967 case 0x21: /* ldfsr, V9 ldxfsr */
4968#ifdef TARGET_SPARC64
2cade6a3 4969 gen_address_mask(dc, cpu_addr);
3a3b925d
BS
4970 if (rd == 1) {
4971 tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
2e2f4ade 4972 gen_helper_ldxfsr(cpu_env, cpu_tmp64);
fe987e23
IK
4973 } else {
4974 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4975 tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
2e2f4ade 4976 gen_helper_ldfsr(cpu_env, cpu_tmp32);
fe987e23 4977 }
3a3b925d
BS
4978#else
4979 {
4980 tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
2e2f4ade 4981 gen_helper_ldfsr(cpu_env, cpu_tmp32);
3a3b925d
BS
4982 }
4983#endif
0f8a249a 4984 break;
b89e94af 4985 case 0x22: /* ldqf, load quad fpreg */
2ea815ca 4986 {
a7812ae4 4987 TCGv_i32 r_const;
2ea815ca
BS
4988
4989 CHECK_FPU_FEATURE(dc, FLOAT128);
4990 r_const = tcg_const_i32(dc->mem_idx);
1295001c 4991 gen_address_mask(dc, cpu_addr);
fe8d8f0f 4992 gen_helper_ldqf(cpu_env, cpu_addr, r_const);
a7812ae4 4993 tcg_temp_free_i32(r_const);
2ea815ca 4994 gen_op_store_QT0_fpr(QFPREG(rd));
638737ad 4995 gen_update_fprs_dirty(QFPREG(rd));
2ea815ca 4996 }
1f587329 4997 break;
b89e94af 4998 case 0x23: /* lddf, load double fpreg */
03fb8cfc
RH
4999 gen_address_mask(dc, cpu_addr);
5000 cpu_dst_64 = gen_dest_fpr_D();
5001 tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
5002 gen_store_fpr_D(dc, rd, cpu_dst_64);
0f8a249a
BS
5003 break;
5004 default:
5005 goto illegal_insn;
5006 }
dc1a6971 5007 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
0f8a249a 5008 xop == 0xe || xop == 0x1e) {
6ae20372 5009 gen_movl_reg_TN(rd, cpu_val);
0f8a249a 5010 switch (xop) {
b89e94af 5011 case 0x4: /* st, store word */
2cade6a3 5012 gen_address_mask(dc, cpu_addr);
6ae20372 5013 tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5014 break;
b89e94af 5015 case 0x5: /* stb, store byte */
2cade6a3 5016 gen_address_mask(dc, cpu_addr);
6ae20372 5017 tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5018 break;
b89e94af 5019 case 0x6: /* sth, store halfword */
2cade6a3 5020 gen_address_mask(dc, cpu_addr);
6ae20372 5021 tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 5022 break;
b89e94af 5023 case 0x7: /* std, store double word */
0f8a249a 5024 if (rd & 1)
d4218d99 5025 goto illegal_insn;
1a2fb1c0 5026 else {
a7812ae4 5027 TCGv_i32 r_const;
1a2fb1c0 5028
66442b07 5029 save_state(dc);
2cade6a3 5030 gen_address_mask(dc, cpu_addr);
2ea815ca 5031 r_const = tcg_const_i32(7);
fe8d8f0f
BS
5032 /* XXX remove alignment check */
5033 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 5034 tcg_temp_free_i32(r_const);
a7ec4229 5035 gen_movl_reg_TN(rd + 1, cpu_tmp0);
ab508019 5036 tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
6ae20372 5037 tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
7fa76c0b 5038 }
0f8a249a 5039 break;
3475187d 5040#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 5041 case 0x14: /* sta, V9 stwa, store word alternate */
3475187d 5042#ifndef TARGET_SPARC64
0f8a249a
BS
5043 if (IS_IMM)
5044 goto illegal_insn;
5045 if (!supervisor(dc))
5046 goto priv_insn;
6ea4a6c8 5047#endif
66442b07 5048 save_state(dc);
6ae20372 5049 gen_st_asi(cpu_val, cpu_addr, insn, 4);
9fd1ae3a 5050 dc->npc = DYNAMIC_PC;
d39c0b99 5051 break;
b89e94af 5052 case 0x15: /* stba, store byte alternate */
3475187d 5053#ifndef TARGET_SPARC64
0f8a249a
BS
5054 if (IS_IMM)
5055 goto illegal_insn;
5056 if (!supervisor(dc))
5057 goto priv_insn;
3475187d 5058#endif
66442b07 5059 save_state(dc);
6ae20372 5060 gen_st_asi(cpu_val, cpu_addr, insn, 1);
9fd1ae3a 5061 dc->npc = DYNAMIC_PC;
d39c0b99 5062 break;
b89e94af 5063 case 0x16: /* stha, store halfword alternate */
3475187d 5064#ifndef TARGET_SPARC64
0f8a249a
BS
5065 if (IS_IMM)
5066 goto illegal_insn;
5067 if (!supervisor(dc))
5068 goto priv_insn;
6ea4a6c8 5069#endif
66442b07 5070 save_state(dc);
6ae20372 5071 gen_st_asi(cpu_val, cpu_addr, insn, 2);
9fd1ae3a 5072 dc->npc = DYNAMIC_PC;
d39c0b99 5073 break;
b89e94af 5074 case 0x17: /* stda, store double word alternate */
3475187d 5075#ifndef TARGET_SPARC64
0f8a249a
BS
5076 if (IS_IMM)
5077 goto illegal_insn;
5078 if (!supervisor(dc))
5079 goto priv_insn;
3475187d 5080#endif
0f8a249a 5081 if (rd & 1)
d4218d99 5082 goto illegal_insn;
1a2fb1c0 5083 else {
66442b07 5084 save_state(dc);
6ae20372 5085 gen_stda_asi(cpu_val, cpu_addr, insn, rd);
1a2fb1c0 5086 }
d39c0b99 5087 break;
e80cfcfc 5088#endif
3475187d 5089#ifdef TARGET_SPARC64
0f8a249a 5090 case 0x0e: /* V9 stx */
2cade6a3 5091 gen_address_mask(dc, cpu_addr);
6ae20372 5092 tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5093 break;
5094 case 0x1e: /* V9 stxa */
66442b07 5095 save_state(dc);
6ae20372 5096 gen_st_asi(cpu_val, cpu_addr, insn, 8);
9fd1ae3a 5097 dc->npc = DYNAMIC_PC;
0f8a249a 5098 break;
3475187d 5099#endif
0f8a249a
BS
5100 default:
5101 goto illegal_insn;
5102 }
5103 } else if (xop > 0x23 && xop < 0x28) {
5b12f1e8 5104 if (gen_trap_ifnofpu(dc)) {
a80dde08 5105 goto jmp_insn;
5b12f1e8 5106 }
66442b07 5107 save_state(dc);
0f8a249a 5108 switch (xop) {
b89e94af 5109 case 0x24: /* stf, store fpreg */
2cade6a3 5110 gen_address_mask(dc, cpu_addr);
208ae657
RH
5111 cpu_src1_32 = gen_load_fpr_F(dc, rd);
5112 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_src1_32);
527067d8 5113 tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx);
0f8a249a
BS
5114 break;
5115 case 0x25: /* stfsr, V9 stxfsr */
3a3b925d 5116#ifdef TARGET_SPARC64
2cade6a3 5117 gen_address_mask(dc, cpu_addr);
c5f9864e 5118 tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUSPARCState, fsr));
3a3b925d
BS
5119 if (rd == 1)
5120 tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
527067d8
BS
5121 else
5122 tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx);
3a3b925d 5123#else
c5f9864e 5124 tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fsr));
6ae20372 5125 tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
3a3b925d 5126#endif
0f8a249a 5127 break;
1f587329
BS
5128 case 0x26:
5129#ifdef TARGET_SPARC64
1f587329 5130 /* V9 stqf, store quad fpreg */
2ea815ca 5131 {
a7812ae4 5132 TCGv_i32 r_const;
2ea815ca
BS
5133
5134 CHECK_FPU_FEATURE(dc, FLOAT128);
5135 gen_op_load_fpr_QT0(QFPREG(rd));
5136 r_const = tcg_const_i32(dc->mem_idx);
1295001c 5137 gen_address_mask(dc, cpu_addr);
fe8d8f0f 5138 gen_helper_stqf(cpu_env, cpu_addr, r_const);
a7812ae4 5139 tcg_temp_free_i32(r_const);
2ea815ca 5140 }
1f587329 5141 break;
1f587329
BS
5142#else /* !TARGET_SPARC64 */
5143 /* stdfq, store floating point queue */
5144#if defined(CONFIG_USER_ONLY)
5145 goto illegal_insn;
5146#else
0f8a249a
BS
5147 if (!supervisor(dc))
5148 goto priv_insn;
5b12f1e8 5149 if (gen_trap_ifnofpu(dc)) {
0f8a249a 5150 goto jmp_insn;
5b12f1e8 5151 }
0f8a249a 5152 goto nfq_insn;
1f587329 5153#endif
0f8a249a 5154#endif
b89e94af 5155 case 0x27: /* stdf, store double fpreg */
03fb8cfc
RH
5156 gen_address_mask(dc, cpu_addr);
5157 cpu_src1_64 = gen_load_fpr_D(dc, rd);
5158 tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
0f8a249a
BS
5159 break;
5160 default:
5161 goto illegal_insn;
5162 }
5163 } else if (xop > 0x33 && xop < 0x3f) {
66442b07 5164 save_state(dc);
0f8a249a 5165 switch (xop) {
a4d17f19 5166#ifdef TARGET_SPARC64
0f8a249a 5167 case 0x34: /* V9 stfa */
5b12f1e8 5168 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5169 goto jmp_insn;
5170 }
6ae20372 5171 gen_stf_asi(cpu_addr, insn, 4, rd);
0f8a249a 5172 break;
1f587329 5173 case 0x36: /* V9 stqfa */
2ea815ca 5174 {
a7812ae4 5175 TCGv_i32 r_const;
2ea815ca
BS
5176
5177 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5178 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5179 goto jmp_insn;
5180 }
2ea815ca 5181 r_const = tcg_const_i32(7);
fe8d8f0f 5182 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 5183 tcg_temp_free_i32(r_const);
2ea815ca
BS
5184 gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
5185 }
1f587329 5186 break;
0f8a249a 5187 case 0x37: /* V9 stdfa */
5b12f1e8 5188 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5189 goto jmp_insn;
5190 }
6ae20372 5191 gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
0f8a249a
BS
5192 break;
5193 case 0x3c: /* V9 casa */
71817e48 5194 gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
6ae20372 5195 gen_movl_TN_reg(rd, cpu_val);
0f8a249a
BS
5196 break;
5197 case 0x3e: /* V9 casxa */
71817e48 5198 gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
6ae20372 5199 gen_movl_TN_reg(rd, cpu_val);
0f8a249a 5200 break;
a4d17f19 5201#else
0f8a249a
BS
5202 case 0x34: /* stc */
5203 case 0x35: /* stcsr */
5204 case 0x36: /* stdcq */
5205 case 0x37: /* stdc */
5206 goto ncp_insn;
5207#endif
5208 default:
5209 goto illegal_insn;
5210 }
dc1a6971 5211 } else
0f8a249a
BS
5212 goto illegal_insn;
5213 }
5214 break;
cf495bcf
FB
5215 }
5216 /* default case for non jump instructions */
72cbca10 5217 if (dc->npc == DYNAMIC_PC) {
0f8a249a
BS
5218 dc->pc = DYNAMIC_PC;
5219 gen_op_next_insn();
72cbca10
FB
5220 } else if (dc->npc == JUMP_PC) {
5221 /* we can do a static jump */
6ae20372 5222 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
72cbca10
FB
5223 dc->is_br = 1;
5224 } else {
0f8a249a
BS
5225 dc->pc = dc->npc;
5226 dc->npc = dc->npc + 4;
cf495bcf 5227 }
e80cfcfc 5228 jmp_insn:
42a8aa83 5229 goto egress;
cf495bcf 5230 illegal_insn:
2ea815ca 5231 {
a7812ae4 5232 TCGv_i32 r_const;
2ea815ca 5233
66442b07 5234 save_state(dc);
2ea815ca 5235 r_const = tcg_const_i32(TT_ILL_INSN);
bc265319 5236 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5237 tcg_temp_free_i32(r_const);
2ea815ca
BS
5238 dc->is_br = 1;
5239 }
42a8aa83 5240 goto egress;
64a88d5d 5241 unimp_flush:
2ea815ca 5242 {
a7812ae4 5243 TCGv_i32 r_const;
2ea815ca 5244
66442b07 5245 save_state(dc);
2ea815ca 5246 r_const = tcg_const_i32(TT_UNIMP_FLUSH);
bc265319 5247 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5248 tcg_temp_free_i32(r_const);
2ea815ca
BS
5249 dc->is_br = 1;
5250 }
42a8aa83 5251 goto egress;
e80cfcfc 5252#if !defined(CONFIG_USER_ONLY)
e8af50a3 5253 priv_insn:
2ea815ca 5254 {
a7812ae4 5255 TCGv_i32 r_const;
2ea815ca 5256
66442b07 5257 save_state(dc);
2ea815ca 5258 r_const = tcg_const_i32(TT_PRIV_INSN);
bc265319 5259 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5260 tcg_temp_free_i32(r_const);
2ea815ca
BS
5261 dc->is_br = 1;
5262 }
42a8aa83 5263 goto egress;
64a88d5d 5264#endif
e80cfcfc 5265 nfpu_insn:
66442b07 5266 save_state(dc);
e80cfcfc
FB
5267 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
5268 dc->is_br = 1;
42a8aa83 5269 goto egress;
64a88d5d 5270#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
9143e598 5271 nfq_insn:
66442b07 5272 save_state(dc);
9143e598
BS
5273 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
5274 dc->is_br = 1;
42a8aa83 5275 goto egress;
9143e598 5276#endif
fcc72045
BS
5277#ifndef TARGET_SPARC64
5278 ncp_insn:
2ea815ca
BS
5279 {
5280 TCGv r_const;
5281
66442b07 5282 save_state(dc);
2ea815ca 5283 r_const = tcg_const_i32(TT_NCP_INSN);
bc265319 5284 gen_helper_raise_exception(cpu_env, r_const);
2ea815ca
BS
5285 tcg_temp_free(r_const);
5286 dc->is_br = 1;
5287 }
42a8aa83 5288 goto egress;
fcc72045 5289#endif
42a8aa83
RH
5290 egress:
5291 tcg_temp_free(cpu_tmp1);
5292 tcg_temp_free(cpu_tmp2);
30038fd8
RH
5293 if (dc->n_t32 != 0) {
5294 int i;
5295 for (i = dc->n_t32 - 1; i >= 0; --i) {
5296 tcg_temp_free_i32(dc->t32[i]);
5297 }
5298 dc->n_t32 = 0;
5299 }
7a3f1944
FB
5300}
5301
2cfc5f17
TS
5302static inline void gen_intermediate_code_internal(TranslationBlock * tb,
5303 int spc, CPUSPARCState *env)
7a3f1944 5304{
72cbca10 5305 target_ulong pc_start, last_pc;
cf495bcf
FB
5306 uint16_t *gen_opc_end;
5307 DisasContext dc1, *dc = &dc1;
a1d1bb31 5308 CPUBreakpoint *bp;
e8af50a3 5309 int j, lj = -1;
2e70f6ef
PB
5310 int num_insns;
5311 int max_insns;
0184e266 5312 unsigned int insn;
cf495bcf
FB
5313
5314 memset(dc, 0, sizeof(DisasContext));
cf495bcf 5315 dc->tb = tb;
72cbca10 5316 pc_start = tb->pc;
cf495bcf 5317 dc->pc = pc_start;
e80cfcfc 5318 last_pc = dc->pc;
72cbca10 5319 dc->npc = (target_ulong) tb->cs_base;
8393617c 5320 dc->cc_op = CC_OP_DYNAMIC;
6f27aba6 5321 dc->mem_idx = cpu_mmu_index(env);
5578ceab 5322 dc->def = env->def;
f838e2c5
BS
5323 dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5324 dc->address_mask_32bit = tb_am_enabled(tb->flags);
060718c1 5325 dc->singlestep = (env->singlestep_enabled || singlestep);
cf495bcf 5326 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
cf495bcf 5327
a7812ae4
PB
5328 cpu_tmp0 = tcg_temp_new();
5329 cpu_tmp32 = tcg_temp_new_i32();
5330 cpu_tmp64 = tcg_temp_new_i64();
d987963a 5331
a7812ae4 5332 cpu_dst = tcg_temp_local_new();
d987963a
BS
5333
5334 // loads and stores
a7812ae4
PB
5335 cpu_val = tcg_temp_local_new();
5336 cpu_addr = tcg_temp_local_new();
1a2fb1c0 5337
2e70f6ef
PB
5338 num_insns = 0;
5339 max_insns = tb->cflags & CF_COUNT_MASK;
5340 if (max_insns == 0)
5341 max_insns = CF_COUNT_MASK;
5342 gen_icount_start();
cf495bcf 5343 do {
72cf2d4f
BS
5344 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5345 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 5346 if (bp->pc == dc->pc) {
0f8a249a 5347 if (dc->pc != pc_start)
66442b07 5348 save_state(dc);
bc265319 5349 gen_helper_debug(cpu_env);
57fec1fe 5350 tcg_gen_exit_tb(0);
0f8a249a 5351 dc->is_br = 1;
e80cfcfc 5352 goto exit_gen_loop;
e8af50a3
FB
5353 }
5354 }
5355 }
5356 if (spc) {
93fcfe39 5357 qemu_log("Search PC...\n");
e8af50a3
FB
5358 j = gen_opc_ptr - gen_opc_buf;
5359 if (lj < j) {
5360 lj++;
5361 while (lj < j)
5362 gen_opc_instr_start[lj++] = 0;
5363 gen_opc_pc[lj] = dc->pc;
5364 gen_opc_npc[lj] = dc->npc;
5365 gen_opc_instr_start[lj] = 1;
2e70f6ef 5366 gen_opc_icount[lj] = num_insns;
e8af50a3
FB
5367 }
5368 }
2e70f6ef
PB
5369 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
5370 gen_io_start();
0f8a249a 5371 last_pc = dc->pc;
0184e266
BS
5372 insn = cpu_ldl_code(env, dc->pc);
5373 disas_sparc_insn(dc, insn);
2e70f6ef 5374 num_insns++;
0f8a249a
BS
5375
5376 if (dc->is_br)
5377 break;
5378 /* if the next PC is different, we abort now */
5379 if (dc->pc != (last_pc + 4))
5380 break;
d39c0b99
FB
5381 /* if we reach a page boundary, we stop generation so that the
5382 PC of a TT_TFAULT exception is always in the right page */
5383 if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5384 break;
e80cfcfc
FB
5385 /* if single step mode, we generate only one instruction and
5386 generate an exception */
060718c1 5387 if (dc->singlestep) {
e80cfcfc
FB
5388 break;
5389 }
cf495bcf 5390 } while ((gen_opc_ptr < gen_opc_end) &&
2e70f6ef
PB
5391 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5392 num_insns < max_insns);
e80cfcfc
FB
5393
5394 exit_gen_loop:
d987963a 5395 tcg_temp_free(cpu_addr);
3f0436fe 5396 tcg_temp_free(cpu_val);
d987963a 5397 tcg_temp_free(cpu_dst);
a7812ae4
PB
5398 tcg_temp_free_i64(cpu_tmp64);
5399 tcg_temp_free_i32(cpu_tmp32);
2ea815ca 5400 tcg_temp_free(cpu_tmp0);
96eda024 5401
2e70f6ef
PB
5402 if (tb->cflags & CF_LAST_IO)
5403 gen_io_end();
72cbca10 5404 if (!dc->is_br) {
5fafdf24 5405 if (dc->pc != DYNAMIC_PC &&
72cbca10
FB
5406 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5407 /* static PC and NPC: we can use direct chaining */
2f5680ee 5408 gen_goto_tb(dc, 0, dc->pc, dc->npc);
72cbca10
FB
5409 } else {
5410 if (dc->pc != DYNAMIC_PC)
2f5680ee 5411 tcg_gen_movi_tl(cpu_pc, dc->pc);
934da7ee 5412 save_npc(dc);
57fec1fe 5413 tcg_gen_exit_tb(0);
72cbca10
FB
5414 }
5415 }
2e70f6ef 5416 gen_icount_end(tb, num_insns);
cf495bcf 5417 *gen_opc_ptr = INDEX_op_end;
e8af50a3
FB
5418 if (spc) {
5419 j = gen_opc_ptr - gen_opc_buf;
5420 lj++;
5421 while (lj <= j)
5422 gen_opc_instr_start[lj++] = 0;
e8af50a3 5423#if 0
93fcfe39 5424 log_page_dump();
e8af50a3 5425#endif
c3278b7b
FB
5426 gen_opc_jump_pc[0] = dc->jump_pc[0];
5427 gen_opc_jump_pc[1] = dc->jump_pc[1];
e8af50a3 5428 } else {
e80cfcfc 5429 tb->size = last_pc + 4 - pc_start;
2e70f6ef 5430 tb->icount = num_insns;
e8af50a3 5431 }
7a3f1944 5432#ifdef DEBUG_DISAS
8fec2b8c 5433 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
5434 qemu_log("--------------\n");
5435 qemu_log("IN: %s\n", lookup_symbol(pc_start));
5436 log_target_disas(pc_start, last_pc + 4 - pc_start, 0);
5437 qemu_log("\n");
cf495bcf 5438 }
7a3f1944 5439#endif
7a3f1944
FB
5440}
5441
2cfc5f17 5442void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5443{
2cfc5f17 5444 gen_intermediate_code_internal(tb, 0, env);
7a3f1944
FB
5445}
5446
2cfc5f17 5447void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5448{
2cfc5f17 5449 gen_intermediate_code_internal(tb, 1, env);
7a3f1944
FB
5450}
5451
c48fcb47 5452void gen_intermediate_code_init(CPUSPARCState *env)
e80cfcfc 5453{
f5069b26 5454 unsigned int i;
c48fcb47 5455 static int inited;
f5069b26
BS
5456 static const char * const gregnames[8] = {
5457 NULL, // g0 not used
5458 "g1",
5459 "g2",
5460 "g3",
5461 "g4",
5462 "g5",
5463 "g6",
5464 "g7",
5465 };
30038fd8
RH
5466 static const char * const fregnames[32] = {
5467 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5468 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5469 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5470 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5471 };
aaed909a 5472
1a2fb1c0
BS
5473 /* init various static tables */
5474 if (!inited) {
5475 inited = 1;
5476
a7812ae4
PB
5477 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
5478 cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
c5f9864e 5479 offsetof(CPUSPARCState, regwptr),
a7812ae4 5480 "regwptr");
1a2fb1c0 5481#ifdef TARGET_SPARC64
c5f9864e 5482 cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, xcc),
a7812ae4 5483 "xcc");
c5f9864e 5484 cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, asi),
a7812ae4 5485 "asi");
c5f9864e 5486 cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, fprs),
a7812ae4 5487 "fprs");
c5f9864e 5488 cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, gsr),
255e1fcb 5489 "gsr");
a7812ae4 5490 cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5491 offsetof(CPUSPARCState, tick_cmpr),
255e1fcb 5492 "tick_cmpr");
a7812ae4 5493 cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5494 offsetof(CPUSPARCState, stick_cmpr),
255e1fcb 5495 "stick_cmpr");
a7812ae4 5496 cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5497 offsetof(CPUSPARCState, hstick_cmpr),
255e1fcb 5498 "hstick_cmpr");
c5f9864e 5499 cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hintp),
255e1fcb 5500 "hintp");
c5f9864e 5501 cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, htba),
a7812ae4 5502 "htba");
c5f9864e 5503 cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hver),
a7812ae4
PB
5504 "hver");
5505 cpu_ssr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5506 offsetof(CPUSPARCState, ssr), "ssr");
a7812ae4 5507 cpu_ver = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5508 offsetof(CPUSPARCState, version), "ver");
a7812ae4 5509 cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
c5f9864e 5510 offsetof(CPUSPARCState, softint),
a7812ae4 5511 "softint");
255e1fcb 5512#else
c5f9864e 5513 cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, wim),
255e1fcb 5514 "wim");
1a2fb1c0 5515#endif
c5f9864e 5516 cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cond),
77f193da 5517 "cond");
c5f9864e 5518 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_src),
dc99a3f2 5519 "cc_src");
a7812ae4 5520 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5521 offsetof(CPUSPARCState, cc_src2),
d9bdab86 5522 "cc_src2");
c5f9864e 5523 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_dst),
dc99a3f2 5524 "cc_dst");
c5f9864e 5525 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, cc_op),
8393617c 5526 "cc_op");
c5f9864e 5527 cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, psr),
a7812ae4 5528 "psr");
c5f9864e 5529 cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, fsr),
87e92502 5530 "fsr");
c5f9864e 5531 cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, pc),
48d5c82b 5532 "pc");
c5f9864e 5533 cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, npc),
a7812ae4 5534 "npc");
c5f9864e 5535 cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, y), "y");
255e1fcb 5536#ifndef CONFIG_USER_ONLY
c5f9864e 5537 cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, tbr),
255e1fcb
BS
5538 "tbr");
5539#endif
30038fd8 5540 for (i = 1; i < 8; i++) {
a7812ae4 5541 cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5542 offsetof(CPUSPARCState, gregs[i]),
f5069b26 5543 gregnames[i]);
30038fd8
RH
5544 }
5545 for (i = 0; i < TARGET_DPREGS; i++) {
5546 cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
c5f9864e 5547 offsetof(CPUSPARCState, fpr[i]),
45c7b743 5548 fregnames[i]);
30038fd8 5549 }
714547bb 5550
c9e03d8f
BS
5551 /* register helpers */
5552
a7812ae4 5553#define GEN_HELPER 2
c9e03d8f 5554#include "helper.h"
1a2fb1c0 5555 }
658138bc 5556}
d2856f1a 5557
c5f9864e 5558void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
5559{
5560 target_ulong npc;
5561 env->pc = gen_opc_pc[pc_pos];
5562 npc = gen_opc_npc[pc_pos];
5563 if (npc == 1) {
5564 /* dynamic NPC: already stored */
5565 } else if (npc == 2) {
d7da2a10
BS
5566 /* jump PC: use 'cond' and the jump targets of the translation */
5567 if (env->cond) {
d2856f1a 5568 env->npc = gen_opc_jump_pc[0];
d7da2a10 5569 } else {
d2856f1a 5570 env->npc = gen_opc_jump_pc[1];
d7da2a10 5571 }
d2856f1a
AJ
5572 } else {
5573 env->npc = npc;
5574 }
14ed7adc
IK
5575
5576 /* flush pending conditional evaluations before exposing cpu state */
5577 if (CC_OP != CC_OP_FLAGS) {
2ffd9176 5578 helper_compute_psr(env);
14ed7adc 5579 }
d2856f1a 5580}