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