]> git.proxmox.com Git - mirror_qemu.git/blame - target-sparc/translate.c
cpu: Move singlestep_enabled field from CPU_COMMON to CPUState
[mirror_qemu.git] / target-sparc / translate.c
CommitLineData
7a3f1944
FB
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
3475187d 5 Copyright (C) 2003-2005 Fabrice Bellard
7a3f1944
FB
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
8167ee88 18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
7a3f1944
FB
19 */
20
7a3f1944
FB
21#include <stdarg.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <inttypes.h>
26
27#include "cpu.h"
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);
4b4a72e5 325 tcg_gen_exit_tb((tcg_target_long)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_cas_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_cas_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
81634eea 2122static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
c7785e16 2123 TCGv val2, int insn, int rd)
1a2fb1c0 2124{
81634eea
RH
2125 TCGv val1 = gen_load_gpr(dc, rd);
2126 TCGv dst = gen_dest_gpr(dc, rd);
c7785e16 2127 TCGv_i32 r_asi = gen_get_asi(insn, addr);
1a2fb1c0 2128
81634eea 2129 gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
a7812ae4 2130 tcg_temp_free_i32(r_asi);
81634eea 2131 gen_store_gpr(dc, rd, dst);
1a2fb1c0
BS
2132}
2133
2134#elif !defined(CONFIG_USER_ONLY)
2135
77f193da
BS
2136static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
2137 int sign)
1a2fb1c0 2138{
a7812ae4 2139 TCGv_i32 r_asi, r_size, r_sign;
1ec789ab 2140 TCGv_i64 t64 = tcg_temp_new_i64();
1a2fb1c0 2141
2ea815ca
BS
2142 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2143 r_size = tcg_const_i32(size);
2144 r_sign = tcg_const_i32(sign);
1ec789ab
RH
2145 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2146 tcg_temp_free_i32(r_sign);
2147 tcg_temp_free_i32(r_size);
2148 tcg_temp_free_i32(r_asi);
2149 tcg_gen_trunc_i64_tl(dst, t64);
2150 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2151}
2152
4af984a7 2153static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
1a2fb1c0 2154{
a7812ae4 2155 TCGv_i32 r_asi, r_size;
1ec789ab 2156 TCGv_i64 t64 = tcg_temp_new_i64();
1a2fb1c0 2157
1ec789ab 2158 tcg_gen_extu_tl_i64(t64, src);
2ea815ca
BS
2159 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2160 r_size = tcg_const_i32(size);
1ec789ab
RH
2161 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
2162 tcg_temp_free_i32(r_size);
2163 tcg_temp_free_i32(r_asi);
2164 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2165}
2166
06828032 2167static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn)
1a2fb1c0 2168{
a7812ae4 2169 TCGv_i32 r_asi, r_size, r_sign;
1ec789ab 2170 TCGv_i64 r_val, t64;
1a2fb1c0 2171
2ea815ca
BS
2172 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2173 r_size = tcg_const_i32(4);
2174 r_sign = tcg_const_i32(0);
1ec789ab
RH
2175 t64 = tcg_temp_new_i64();
2176 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2ea815ca 2177 tcg_temp_free(r_sign);
a7812ae4 2178 r_val = tcg_temp_new_i64();
06828032 2179 tcg_gen_extu_tl_i64(r_val, src);
fe8d8f0f 2180 gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
a7812ae4 2181 tcg_temp_free_i64(r_val);
1ec789ab
RH
2182 tcg_temp_free_i32(r_size);
2183 tcg_temp_free_i32(r_asi);
2184 tcg_gen_trunc_i64_tl(dst, t64);
2185 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2186}
2187
c7785e16
RH
2188static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2189 int insn, int rd)
1a2fb1c0 2190{
a7812ae4 2191 TCGv_i32 r_asi, r_size, r_sign;
c7785e16 2192 TCGv t;
1ec789ab 2193 TCGv_i64 t64;
1a2fb1c0 2194
2ea815ca
BS
2195 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2196 r_size = tcg_const_i32(8);
2197 r_sign = tcg_const_i32(0);
1ec789ab
RH
2198 t64 = tcg_temp_new_i64();
2199 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
2200 tcg_temp_free_i32(r_sign);
2201 tcg_temp_free_i32(r_size);
2202 tcg_temp_free_i32(r_asi);
c7785e16
RH
2203
2204 t = gen_dest_gpr(dc, rd + 1);
1ec789ab 2205 tcg_gen_trunc_i64_tl(t, t64);
c7785e16
RH
2206 gen_store_gpr(dc, rd + 1, t);
2207
1ec789ab
RH
2208 tcg_gen_shri_i64(t64, t64, 32);
2209 tcg_gen_trunc_i64_tl(hi, t64);
2210 tcg_temp_free_i64(t64);
c7785e16 2211 gen_store_gpr(dc, rd, hi);
0425bee5
BS
2212}
2213
c7785e16
RH
2214static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2215 int insn, int rd)
0425bee5 2216{
a7812ae4 2217 TCGv_i32 r_asi, r_size;
c7785e16 2218 TCGv lo = gen_load_gpr(dc, rd + 1);
1ec789ab 2219 TCGv_i64 t64 = tcg_temp_new_i64();
a7ec4229 2220
1ec789ab 2221 tcg_gen_concat_tl_i64(t64, lo, hi);
2ea815ca
BS
2222 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2223 r_size = tcg_const_i32(8);
1ec789ab
RH
2224 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
2225 tcg_temp_free_i32(r_size);
2226 tcg_temp_free_i32(r_asi);
2227 tcg_temp_free_i64(t64);
1a2fb1c0
BS
2228}
2229#endif
2230
2231#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
4af984a7 2232static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
1a2fb1c0 2233{
a7812ae4
PB
2234 TCGv_i64 r_val;
2235 TCGv_i32 r_asi, r_size;
1a2fb1c0 2236
4af984a7 2237 gen_ld_asi(dst, addr, insn, 1, 0);
1a2fb1c0 2238
2ea815ca
BS
2239 r_val = tcg_const_i64(0xffULL);
2240 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2241 r_size = tcg_const_i32(1);
fe8d8f0f 2242 gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
a7812ae4
PB
2243 tcg_temp_free_i32(r_size);
2244 tcg_temp_free_i32(r_asi);
2245 tcg_temp_free_i64(r_val);
1a2fb1c0
BS
2246}
2247#endif
2248
9d1d4e34 2249static TCGv get_src1(DisasContext *dc, unsigned int insn)
9322a4bf 2250{
9d1d4e34
RH
2251 unsigned int rs1 = GET_FIELD(insn, 13, 17);
2252 return gen_load_gpr(dc, rs1);
9322a4bf
BS
2253}
2254
9d1d4e34 2255static TCGv get_src2(DisasContext *dc, unsigned int insn)
a49d9390 2256{
a49d9390 2257 if (IS_IMM) { /* immediate */
42a8aa83 2258 target_long simm = GET_FIELDs(insn, 19, 31);
9d1d4e34
RH
2259 TCGv t = get_temp_tl(dc);
2260 tcg_gen_movi_tl(t, simm);
2261 return t;
2262 } else { /* register */
42a8aa83 2263 unsigned int rs2 = GET_FIELD(insn, 27, 31);
9d1d4e34 2264 return gen_load_gpr(dc, rs2);
a49d9390 2265 }
a49d9390
BS
2266}
2267
8194f35a 2268#ifdef TARGET_SPARC64
7e480893
RH
2269static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2270{
2271 TCGv_i32 c32, zero, dst, s1, s2;
2272
2273 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2274 or fold the comparison down to 32 bits and use movcond_i32. Choose
2275 the later. */
2276 c32 = tcg_temp_new_i32();
2277 if (cmp->is_bool) {
2278 tcg_gen_trunc_i64_i32(c32, cmp->c1);
2279 } else {
2280 TCGv_i64 c64 = tcg_temp_new_i64();
2281 tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2282 tcg_gen_trunc_i64_i32(c32, c64);
2283 tcg_temp_free_i64(c64);
2284 }
2285
2286 s1 = gen_load_fpr_F(dc, rs);
2287 s2 = gen_load_fpr_F(dc, rd);
ba5f5179 2288 dst = gen_dest_fpr_F(dc);
7e480893
RH
2289 zero = tcg_const_i32(0);
2290
2291 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2292
2293 tcg_temp_free_i32(c32);
2294 tcg_temp_free_i32(zero);
2295 gen_store_fpr_F(dc, rd, dst);
2296}
2297
2298static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2299{
3886b8a3 2300 TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
7e480893
RH
2301 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
2302 gen_load_fpr_D(dc, rs),
2303 gen_load_fpr_D(dc, rd));
2304 gen_store_fpr_D(dc, rd, dst);
2305}
2306
2307static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2308{
2309 int qd = QFPREG(rd);
2310 int qs = QFPREG(rs);
2311
2312 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
2313 cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2314 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
2315 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2316
2317 gen_update_fprs_dirty(qd);
2318}
2319
8194f35a
IK
2320static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
2321{
b551ec04 2322 TCGv_i32 r_tl = tcg_temp_new_i32();
8194f35a
IK
2323
2324 /* load env->tl into r_tl */
b551ec04 2325 tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
8194f35a
IK
2326
2327 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
b551ec04 2328 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
8194f35a
IK
2329
2330 /* calculate offset to current trap state from env->ts, reuse r_tl */
b551ec04 2331 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
c5f9864e 2332 tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
8194f35a
IK
2333
2334 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
b551ec04
JF
2335 {
2336 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2337 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2338 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
bc57c114 2339 tcg_temp_free_ptr(r_tl_tmp);
b551ec04 2340 }
8194f35a 2341
b551ec04 2342 tcg_temp_free_i32(r_tl);
8194f35a 2343}
6c073553
RH
2344
2345static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2346 int width, bool cc, bool left)
2347{
2348 TCGv lo1, lo2, t1, t2;
2349 uint64_t amask, tabl, tabr;
2350 int shift, imask, omask;
2351
2352 if (cc) {
2353 tcg_gen_mov_tl(cpu_cc_src, s1);
2354 tcg_gen_mov_tl(cpu_cc_src2, s2);
2355 tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2356 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2357 dc->cc_op = CC_OP_SUB;
2358 }
2359
2360 /* Theory of operation: there are two tables, left and right (not to
2361 be confused with the left and right versions of the opcode). These
2362 are indexed by the low 3 bits of the inputs. To make things "easy",
2363 these tables are loaded into two constants, TABL and TABR below.
2364 The operation index = (input & imask) << shift calculates the index
2365 into the constant, while val = (table >> index) & omask calculates
2366 the value we're looking for. */
2367 switch (width) {
2368 case 8:
2369 imask = 0x7;
2370 shift = 3;
2371 omask = 0xff;
2372 if (left) {
2373 tabl = 0x80c0e0f0f8fcfeffULL;
2374 tabr = 0xff7f3f1f0f070301ULL;
2375 } else {
2376 tabl = 0x0103070f1f3f7fffULL;
2377 tabr = 0xfffefcf8f0e0c080ULL;
2378 }
2379 break;
2380 case 16:
2381 imask = 0x6;
2382 shift = 1;
2383 omask = 0xf;
2384 if (left) {
2385 tabl = 0x8cef;
2386 tabr = 0xf731;
2387 } else {
2388 tabl = 0x137f;
2389 tabr = 0xfec8;
2390 }
2391 break;
2392 case 32:
2393 imask = 0x4;
2394 shift = 0;
2395 omask = 0x3;
2396 if (left) {
2397 tabl = (2 << 2) | 3;
2398 tabr = (3 << 2) | 1;
2399 } else {
2400 tabl = (1 << 2) | 3;
2401 tabr = (3 << 2) | 2;
2402 }
2403 break;
2404 default:
2405 abort();
2406 }
2407
2408 lo1 = tcg_temp_new();
2409 lo2 = tcg_temp_new();
2410 tcg_gen_andi_tl(lo1, s1, imask);
2411 tcg_gen_andi_tl(lo2, s2, imask);
2412 tcg_gen_shli_tl(lo1, lo1, shift);
2413 tcg_gen_shli_tl(lo2, lo2, shift);
2414
2415 t1 = tcg_const_tl(tabl);
2416 t2 = tcg_const_tl(tabr);
2417 tcg_gen_shr_tl(lo1, t1, lo1);
2418 tcg_gen_shr_tl(lo2, t2, lo2);
2419 tcg_gen_andi_tl(dst, lo1, omask);
2420 tcg_gen_andi_tl(lo2, lo2, omask);
2421
2422 amask = -8;
2423 if (AM_CHECK(dc)) {
2424 amask &= 0xffffffffULL;
2425 }
2426 tcg_gen_andi_tl(s1, s1, amask);
2427 tcg_gen_andi_tl(s2, s2, amask);
2428
2429 /* We want to compute
2430 dst = (s1 == s2 ? lo1 : lo1 & lo2).
2431 We've already done dst = lo1, so this reduces to
2432 dst &= (s1 == s2 ? -1 : lo2)
2433 Which we perform by
2434 lo2 |= -(s1 == s2)
2435 dst &= lo2
2436 */
2437 tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2);
2438 tcg_gen_neg_tl(t1, t1);
2439 tcg_gen_or_tl(lo2, lo2, t1);
2440 tcg_gen_and_tl(dst, dst, lo2);
2441
2442 tcg_temp_free(lo1);
2443 tcg_temp_free(lo2);
2444 tcg_temp_free(t1);
2445 tcg_temp_free(t2);
2446}
add545ab
RH
2447
2448static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
2449{
2450 TCGv tmp = tcg_temp_new();
2451
2452 tcg_gen_add_tl(tmp, s1, s2);
2453 tcg_gen_andi_tl(dst, tmp, -8);
2454 if (left) {
2455 tcg_gen_neg_tl(tmp, tmp);
2456 }
2457 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
2458
2459 tcg_temp_free(tmp);
2460}
50c796f9
RH
2461
2462static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
2463{
2464 TCGv t1, t2, shift;
2465
2466 t1 = tcg_temp_new();
2467 t2 = tcg_temp_new();
2468 shift = tcg_temp_new();
2469
2470 tcg_gen_andi_tl(shift, gsr, 7);
2471 tcg_gen_shli_tl(shift, shift, 3);
2472 tcg_gen_shl_tl(t1, s1, shift);
2473
2474 /* A shift of 64 does not produce 0 in TCG. Divide this into a
2475 shift of (up to 63) followed by a constant shift of 1. */
2476 tcg_gen_xori_tl(shift, shift, 63);
2477 tcg_gen_shr_tl(t2, s2, shift);
2478 tcg_gen_shri_tl(t2, t2, 1);
2479
2480 tcg_gen_or_tl(dst, t1, t2);
2481
2482 tcg_temp_free(t1);
2483 tcg_temp_free(t2);
2484 tcg_temp_free(shift);
2485}
8194f35a
IK
2486#endif
2487
64a88d5d 2488#define CHECK_IU_FEATURE(dc, FEATURE) \
5578ceab 2489 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
2490 goto illegal_insn;
2491#define CHECK_FPU_FEATURE(dc, FEATURE) \
5578ceab 2492 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
64a88d5d
BS
2493 goto nfpu_insn;
2494
0bee699e 2495/* before an instruction, dc->pc must be static */
0184e266 2496static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cf495bcf 2497{
0184e266 2498 unsigned int opc, rs1, rs2, rd;
a4273524 2499 TCGv cpu_src1, cpu_src2;
208ae657 2500 TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
96eda024 2501 TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
67526b20 2502 target_long simm;
7a3f1944 2503
fdefe51c 2504 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
a8c768c0 2505 tcg_gen_debug_insn_start(dc->pc);
fdefe51c 2506 }
0184e266 2507
cf495bcf 2508 opc = GET_FIELD(insn, 0, 1);
cf495bcf 2509 rd = GET_FIELD(insn, 2, 6);
6ae20372 2510
cf495bcf 2511 switch (opc) {
0f8a249a
BS
2512 case 0: /* branches/sethi */
2513 {
2514 unsigned int xop = GET_FIELD(insn, 7, 9);
2515 int32_t target;
2516 switch (xop) {
3475187d 2517#ifdef TARGET_SPARC64
0f8a249a
BS
2518 case 0x1: /* V9 BPcc */
2519 {
2520 int cc;
2521
2522 target = GET_FIELD_SP(insn, 0, 18);
86f1f2ae 2523 target = sign_extend(target, 19);
0f8a249a
BS
2524 target <<= 2;
2525 cc = GET_FIELD_SP(insn, 20, 21);
2526 if (cc == 0)
d4a288ef 2527 do_branch(dc, target, insn, 0);
0f8a249a 2528 else if (cc == 2)
d4a288ef 2529 do_branch(dc, target, insn, 1);
0f8a249a
BS
2530 else
2531 goto illegal_insn;
2532 goto jmp_insn;
2533 }
2534 case 0x3: /* V9 BPr */
2535 {
2536 target = GET_FIELD_SP(insn, 0, 13) |
13846e70 2537 (GET_FIELD_SP(insn, 20, 21) << 14);
0f8a249a
BS
2538 target = sign_extend(target, 16);
2539 target <<= 2;
9d1d4e34 2540 cpu_src1 = get_src1(dc, insn);
d4a288ef 2541 do_branch_reg(dc, target, insn, cpu_src1);
0f8a249a
BS
2542 goto jmp_insn;
2543 }
2544 case 0x5: /* V9 FBPcc */
2545 {
2546 int cc = GET_FIELD_SP(insn, 20, 21);
5b12f1e8 2547 if (gen_trap_ifnofpu(dc)) {
a80dde08 2548 goto jmp_insn;
5b12f1e8 2549 }
0f8a249a
BS
2550 target = GET_FIELD_SP(insn, 0, 18);
2551 target = sign_extend(target, 19);
2552 target <<= 2;
d4a288ef 2553 do_fbranch(dc, target, insn, cc);
0f8a249a
BS
2554 goto jmp_insn;
2555 }
a4d17f19 2556#else
0f8a249a
BS
2557 case 0x7: /* CBN+x */
2558 {
2559 goto ncp_insn;
2560 }
2561#endif
2562 case 0x2: /* BN+x */
2563 {
2564 target = GET_FIELD(insn, 10, 31);
2565 target = sign_extend(target, 22);
2566 target <<= 2;
d4a288ef 2567 do_branch(dc, target, insn, 0);
0f8a249a
BS
2568 goto jmp_insn;
2569 }
2570 case 0x6: /* FBN+x */
2571 {
5b12f1e8 2572 if (gen_trap_ifnofpu(dc)) {
a80dde08 2573 goto jmp_insn;
5b12f1e8 2574 }
0f8a249a
BS
2575 target = GET_FIELD(insn, 10, 31);
2576 target = sign_extend(target, 22);
2577 target <<= 2;
d4a288ef 2578 do_fbranch(dc, target, insn, 0);
0f8a249a
BS
2579 goto jmp_insn;
2580 }
2581 case 0x4: /* SETHI */
97ea2859
RH
2582 /* Special-case %g0 because that's the canonical nop. */
2583 if (rd) {
0f8a249a 2584 uint32_t value = GET_FIELD(insn, 10, 31);
97ea2859
RH
2585 TCGv t = gen_dest_gpr(dc, rd);
2586 tcg_gen_movi_tl(t, value << 10);
2587 gen_store_gpr(dc, rd, t);
0f8a249a 2588 }
0f8a249a
BS
2589 break;
2590 case 0x0: /* UNIMPL */
2591 default:
3475187d 2592 goto illegal_insn;
0f8a249a
BS
2593 }
2594 break;
2595 }
2596 break;
dc1a6971
BS
2597 case 1: /*CALL*/
2598 {
0f8a249a 2599 target_long target = GET_FIELDs(insn, 2, 31) << 2;
97ea2859 2600 TCGv o7 = gen_dest_gpr(dc, 15);
cf495bcf 2601
97ea2859
RH
2602 tcg_gen_movi_tl(o7, dc->pc);
2603 gen_store_gpr(dc, 15, o7);
0f8a249a 2604 target += dc->pc;
13a6dd00 2605 gen_mov_pc_npc(dc);
22036a49
AT
2606#ifdef TARGET_SPARC64
2607 if (unlikely(AM_CHECK(dc))) {
2608 target &= 0xffffffffULL;
2609 }
2610#endif
0f8a249a
BS
2611 dc->npc = target;
2612 }
2613 goto jmp_insn;
2614 case 2: /* FPU & Logical Operations */
2615 {
2616 unsigned int xop = GET_FIELD(insn, 7, 12);
e7d51b34 2617 TCGv cpu_dst = get_temp_tl(dc);
de9e9d9f 2618 TCGv cpu_tmp0;
5793f2a4 2619
0f8a249a 2620 if (xop == 0x3a) { /* generate trap */
bd49ed41
RH
2621 int cond = GET_FIELD(insn, 3, 6);
2622 TCGv_i32 trap;
2623 int l1 = -1, mask;
3475187d 2624
bd49ed41
RH
2625 if (cond == 0) {
2626 /* Trap never. */
2627 break;
cf495bcf 2628 }
b04d9890 2629
bd49ed41 2630 save_state(dc);
b04d9890 2631
bd49ed41
RH
2632 if (cond != 8) {
2633 /* Conditional trap. */
3a49e759 2634 DisasCompare cmp;
3475187d 2635#ifdef TARGET_SPARC64
0f8a249a
BS
2636 /* V9 icc/xcc */
2637 int cc = GET_FIELD_SP(insn, 11, 12);
3a49e759
RH
2638 if (cc == 0) {
2639 gen_compare(&cmp, 0, cond, dc);
2640 } else if (cc == 2) {
2641 gen_compare(&cmp, 1, cond, dc);
2642 } else {
0f8a249a 2643 goto illegal_insn;
3a49e759 2644 }
3475187d 2645#else
3a49e759 2646 gen_compare(&cmp, 0, cond, dc);
3475187d 2647#endif
b158a785 2648 l1 = gen_new_label();
3a49e759
RH
2649 tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
2650 cmp.c1, cmp.c2, l1);
2651 free_compare(&cmp);
bd49ed41 2652 }
b158a785 2653
bd49ed41
RH
2654 mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
2655 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
2656
2657 /* Don't use the normal temporaries, as they may well have
2658 gone out of scope with the branch above. While we're
2659 doing that we might as well pre-truncate to 32-bit. */
2660 trap = tcg_temp_new_i32();
2661
2662 rs1 = GET_FIELD_SP(insn, 14, 18);
2663 if (IS_IMM) {
2664 rs2 = GET_FIELD_SP(insn, 0, 6);
2665 if (rs1 == 0) {
2666 tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
2667 /* Signal that the trap value is fully constant. */
2668 mask = 0;
2669 } else {
97ea2859 2670 TCGv t1 = gen_load_gpr(dc, rs1);
bd49ed41 2671 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
2672 tcg_gen_addi_i32(trap, trap, rs2);
2673 }
2674 } else {
97ea2859 2675 TCGv t1, t2;
bd49ed41 2676 rs2 = GET_FIELD_SP(insn, 0, 4);
97ea2859
RH
2677 t1 = gen_load_gpr(dc, rs1);
2678 t2 = gen_load_gpr(dc, rs2);
bd49ed41
RH
2679 tcg_gen_add_tl(t1, t1, t2);
2680 tcg_gen_trunc_tl_i32(trap, t1);
bd49ed41
RH
2681 }
2682 if (mask != 0) {
2683 tcg_gen_andi_i32(trap, trap, mask);
2684 tcg_gen_addi_i32(trap, trap, TT_TRAP);
2685 }
2686
2687 gen_helper_raise_exception(cpu_env, trap);
2688 tcg_temp_free_i32(trap);
b158a785 2689
fe1755cb
RH
2690 if (cond == 8) {
2691 /* An unconditional trap ends the TB. */
2692 dc->is_br = 1;
2693 goto jmp_insn;
2694 } else {
2695 /* A conditional trap falls through to the next insn. */
b158a785 2696 gen_set_label(l1);
fe1755cb 2697 break;
cf495bcf
FB
2698 }
2699 } else if (xop == 0x28) {
2700 rs1 = GET_FIELD(insn, 13, 17);
2701 switch(rs1) {
2702 case 0: /* rdy */
65fe7b09
BS
2703#ifndef TARGET_SPARC64
2704 case 0x01 ... 0x0e: /* undefined in the SPARCv8
2705 manual, rdy on the microSPARC
2706 II */
2707 case 0x0f: /* stbar in the SPARCv8 manual,
2708 rdy on the microSPARC II */
2709 case 0x10 ... 0x1f: /* implementation-dependent in the
2710 SPARCv8 manual, rdy on the
2711 microSPARC II */
4a2ba232
FC
2712 /* Read Asr17 */
2713 if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
97ea2859 2714 TCGv t = gen_dest_gpr(dc, rd);
4a2ba232 2715 /* Read Asr17 for a Leon3 monoprocessor */
97ea2859
RH
2716 tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1));
2717 gen_store_gpr(dc, rd, t);
4a2ba232
FC
2718 break;
2719 }
65fe7b09 2720#endif
97ea2859 2721 gen_store_gpr(dc, rd, cpu_y);
cf495bcf 2722 break;
3475187d 2723#ifdef TARGET_SPARC64
0f8a249a 2724 case 0x2: /* V9 rdccr */
20132b96 2725 update_psr(dc);
063c3675 2726 gen_helper_rdccr(cpu_dst, cpu_env);
97ea2859 2727 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2728 break;
0f8a249a 2729 case 0x3: /* V9 rdasi */
255e1fcb 2730 tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
97ea2859 2731 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2732 break;
0f8a249a 2733 case 0x4: /* V9 rdtick */
ccd4a219 2734 {
a7812ae4 2735 TCGv_ptr r_tickptr;
ccd4a219 2736
a7812ae4 2737 r_tickptr = tcg_temp_new_ptr();
ccd4a219 2738 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2739 offsetof(CPUSPARCState, tick));
a7812ae4
PB
2740 gen_helper_tick_get_count(cpu_dst, r_tickptr);
2741 tcg_temp_free_ptr(r_tickptr);
97ea2859 2742 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 2743 }
3475187d 2744 break;
0f8a249a 2745 case 0x5: /* V9 rdpc */
2ea815ca 2746 {
97ea2859 2747 TCGv t = gen_dest_gpr(dc, rd);
22036a49 2748 if (unlikely(AM_CHECK(dc))) {
97ea2859 2749 tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL);
22036a49 2750 } else {
97ea2859 2751 tcg_gen_movi_tl(t, dc->pc);
22036a49 2752 }
97ea2859 2753 gen_store_gpr(dc, rd, t);
2ea815ca 2754 }
0f8a249a
BS
2755 break;
2756 case 0x6: /* V9 rdfprs */
255e1fcb 2757 tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
97ea2859 2758 gen_store_gpr(dc, rd, cpu_dst);
3475187d 2759 break;
65fe7b09
BS
2760 case 0xf: /* V9 membar */
2761 break; /* no effect */
0f8a249a 2762 case 0x13: /* Graphics Status */
5b12f1e8 2763 if (gen_trap_ifnofpu(dc)) {
725cb90b 2764 goto jmp_insn;
5b12f1e8 2765 }
97ea2859 2766 gen_store_gpr(dc, rd, cpu_gsr);
725cb90b 2767 break;
9d926598
BS
2768 case 0x16: /* Softint */
2769 tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
97ea2859 2770 gen_store_gpr(dc, rd, cpu_dst);
9d926598 2771 break;
0f8a249a 2772 case 0x17: /* Tick compare */
97ea2859 2773 gen_store_gpr(dc, rd, cpu_tick_cmpr);
83469015 2774 break;
0f8a249a 2775 case 0x18: /* System tick */
ccd4a219 2776 {
a7812ae4 2777 TCGv_ptr r_tickptr;
ccd4a219 2778
a7812ae4 2779 r_tickptr = tcg_temp_new_ptr();
ccd4a219 2780 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2781 offsetof(CPUSPARCState, stick));
a7812ae4
PB
2782 gen_helper_tick_get_count(cpu_dst, r_tickptr);
2783 tcg_temp_free_ptr(r_tickptr);
97ea2859 2784 gen_store_gpr(dc, rd, cpu_dst);
ccd4a219 2785 }
83469015 2786 break;
0f8a249a 2787 case 0x19: /* System tick compare */
97ea2859 2788 gen_store_gpr(dc, rd, cpu_stick_cmpr);
83469015 2789 break;
0f8a249a
BS
2790 case 0x10: /* Performance Control */
2791 case 0x11: /* Performance Instrumentation Counter */
2792 case 0x12: /* Dispatch Control */
2793 case 0x14: /* Softint set, WO */
2794 case 0x15: /* Softint clear, WO */
3475187d
FB
2795#endif
2796 default:
cf495bcf
FB
2797 goto illegal_insn;
2798 }
e8af50a3 2799#if !defined(CONFIG_USER_ONLY)
e9ebed4d 2800 } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
3475187d 2801#ifndef TARGET_SPARC64
20132b96 2802 if (!supervisor(dc)) {
0f8a249a 2803 goto priv_insn;
20132b96
RH
2804 }
2805 update_psr(dc);
063c3675 2806 gen_helper_rdpsr(cpu_dst, cpu_env);
e9ebed4d 2807#else
fb79ceb9 2808 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
2809 if (!hypervisor(dc))
2810 goto priv_insn;
2811 rs1 = GET_FIELD(insn, 13, 17);
2812 switch (rs1) {
2813 case 0: // hpstate
2814 // gen_op_rdhpstate();
2815 break;
2816 case 1: // htstate
2817 // gen_op_rdhtstate();
2818 break;
2819 case 3: // hintp
255e1fcb 2820 tcg_gen_mov_tl(cpu_dst, cpu_hintp);
e9ebed4d
BS
2821 break;
2822 case 5: // htba
255e1fcb 2823 tcg_gen_mov_tl(cpu_dst, cpu_htba);
e9ebed4d
BS
2824 break;
2825 case 6: // hver
255e1fcb 2826 tcg_gen_mov_tl(cpu_dst, cpu_hver);
e9ebed4d
BS
2827 break;
2828 case 31: // hstick_cmpr
255e1fcb 2829 tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
e9ebed4d
BS
2830 break;
2831 default:
2832 goto illegal_insn;
2833 }
2834#endif
97ea2859 2835 gen_store_gpr(dc, rd, cpu_dst);
e8af50a3 2836 break;
3475187d 2837 } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
de9e9d9f 2838 if (!supervisor(dc)) {
0f8a249a 2839 goto priv_insn;
de9e9d9f
RH
2840 }
2841 cpu_tmp0 = get_temp_tl(dc);
3475187d
FB
2842#ifdef TARGET_SPARC64
2843 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2844 switch (rs1) {
2845 case 0: // tpc
375ee38b 2846 {
a7812ae4 2847 TCGv_ptr r_tsptr;
375ee38b 2848
a7812ae4 2849 r_tsptr = tcg_temp_new_ptr();
8194f35a 2850 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
a7812ae4 2851 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2852 offsetof(trap_state, tpc));
a7812ae4 2853 tcg_temp_free_ptr(r_tsptr);
375ee38b 2854 }
0f8a249a
BS
2855 break;
2856 case 1: // tnpc
375ee38b 2857 {
a7812ae4 2858 TCGv_ptr r_tsptr;
375ee38b 2859
a7812ae4 2860 r_tsptr = tcg_temp_new_ptr();
8194f35a 2861 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 2862 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2863 offsetof(trap_state, tnpc));
a7812ae4 2864 tcg_temp_free_ptr(r_tsptr);
375ee38b 2865 }
0f8a249a
BS
2866 break;
2867 case 2: // tstate
375ee38b 2868 {
a7812ae4 2869 TCGv_ptr r_tsptr;
375ee38b 2870
a7812ae4 2871 r_tsptr = tcg_temp_new_ptr();
8194f35a 2872 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 2873 tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
375ee38b 2874 offsetof(trap_state, tstate));
a7812ae4 2875 tcg_temp_free_ptr(r_tsptr);
375ee38b 2876 }
0f8a249a
BS
2877 break;
2878 case 3: // tt
375ee38b 2879 {
45778f99 2880 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
375ee38b 2881
8194f35a 2882 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
45778f99
RH
2883 tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr,
2884 offsetof(trap_state, tt));
a7812ae4 2885 tcg_temp_free_ptr(r_tsptr);
375ee38b 2886 }
0f8a249a
BS
2887 break;
2888 case 4: // tick
ccd4a219 2889 {
a7812ae4 2890 TCGv_ptr r_tickptr;
ccd4a219 2891
a7812ae4 2892 r_tickptr = tcg_temp_new_ptr();
ccd4a219 2893 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 2894 offsetof(CPUSPARCState, tick));
a7812ae4 2895 gen_helper_tick_get_count(cpu_tmp0, r_tickptr);
a7812ae4 2896 tcg_temp_free_ptr(r_tickptr);
ccd4a219 2897 }
0f8a249a
BS
2898 break;
2899 case 5: // tba
255e1fcb 2900 tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
0f8a249a
BS
2901 break;
2902 case 6: // pstate
45778f99
RH
2903 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2904 offsetof(CPUSPARCState, pstate));
0f8a249a
BS
2905 break;
2906 case 7: // tl
45778f99
RH
2907 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2908 offsetof(CPUSPARCState, tl));
0f8a249a
BS
2909 break;
2910 case 8: // pil
45778f99
RH
2911 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2912 offsetof(CPUSPARCState, psrpil));
0f8a249a
BS
2913 break;
2914 case 9: // cwp
063c3675 2915 gen_helper_rdcwp(cpu_tmp0, cpu_env);
0f8a249a
BS
2916 break;
2917 case 10: // cansave
45778f99
RH
2918 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2919 offsetof(CPUSPARCState, cansave));
0f8a249a
BS
2920 break;
2921 case 11: // canrestore
45778f99
RH
2922 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2923 offsetof(CPUSPARCState, canrestore));
0f8a249a
BS
2924 break;
2925 case 12: // cleanwin
45778f99
RH
2926 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2927 offsetof(CPUSPARCState, cleanwin));
0f8a249a
BS
2928 break;
2929 case 13: // otherwin
45778f99
RH
2930 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2931 offsetof(CPUSPARCState, otherwin));
0f8a249a
BS
2932 break;
2933 case 14: // wstate
45778f99
RH
2934 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2935 offsetof(CPUSPARCState, wstate));
0f8a249a 2936 break;
e9ebed4d 2937 case 16: // UA2005 gl
fb79ceb9 2938 CHECK_IU_FEATURE(dc, GL);
45778f99
RH
2939 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
2940 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
2941 break;
2942 case 26: // UA2005 strand status
fb79ceb9 2943 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
2944 if (!hypervisor(dc))
2945 goto priv_insn;
527067d8 2946 tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
e9ebed4d 2947 break;
0f8a249a 2948 case 31: // ver
255e1fcb 2949 tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
0f8a249a
BS
2950 break;
2951 case 15: // fq
2952 default:
2953 goto illegal_insn;
2954 }
3475187d 2955#else
255e1fcb 2956 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
3475187d 2957#endif
97ea2859 2958 gen_store_gpr(dc, rd, cpu_tmp0);
e8af50a3 2959 break;
3475187d
FB
2960 } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
2961#ifdef TARGET_SPARC64
66442b07 2962 save_state(dc);
063c3675 2963 gen_helper_flushw(cpu_env);
3475187d 2964#else
0f8a249a
BS
2965 if (!supervisor(dc))
2966 goto priv_insn;
97ea2859 2967 gen_store_gpr(dc, rd, cpu_tbr);
3475187d 2968#endif
e8af50a3
FB
2969 break;
2970#endif
0f8a249a 2971 } else if (xop == 0x34) { /* FPU Operations */
5b12f1e8 2972 if (gen_trap_ifnofpu(dc)) {
a80dde08 2973 goto jmp_insn;
5b12f1e8 2974 }
0f8a249a 2975 gen_op_clear_ieee_excp_and_FTT();
e8af50a3 2976 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
2977 rs2 = GET_FIELD(insn, 27, 31);
2978 xop = GET_FIELD(insn, 18, 26);
66442b07 2979 save_state(dc);
0f8a249a 2980 switch (xop) {
dc1a6971 2981 case 0x1: /* fmovs */
208ae657
RH
2982 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
2983 gen_store_fpr_F(dc, rd, cpu_src1_32);
dc1a6971
BS
2984 break;
2985 case 0x5: /* fnegs */
61f17f6e 2986 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
dc1a6971
BS
2987 break;
2988 case 0x9: /* fabss */
61f17f6e 2989 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
dc1a6971
BS
2990 break;
2991 case 0x29: /* fsqrts */
2992 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 2993 gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
dc1a6971
BS
2994 break;
2995 case 0x2a: /* fsqrtd */
2996 CHECK_FPU_FEATURE(dc, FSQRT);
61f17f6e 2997 gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
dc1a6971
BS
2998 break;
2999 case 0x2b: /* fsqrtq */
3000 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3001 gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
dc1a6971
BS
3002 break;
3003 case 0x41: /* fadds */
61f17f6e 3004 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
dc1a6971
BS
3005 break;
3006 case 0x42: /* faddd */
61f17f6e 3007 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
dc1a6971
BS
3008 break;
3009 case 0x43: /* faddq */
3010 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3011 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
dc1a6971
BS
3012 break;
3013 case 0x45: /* fsubs */
61f17f6e 3014 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
dc1a6971
BS
3015 break;
3016 case 0x46: /* fsubd */
61f17f6e 3017 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
dc1a6971
BS
3018 break;
3019 case 0x47: /* fsubq */
3020 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3021 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
dc1a6971
BS
3022 break;
3023 case 0x49: /* fmuls */
3024 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3025 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
dc1a6971
BS
3026 break;
3027 case 0x4a: /* fmuld */
3028 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3029 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
dc1a6971
BS
3030 break;
3031 case 0x4b: /* fmulq */
3032 CHECK_FPU_FEATURE(dc, FLOAT128);
3033 CHECK_FPU_FEATURE(dc, FMUL);
61f17f6e 3034 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
dc1a6971
BS
3035 break;
3036 case 0x4d: /* fdivs */
61f17f6e 3037 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
dc1a6971
BS
3038 break;
3039 case 0x4e: /* fdivd */
61f17f6e 3040 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
dc1a6971
BS
3041 break;
3042 case 0x4f: /* fdivq */
3043 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3044 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
dc1a6971
BS
3045 break;
3046 case 0x69: /* fsmuld */
3047 CHECK_FPU_FEATURE(dc, FSMULD);
61f17f6e 3048 gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
dc1a6971
BS
3049 break;
3050 case 0x6e: /* fdmulq */
3051 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3052 gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
dc1a6971
BS
3053 break;
3054 case 0xc4: /* fitos */
61f17f6e 3055 gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
dc1a6971
BS
3056 break;
3057 case 0xc6: /* fdtos */
61f17f6e 3058 gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
dc1a6971
BS
3059 break;
3060 case 0xc7: /* fqtos */
3061 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3062 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
dc1a6971
BS
3063 break;
3064 case 0xc8: /* fitod */
61f17f6e 3065 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
dc1a6971
BS
3066 break;
3067 case 0xc9: /* fstod */
61f17f6e 3068 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
dc1a6971
BS
3069 break;
3070 case 0xcb: /* fqtod */
3071 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3072 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
dc1a6971
BS
3073 break;
3074 case 0xcc: /* fitoq */
3075 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3076 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
dc1a6971
BS
3077 break;
3078 case 0xcd: /* fstoq */
3079 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3080 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
dc1a6971
BS
3081 break;
3082 case 0xce: /* fdtoq */
3083 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3084 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
dc1a6971
BS
3085 break;
3086 case 0xd1: /* fstoi */
61f17f6e 3087 gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
dc1a6971
BS
3088 break;
3089 case 0xd2: /* fdtoi */
61f17f6e 3090 gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
dc1a6971
BS
3091 break;
3092 case 0xd3: /* fqtoi */
3093 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3094 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
dc1a6971 3095 break;
3475187d 3096#ifdef TARGET_SPARC64
dc1a6971 3097 case 0x2: /* V9 fmovd */
96eda024
RH
3098 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
3099 gen_store_fpr_D(dc, rd, cpu_src1_64);
dc1a6971
BS
3100 break;
3101 case 0x3: /* V9 fmovq */
3102 CHECK_FPU_FEATURE(dc, FLOAT128);
ac11f776 3103 gen_move_Q(rd, rs2);
dc1a6971
BS
3104 break;
3105 case 0x6: /* V9 fnegd */
61f17f6e 3106 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
dc1a6971
BS
3107 break;
3108 case 0x7: /* V9 fnegq */
3109 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3110 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
dc1a6971
BS
3111 break;
3112 case 0xa: /* V9 fabsd */
61f17f6e 3113 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
dc1a6971
BS
3114 break;
3115 case 0xb: /* V9 fabsq */
3116 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3117 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
dc1a6971
BS
3118 break;
3119 case 0x81: /* V9 fstox */
61f17f6e 3120 gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
dc1a6971
BS
3121 break;
3122 case 0x82: /* V9 fdtox */
61f17f6e 3123 gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
dc1a6971
BS
3124 break;
3125 case 0x83: /* V9 fqtox */
3126 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3127 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
dc1a6971
BS
3128 break;
3129 case 0x84: /* V9 fxtos */
61f17f6e 3130 gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
dc1a6971
BS
3131 break;
3132 case 0x88: /* V9 fxtod */
61f17f6e 3133 gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
dc1a6971
BS
3134 break;
3135 case 0x8c: /* V9 fxtoq */
3136 CHECK_FPU_FEATURE(dc, FLOAT128);
61f17f6e 3137 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
dc1a6971 3138 break;
0f8a249a 3139#endif
dc1a6971
BS
3140 default:
3141 goto illegal_insn;
0f8a249a
BS
3142 }
3143 } else if (xop == 0x35) { /* FPU Operations */
3475187d 3144#ifdef TARGET_SPARC64
0f8a249a 3145 int cond;
3475187d 3146#endif
5b12f1e8 3147 if (gen_trap_ifnofpu(dc)) {
a80dde08 3148 goto jmp_insn;
5b12f1e8 3149 }
0f8a249a 3150 gen_op_clear_ieee_excp_and_FTT();
cf495bcf 3151 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a
BS
3152 rs2 = GET_FIELD(insn, 27, 31);
3153 xop = GET_FIELD(insn, 18, 26);
66442b07 3154 save_state(dc);
dcf24905 3155
690995a6
RH
3156#ifdef TARGET_SPARC64
3157#define FMOVR(sz) \
3158 do { \
3159 DisasCompare cmp; \
e7c8afb9 3160 cond = GET_FIELD_SP(insn, 10, 12); \
9d1d4e34 3161 cpu_src1 = get_src1(dc, insn); \
690995a6
RH
3162 gen_compare_reg(&cmp, cond, cpu_src1); \
3163 gen_fmov##sz(dc, &cmp, rd, rs2); \
3164 free_compare(&cmp); \
3165 } while (0)
3166
3167 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
3168 FMOVR(s);
0f8a249a
BS
3169 break;
3170 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
690995a6 3171 FMOVR(d);
0f8a249a
BS
3172 break;
3173 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
64a88d5d 3174 CHECK_FPU_FEATURE(dc, FLOAT128);
690995a6 3175 FMOVR(q);
1f587329 3176 break;
0f8a249a 3177 }
690995a6 3178#undef FMOVR
0f8a249a
BS
3179#endif
3180 switch (xop) {
3475187d 3181#ifdef TARGET_SPARC64
7e480893
RH
3182#define FMOVCC(fcc, sz) \
3183 do { \
3184 DisasCompare cmp; \
714547bb 3185 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3186 gen_fcompare(&cmp, fcc, cond); \
3187 gen_fmov##sz(dc, &cmp, rd, rs2); \
3188 free_compare(&cmp); \
3189 } while (0)
3190
0f8a249a 3191 case 0x001: /* V9 fmovscc %fcc0 */
7e480893 3192 FMOVCC(0, s);
0f8a249a
BS
3193 break;
3194 case 0x002: /* V9 fmovdcc %fcc0 */
7e480893 3195 FMOVCC(0, d);
0f8a249a
BS
3196 break;
3197 case 0x003: /* V9 fmovqcc %fcc0 */
64a88d5d 3198 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3199 FMOVCC(0, q);
1f587329 3200 break;
0f8a249a 3201 case 0x041: /* V9 fmovscc %fcc1 */
7e480893 3202 FMOVCC(1, s);
0f8a249a
BS
3203 break;
3204 case 0x042: /* V9 fmovdcc %fcc1 */
7e480893 3205 FMOVCC(1, d);
0f8a249a
BS
3206 break;
3207 case 0x043: /* V9 fmovqcc %fcc1 */
64a88d5d 3208 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3209 FMOVCC(1, q);
1f587329 3210 break;
0f8a249a 3211 case 0x081: /* V9 fmovscc %fcc2 */
7e480893 3212 FMOVCC(2, s);
0f8a249a
BS
3213 break;
3214 case 0x082: /* V9 fmovdcc %fcc2 */
7e480893 3215 FMOVCC(2, d);
0f8a249a
BS
3216 break;
3217 case 0x083: /* V9 fmovqcc %fcc2 */
64a88d5d 3218 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3219 FMOVCC(2, q);
1f587329 3220 break;
0f8a249a 3221 case 0x0c1: /* V9 fmovscc %fcc3 */
7e480893 3222 FMOVCC(3, s);
0f8a249a
BS
3223 break;
3224 case 0x0c2: /* V9 fmovdcc %fcc3 */
7e480893 3225 FMOVCC(3, d);
0f8a249a
BS
3226 break;
3227 case 0x0c3: /* V9 fmovqcc %fcc3 */
64a88d5d 3228 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3229 FMOVCC(3, q);
1f587329 3230 break;
7e480893
RH
3231#undef FMOVCC
3232#define FMOVCC(xcc, sz) \
3233 do { \
3234 DisasCompare cmp; \
714547bb 3235 cond = GET_FIELD_SP(insn, 14, 17); \
7e480893
RH
3236 gen_compare(&cmp, xcc, cond, dc); \
3237 gen_fmov##sz(dc, &cmp, rd, rs2); \
3238 free_compare(&cmp); \
3239 } while (0)
19f329ad 3240
0f8a249a 3241 case 0x101: /* V9 fmovscc %icc */
7e480893 3242 FMOVCC(0, s);
0f8a249a
BS
3243 break;
3244 case 0x102: /* V9 fmovdcc %icc */
7e480893 3245 FMOVCC(0, d);
b7d69dc2 3246 break;
0f8a249a 3247 case 0x103: /* V9 fmovqcc %icc */
64a88d5d 3248 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3249 FMOVCC(0, q);
1f587329 3250 break;
0f8a249a 3251 case 0x181: /* V9 fmovscc %xcc */
7e480893 3252 FMOVCC(1, s);
0f8a249a
BS
3253 break;
3254 case 0x182: /* V9 fmovdcc %xcc */
7e480893 3255 FMOVCC(1, d);
0f8a249a
BS
3256 break;
3257 case 0x183: /* V9 fmovqcc %xcc */
64a88d5d 3258 CHECK_FPU_FEATURE(dc, FLOAT128);
7e480893 3259 FMOVCC(1, q);
1f587329 3260 break;
7e480893 3261#undef FMOVCC
1f587329
BS
3262#endif
3263 case 0x51: /* fcmps, V9 %fcc */
208ae657
RH
3264 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3265 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3266 gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a 3267 break;
1f587329 3268 case 0x52: /* fcmpd, V9 %fcc */
03fb8cfc
RH
3269 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3270 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3271 gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3272 break;
1f587329 3273 case 0x53: /* fcmpq, V9 %fcc */
64a88d5d 3274 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3275 gen_op_load_fpr_QT0(QFPREG(rs1));
3276 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3277 gen_op_fcmpq(rd & 3);
1f587329 3278 break;
0f8a249a 3279 case 0x55: /* fcmpes, V9 %fcc */
208ae657
RH
3280 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3281 cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3282 gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
0f8a249a
BS
3283 break;
3284 case 0x56: /* fcmped, V9 %fcc */
03fb8cfc
RH
3285 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3286 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3287 gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
0f8a249a 3288 break;
1f587329 3289 case 0x57: /* fcmpeq, V9 %fcc */
64a88d5d 3290 CHECK_FPU_FEATURE(dc, FLOAT128);
1f587329
BS
3291 gen_op_load_fpr_QT0(QFPREG(rs1));
3292 gen_op_load_fpr_QT1(QFPREG(rs2));
7e8c2b6c 3293 gen_op_fcmpeq(rd & 3);
1f587329 3294 break;
0f8a249a
BS
3295 default:
3296 goto illegal_insn;
3297 }
0f8a249a 3298 } else if (xop == 0x2) {
97ea2859 3299 TCGv dst = gen_dest_gpr(dc, rd);
e80cfcfc 3300 rs1 = GET_FIELD(insn, 13, 17);
0f8a249a 3301 if (rs1 == 0) {
97ea2859 3302 /* clr/mov shortcut : or %g0, x, y -> mov x, y */
0f8a249a 3303 if (IS_IMM) { /* immediate */
67526b20 3304 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3305 tcg_gen_movi_tl(dst, simm);
3306 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
3307 } else { /* register */
3308 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3309 if (rs2 == 0) {
3310 tcg_gen_movi_tl(dst, 0);
3311 gen_store_gpr(dc, rd, dst);
3312 } else {
3313 cpu_src2 = gen_load_gpr(dc, rs2);
3314 gen_store_gpr(dc, rd, cpu_src2);
3315 }
0f8a249a 3316 }
0f8a249a 3317 } else {
9d1d4e34 3318 cpu_src1 = get_src1(dc, insn);
0f8a249a 3319 if (IS_IMM) { /* immediate */
67526b20 3320 simm = GET_FIELDs(insn, 19, 31);
97ea2859
RH
3321 tcg_gen_ori_tl(dst, cpu_src1, simm);
3322 gen_store_gpr(dc, rd, dst);
0f8a249a 3323 } else { /* register */
0f8a249a 3324 rs2 = GET_FIELD(insn, 27, 31);
97ea2859
RH
3325 if (rs2 == 0) {
3326 /* mov shortcut: or x, %g0, y -> mov x, y */
3327 gen_store_gpr(dc, rd, cpu_src1);
3328 } else {
3329 cpu_src2 = gen_load_gpr(dc, rs2);
3330 tcg_gen_or_tl(dst, cpu_src1, cpu_src2);
3331 gen_store_gpr(dc, rd, dst);
3332 }
0f8a249a 3333 }
0f8a249a 3334 }
83469015 3335#ifdef TARGET_SPARC64
0f8a249a 3336 } else if (xop == 0x25) { /* sll, V9 sllx */
9d1d4e34 3337 cpu_src1 = get_src1(dc, insn);
0f8a249a 3338 if (IS_IMM) { /* immediate */
67526b20 3339 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3340 if (insn & (1 << 12)) {
67526b20 3341 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3342 } else {
67526b20 3343 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
1a2fb1c0 3344 }
0f8a249a 3345 } else { /* register */
83469015 3346 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3347 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3348 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3349 if (insn & (1 << 12)) {
6ae20372 3350 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
1a2fb1c0 3351 } else {
6ae20372 3352 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
1a2fb1c0 3353 }
01b1fa6d 3354 tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
83469015 3355 }
97ea2859 3356 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3357 } else if (xop == 0x26) { /* srl, V9 srlx */
9d1d4e34 3358 cpu_src1 = get_src1(dc, insn);
0f8a249a 3359 if (IS_IMM) { /* immediate */
67526b20 3360 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3361 if (insn & (1 << 12)) {
67526b20 3362 tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3363 } else {
6ae20372 3364 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
67526b20 3365 tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3366 }
0f8a249a 3367 } else { /* register */
83469015 3368 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3369 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3370 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3371 if (insn & (1 << 12)) {
6ae20372
BS
3372 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3373 tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3374 } else {
6ae20372
BS
3375 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3376 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3377 tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3378 }
83469015 3379 }
97ea2859 3380 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a 3381 } else if (xop == 0x27) { /* sra, V9 srax */
9d1d4e34 3382 cpu_src1 = get_src1(dc, insn);
0f8a249a 3383 if (IS_IMM) { /* immediate */
67526b20 3384 simm = GET_FIELDs(insn, 20, 31);
1a2fb1c0 3385 if (insn & (1 << 12)) {
67526b20 3386 tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
1a2fb1c0 3387 } else {
97ea2859 3388 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
67526b20 3389 tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
1a2fb1c0 3390 }
0f8a249a 3391 } else { /* register */
83469015 3392 rs2 = GET_FIELD(insn, 27, 31);
97ea2859 3393 cpu_src2 = gen_load_gpr(dc, rs2);
de9e9d9f 3394 cpu_tmp0 = get_temp_tl(dc);
1a2fb1c0 3395 if (insn & (1 << 12)) {
6ae20372
BS
3396 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3397 tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
1a2fb1c0 3398 } else {
6ae20372 3399 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
97ea2859 3400 tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
6ae20372 3401 tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
1a2fb1c0 3402 }
83469015 3403 }
97ea2859 3404 gen_store_gpr(dc, rd, cpu_dst);
e80cfcfc 3405#endif
fcc72045 3406 } else if (xop < 0x36) {
cf495bcf 3407 if (xop < 0x20) {
9d1d4e34
RH
3408 cpu_src1 = get_src1(dc, insn);
3409 cpu_src2 = get_src2(dc, insn);
cf495bcf 3410 switch (xop & ~0x10) {
b89e94af 3411 case 0x0: /* add */
97ea2859
RH
3412 if (xop & 0x10) {
3413 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
3414 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3415 dc->cc_op = CC_OP_ADD;
41d72852 3416 } else {
97ea2859 3417 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3418 }
cf495bcf 3419 break;
b89e94af 3420 case 0x1: /* and */
97ea2859 3421 tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3422 if (xop & 0x10) {
38482a77
BS
3423 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3424 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3425 dc->cc_op = CC_OP_LOGIC;
41d72852 3426 }
cf495bcf 3427 break;
b89e94af 3428 case 0x2: /* or */
97ea2859 3429 tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3430 if (xop & 0x10) {
38482a77
BS
3431 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3432 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3433 dc->cc_op = CC_OP_LOGIC;
8393617c 3434 }
0f8a249a 3435 break;
b89e94af 3436 case 0x3: /* xor */
97ea2859 3437 tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3438 if (xop & 0x10) {
38482a77
BS
3439 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3440 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3441 dc->cc_op = CC_OP_LOGIC;
8393617c 3442 }
cf495bcf 3443 break;
b89e94af 3444 case 0x4: /* sub */
97ea2859
RH
3445 if (xop & 0x10) {
3446 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
3447 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
3448 dc->cc_op = CC_OP_SUB;
41d72852 3449 } else {
97ea2859 3450 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
41d72852 3451 }
cf495bcf 3452 break;
b89e94af 3453 case 0x5: /* andn */
97ea2859 3454 tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3455 if (xop & 0x10) {
38482a77
BS
3456 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3457 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3458 dc->cc_op = CC_OP_LOGIC;
8393617c 3459 }
cf495bcf 3460 break;
b89e94af 3461 case 0x6: /* orn */
97ea2859 3462 tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3463 if (xop & 0x10) {
38482a77
BS
3464 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3465 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3466 dc->cc_op = CC_OP_LOGIC;
8393617c 3467 }
cf495bcf 3468 break;
b89e94af 3469 case 0x7: /* xorn */
97ea2859 3470 tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2);
8393617c 3471 if (xop & 0x10) {
38482a77
BS
3472 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3473 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3474 dc->cc_op = CC_OP_LOGIC;
8393617c 3475 }
cf495bcf 3476 break;
b89e94af 3477 case 0x8: /* addx, V9 addc */
70c48285
RH
3478 gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3479 (xop & 0x10));
cf495bcf 3480 break;
ded3ab80 3481#ifdef TARGET_SPARC64
0f8a249a 3482 case 0x9: /* V9 mulx */
97ea2859 3483 tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
ded3ab80
PB
3484 break;
3485#endif
b89e94af 3486 case 0xa: /* umul */
64a88d5d 3487 CHECK_IU_FEATURE(dc, MUL);
6ae20372 3488 gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
8393617c 3489 if (xop & 0x10) {
38482a77
BS
3490 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3491 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3492 dc->cc_op = CC_OP_LOGIC;
8393617c 3493 }
cf495bcf 3494 break;
b89e94af 3495 case 0xb: /* smul */
64a88d5d 3496 CHECK_IU_FEATURE(dc, MUL);
6ae20372 3497 gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
8393617c 3498 if (xop & 0x10) {
38482a77
BS
3499 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3500 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3501 dc->cc_op = CC_OP_LOGIC;
8393617c 3502 }
cf495bcf 3503 break;
b89e94af 3504 case 0xc: /* subx, V9 subc */
70c48285
RH
3505 gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3506 (xop & 0x10));
cf495bcf 3507 break;
ded3ab80 3508#ifdef TARGET_SPARC64
0f8a249a 3509 case 0xd: /* V9 udivx */
c28ae41e 3510 gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
ded3ab80
PB
3511 break;
3512#endif
b89e94af 3513 case 0xe: /* udiv */
64a88d5d 3514 CHECK_IU_FEATURE(dc, DIV);
8393617c 3515 if (xop & 0x10) {
7a5e4488
BS
3516 gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
3517 cpu_src2);
6c78ea32 3518 dc->cc_op = CC_OP_DIV;
0fcec41e 3519 } else {
7a5e4488
BS
3520 gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
3521 cpu_src2);
8393617c 3522 }
cf495bcf 3523 break;
b89e94af 3524 case 0xf: /* sdiv */
64a88d5d 3525 CHECK_IU_FEATURE(dc, DIV);
8393617c 3526 if (xop & 0x10) {
7a5e4488
BS
3527 gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
3528 cpu_src2);
6c78ea32 3529 dc->cc_op = CC_OP_DIV;
0fcec41e 3530 } else {
7a5e4488
BS
3531 gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
3532 cpu_src2);
8393617c 3533 }
cf495bcf
FB
3534 break;
3535 default:
3536 goto illegal_insn;
3537 }
97ea2859 3538 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3539 } else {
9d1d4e34
RH
3540 cpu_src1 = get_src1(dc, insn);
3541 cpu_src2 = get_src2(dc, insn);
cf495bcf 3542 switch (xop) {
0f8a249a 3543 case 0x20: /* taddcc */
a2ea4aa9 3544 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3545 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
3546 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
3547 dc->cc_op = CC_OP_TADD;
0f8a249a
BS
3548 break;
3549 case 0x21: /* tsubcc */
a2ea4aa9 3550 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3551 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92
BS
3552 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
3553 dc->cc_op = CC_OP_TSUB;
0f8a249a
BS
3554 break;
3555 case 0x22: /* taddcctv */
a2ea4aa9
RH
3556 gen_helper_taddcctv(cpu_dst, cpu_env,
3557 cpu_src1, cpu_src2);
97ea2859 3558 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 3559 dc->cc_op = CC_OP_TADDTV;
0f8a249a
BS
3560 break;
3561 case 0x23: /* tsubcctv */
a2ea4aa9
RH
3562 gen_helper_tsubcctv(cpu_dst, cpu_env,
3563 cpu_src1, cpu_src2);
97ea2859 3564 gen_store_gpr(dc, rd, cpu_dst);
3b2d1e92 3565 dc->cc_op = CC_OP_TSUBTV;
0f8a249a 3566 break;
cf495bcf 3567 case 0x24: /* mulscc */
20132b96 3568 update_psr(dc);
6ae20372 3569 gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
97ea2859 3570 gen_store_gpr(dc, rd, cpu_dst);
d084469c
BS
3571 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3572 dc->cc_op = CC_OP_ADD;
cf495bcf 3573 break;
83469015 3574#ifndef TARGET_SPARC64
0f8a249a 3575 case 0x25: /* sll */
e35298cd 3576 if (IS_IMM) { /* immediate */
67526b20
BS
3577 simm = GET_FIELDs(insn, 20, 31);
3578 tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3579 } else { /* register */
de9e9d9f 3580 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3581 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3582 tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
3583 }
97ea2859 3584 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3585 break;
83469015 3586 case 0x26: /* srl */
e35298cd 3587 if (IS_IMM) { /* immediate */
67526b20
BS
3588 simm = GET_FIELDs(insn, 20, 31);
3589 tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3590 } else { /* register */
de9e9d9f 3591 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3592 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3593 tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
3594 }
97ea2859 3595 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3596 break;
83469015 3597 case 0x27: /* sra */
e35298cd 3598 if (IS_IMM) { /* immediate */
67526b20
BS
3599 simm = GET_FIELDs(insn, 20, 31);
3600 tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
e35298cd 3601 } else { /* register */
de9e9d9f 3602 cpu_tmp0 = get_temp_tl(dc);
e35298cd
BS
3603 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3604 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
3605 }
97ea2859 3606 gen_store_gpr(dc, rd, cpu_dst);
cf495bcf 3607 break;
83469015 3608#endif
cf495bcf
FB
3609 case 0x30:
3610 {
de9e9d9f 3611 cpu_tmp0 = get_temp_tl(dc);
cf495bcf 3612 switch(rd) {
3475187d 3613 case 0: /* wry */
5068cbd9
BS
3614 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3615 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
cf495bcf 3616 break;
65fe7b09
BS
3617#ifndef TARGET_SPARC64
3618 case 0x01 ... 0x0f: /* undefined in the
3619 SPARCv8 manual, nop
3620 on the microSPARC
3621 II */
3622 case 0x10 ... 0x1f: /* implementation-dependent
3623 in the SPARCv8
3624 manual, nop on the
3625 microSPARC II */
d1c36ba7
RH
3626 if ((rd == 0x13) && (dc->def->features &
3627 CPU_FEATURE_POWERDOWN)) {
3628 /* LEON3 power-down */
3629 gen_helper_power_down(cpu_env);
3630 }
65fe7b09
BS
3631 break;
3632#else
0f8a249a 3633 case 0x2: /* V9 wrccr */
7b04bd5c
RH
3634 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3635 gen_helper_wrccr(cpu_env, cpu_tmp0);
8393617c
BS
3636 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3637 dc->cc_op = CC_OP_FLAGS;
0f8a249a
BS
3638 break;
3639 case 0x3: /* V9 wrasi */
7b04bd5c
RH
3640 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3641 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
3642 tcg_gen_trunc_tl_i32(cpu_asi, cpu_tmp0);
0f8a249a
BS
3643 break;
3644 case 0x6: /* V9 wrfprs */
7b04bd5c
RH
3645 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3646 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
66442b07 3647 save_state(dc);
3299908c 3648 gen_op_next_insn();
57fec1fe 3649 tcg_gen_exit_tb(0);
3299908c 3650 dc->is_br = 1;
0f8a249a
BS
3651 break;
3652 case 0xf: /* V9 sir, nop if user */
3475187d 3653#if !defined(CONFIG_USER_ONLY)
6ad6135d 3654 if (supervisor(dc)) {
1a2fb1c0 3655 ; // XXX
6ad6135d 3656 }
3475187d 3657#endif
0f8a249a
BS
3658 break;
3659 case 0x13: /* Graphics Status */
5b12f1e8 3660 if (gen_trap_ifnofpu(dc)) {
725cb90b 3661 goto jmp_insn;
5b12f1e8 3662 }
255e1fcb 3663 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
0f8a249a 3664 break;
9d926598
BS
3665 case 0x14: /* Softint set */
3666 if (!supervisor(dc))
3667 goto illegal_insn;
aeff993c
RH
3668 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3669 gen_helper_set_softint(cpu_env, cpu_tmp0);
9d926598
BS
3670 break;
3671 case 0x15: /* Softint clear */
3672 if (!supervisor(dc))
3673 goto illegal_insn;
aeff993c
RH
3674 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3675 gen_helper_clear_softint(cpu_env, cpu_tmp0);
9d926598
BS
3676 break;
3677 case 0x16: /* Softint write */
3678 if (!supervisor(dc))
3679 goto illegal_insn;
aeff993c
RH
3680 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3681 gen_helper_write_softint(cpu_env, cpu_tmp0);
9d926598 3682 break;
0f8a249a 3683 case 0x17: /* Tick compare */
83469015 3684#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3685 if (!supervisor(dc))
3686 goto illegal_insn;
83469015 3687#endif
ccd4a219 3688 {
a7812ae4 3689 TCGv_ptr r_tickptr;
ccd4a219 3690
255e1fcb 3691 tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
6ae20372 3692 cpu_src2);
a7812ae4 3693 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3694 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3695 offsetof(CPUSPARCState, tick));
a7812ae4
PB
3696 gen_helper_tick_set_limit(r_tickptr,
3697 cpu_tick_cmpr);
3698 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3699 }
0f8a249a
BS
3700 break;
3701 case 0x18: /* System tick */
83469015 3702#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3703 if (!supervisor(dc))
3704 goto illegal_insn;
83469015 3705#endif
ccd4a219 3706 {
a7812ae4 3707 TCGv_ptr r_tickptr;
ccd4a219 3708
7b04bd5c 3709 tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
6ae20372 3710 cpu_src2);
a7812ae4 3711 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3712 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3713 offsetof(CPUSPARCState, stick));
a7812ae4 3714 gen_helper_tick_set_count(r_tickptr,
7b04bd5c 3715 cpu_tmp0);
a7812ae4 3716 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3717 }
0f8a249a
BS
3718 break;
3719 case 0x19: /* System tick compare */
83469015 3720#if !defined(CONFIG_USER_ONLY)
0f8a249a
BS
3721 if (!supervisor(dc))
3722 goto illegal_insn;
3475187d 3723#endif
ccd4a219 3724 {
a7812ae4 3725 TCGv_ptr r_tickptr;
ccd4a219 3726
255e1fcb 3727 tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
6ae20372 3728 cpu_src2);
a7812ae4 3729 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3730 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3731 offsetof(CPUSPARCState, stick));
a7812ae4
PB
3732 gen_helper_tick_set_limit(r_tickptr,
3733 cpu_stick_cmpr);
3734 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3735 }
0f8a249a 3736 break;
83469015 3737
0f8a249a 3738 case 0x10: /* Performance Control */
77f193da
BS
3739 case 0x11: /* Performance Instrumentation
3740 Counter */
0f8a249a 3741 case 0x12: /* Dispatch Control */
83469015 3742#endif
3475187d 3743 default:
cf495bcf
FB
3744 goto illegal_insn;
3745 }
3746 }
3747 break;
e8af50a3 3748#if !defined(CONFIG_USER_ONLY)
af7bf89b 3749 case 0x31: /* wrpsr, V9 saved, restored */
e8af50a3 3750 {
0f8a249a
BS
3751 if (!supervisor(dc))
3752 goto priv_insn;
3475187d 3753#ifdef TARGET_SPARC64
0f8a249a
BS
3754 switch (rd) {
3755 case 0:
063c3675 3756 gen_helper_saved(cpu_env);
0f8a249a
BS
3757 break;
3758 case 1:
063c3675 3759 gen_helper_restored(cpu_env);
0f8a249a 3760 break;
e9ebed4d
BS
3761 case 2: /* UA2005 allclean */
3762 case 3: /* UA2005 otherw */
3763 case 4: /* UA2005 normalw */
3764 case 5: /* UA2005 invalw */
3765 // XXX
0f8a249a 3766 default:
3475187d
FB
3767 goto illegal_insn;
3768 }
3769#else
de9e9d9f 3770 cpu_tmp0 = get_temp_tl(dc);
7b04bd5c
RH
3771 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3772 gen_helper_wrpsr(cpu_env, cpu_tmp0);
8393617c
BS
3773 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3774 dc->cc_op = CC_OP_FLAGS;
66442b07 3775 save_state(dc);
9e61bde5 3776 gen_op_next_insn();
57fec1fe 3777 tcg_gen_exit_tb(0);
0f8a249a 3778 dc->is_br = 1;
3475187d 3779#endif
e8af50a3
FB
3780 }
3781 break;
af7bf89b 3782 case 0x32: /* wrwim, V9 wrpr */
e8af50a3 3783 {
0f8a249a
BS
3784 if (!supervisor(dc))
3785 goto priv_insn;
de9e9d9f 3786 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 3787 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3475187d 3788#ifdef TARGET_SPARC64
0f8a249a
BS
3789 switch (rd) {
3790 case 0: // tpc
375ee38b 3791 {
a7812ae4 3792 TCGv_ptr r_tsptr;
375ee38b 3793
a7812ae4 3794 r_tsptr = tcg_temp_new_ptr();
8194f35a 3795 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3796 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 3797 offsetof(trap_state, tpc));
a7812ae4 3798 tcg_temp_free_ptr(r_tsptr);
375ee38b 3799 }
0f8a249a
BS
3800 break;
3801 case 1: // tnpc
375ee38b 3802 {
a7812ae4 3803 TCGv_ptr r_tsptr;
375ee38b 3804
a7812ae4 3805 r_tsptr = tcg_temp_new_ptr();
8194f35a 3806 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3807 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
375ee38b 3808 offsetof(trap_state, tnpc));
a7812ae4 3809 tcg_temp_free_ptr(r_tsptr);
375ee38b 3810 }
0f8a249a
BS
3811 break;
3812 case 2: // tstate
375ee38b 3813 {
a7812ae4 3814 TCGv_ptr r_tsptr;
375ee38b 3815
a7812ae4 3816 r_tsptr = tcg_temp_new_ptr();
8194f35a 3817 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
ece43b8d 3818 tcg_gen_st_tl(cpu_tmp0, r_tsptr,
77f193da
BS
3819 offsetof(trap_state,
3820 tstate));
a7812ae4 3821 tcg_temp_free_ptr(r_tsptr);
375ee38b 3822 }
0f8a249a
BS
3823 break;
3824 case 3: // tt
375ee38b 3825 {
a7812ae4 3826 TCGv_ptr r_tsptr;
375ee38b 3827
a7812ae4 3828 r_tsptr = tcg_temp_new_ptr();
8194f35a 3829 gen_load_trap_state_at_tl(r_tsptr, cpu_env);
7b9e066b
RH
3830 tcg_gen_st32_tl(cpu_tmp0, r_tsptr,
3831 offsetof(trap_state, tt));
a7812ae4 3832 tcg_temp_free_ptr(r_tsptr);
375ee38b 3833 }
0f8a249a
BS
3834 break;
3835 case 4: // tick
ccd4a219 3836 {
a7812ae4 3837 TCGv_ptr r_tickptr;
ccd4a219 3838
a7812ae4 3839 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3840 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3841 offsetof(CPUSPARCState, tick));
a7812ae4
PB
3842 gen_helper_tick_set_count(r_tickptr,
3843 cpu_tmp0);
3844 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3845 }
0f8a249a
BS
3846 break;
3847 case 5: // tba
255e1fcb 3848 tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
0f8a249a
BS
3849 break;
3850 case 6: // pstate
6234ac09
RH
3851 save_state(dc);
3852 gen_helper_wrpstate(cpu_env, cpu_tmp0);
3853 dc->npc = DYNAMIC_PC;
0f8a249a
BS
3854 break;
3855 case 7: // tl
6234ac09 3856 save_state(dc);
7b9e066b 3857 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
6234ac09
RH
3858 offsetof(CPUSPARCState, tl));
3859 dc->npc = DYNAMIC_PC;
0f8a249a
BS
3860 break;
3861 case 8: // pil
063c3675 3862 gen_helper_wrpil(cpu_env, cpu_tmp0);
0f8a249a
BS
3863 break;
3864 case 9: // cwp
063c3675 3865 gen_helper_wrcwp(cpu_env, cpu_tmp0);
0f8a249a
BS
3866 break;
3867 case 10: // cansave
7b9e066b
RH
3868 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3869 offsetof(CPUSPARCState,
3870 cansave));
0f8a249a
BS
3871 break;
3872 case 11: // canrestore
7b9e066b
RH
3873 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3874 offsetof(CPUSPARCState,
3875 canrestore));
0f8a249a
BS
3876 break;
3877 case 12: // cleanwin
7b9e066b
RH
3878 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3879 offsetof(CPUSPARCState,
3880 cleanwin));
0f8a249a
BS
3881 break;
3882 case 13: // otherwin
7b9e066b
RH
3883 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3884 offsetof(CPUSPARCState,
3885 otherwin));
0f8a249a
BS
3886 break;
3887 case 14: // wstate
7b9e066b
RH
3888 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3889 offsetof(CPUSPARCState,
3890 wstate));
0f8a249a 3891 break;
e9ebed4d 3892 case 16: // UA2005 gl
fb79ceb9 3893 CHECK_IU_FEATURE(dc, GL);
7b9e066b
RH
3894 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
3895 offsetof(CPUSPARCState, gl));
e9ebed4d
BS
3896 break;
3897 case 26: // UA2005 strand status
fb79ceb9 3898 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3899 if (!hypervisor(dc))
3900 goto priv_insn;
527067d8 3901 tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
e9ebed4d 3902 break;
0f8a249a
BS
3903 default:
3904 goto illegal_insn;
3905 }
3475187d 3906#else
7b9e066b
RH
3907 tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0);
3908 if (dc->def->nwindows != 32) {
3909 tcg_gen_andi_tl(cpu_wim, cpu_wim,
c93e7817 3910 (1 << dc->def->nwindows) - 1);
7b9e066b 3911 }
3475187d 3912#endif
e8af50a3
FB
3913 }
3914 break;
e9ebed4d 3915 case 0x33: /* wrtbr, UA2005 wrhpr */
e8af50a3 3916 {
e9ebed4d 3917#ifndef TARGET_SPARC64
0f8a249a
BS
3918 if (!supervisor(dc))
3919 goto priv_insn;
255e1fcb 3920 tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
e9ebed4d 3921#else
fb79ceb9 3922 CHECK_IU_FEATURE(dc, HYPV);
e9ebed4d
BS
3923 if (!hypervisor(dc))
3924 goto priv_insn;
de9e9d9f 3925 cpu_tmp0 = get_temp_tl(dc);
ece43b8d 3926 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
e9ebed4d
BS
3927 switch (rd) {
3928 case 0: // hpstate
3929 // XXX gen_op_wrhpstate();
66442b07 3930 save_state(dc);
e9ebed4d 3931 gen_op_next_insn();
57fec1fe 3932 tcg_gen_exit_tb(0);
e9ebed4d
BS
3933 dc->is_br = 1;
3934 break;
3935 case 1: // htstate
3936 // XXX gen_op_wrhtstate();
3937 break;
3938 case 3: // hintp
255e1fcb 3939 tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
e9ebed4d
BS
3940 break;
3941 case 5: // htba
255e1fcb 3942 tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
e9ebed4d
BS
3943 break;
3944 case 31: // hstick_cmpr
ccd4a219 3945 {
a7812ae4 3946 TCGv_ptr r_tickptr;
ccd4a219 3947
255e1fcb 3948 tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
a7812ae4 3949 r_tickptr = tcg_temp_new_ptr();
ccd4a219 3950 tcg_gen_ld_ptr(r_tickptr, cpu_env,
c5f9864e 3951 offsetof(CPUSPARCState, hstick));
a7812ae4
PB
3952 gen_helper_tick_set_limit(r_tickptr,
3953 cpu_hstick_cmpr);
3954 tcg_temp_free_ptr(r_tickptr);
ccd4a219 3955 }
e9ebed4d
BS
3956 break;
3957 case 6: // hver readonly
3958 default:
3959 goto illegal_insn;
3960 }
3961#endif
e8af50a3
FB
3962 }
3963 break;
3964#endif
3475187d 3965#ifdef TARGET_SPARC64
0f8a249a
BS
3966 case 0x2c: /* V9 movcc */
3967 {
3968 int cc = GET_FIELD_SP(insn, 11, 12);
3969 int cond = GET_FIELD_SP(insn, 14, 17);
f52879b4 3970 DisasCompare cmp;
97ea2859 3971 TCGv dst;
00f219bf 3972
0f8a249a 3973 if (insn & (1 << 18)) {
f52879b4
RH
3974 if (cc == 0) {
3975 gen_compare(&cmp, 0, cond, dc);
3976 } else if (cc == 2) {
3977 gen_compare(&cmp, 1, cond, dc);
3978 } else {
0f8a249a 3979 goto illegal_insn;
f52879b4 3980 }
0f8a249a 3981 } else {
f52879b4 3982 gen_fcompare(&cmp, cc, cond);
0f8a249a 3983 }
00f219bf 3984
f52879b4
RH
3985 /* The get_src2 above loaded the normal 13-bit
3986 immediate field, not the 11-bit field we have
3987 in movcc. But it did handle the reg case. */
3988 if (IS_IMM) {
67526b20 3989 simm = GET_FIELD_SPs(insn, 0, 10);
f52879b4 3990 tcg_gen_movi_tl(cpu_src2, simm);
00f219bf 3991 }
f52879b4 3992
97ea2859
RH
3993 dst = gen_load_gpr(dc, rd);
3994 tcg_gen_movcond_tl(cmp.cond, dst,
f52879b4 3995 cmp.c1, cmp.c2,
97ea2859 3996 cpu_src2, dst);
f52879b4 3997 free_compare(&cmp);
97ea2859 3998 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
3999 break;
4000 }
4001 case 0x2d: /* V9 sdivx */
c28ae41e 4002 gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
97ea2859 4003 gen_store_gpr(dc, rd, cpu_dst);
0f8a249a
BS
4004 break;
4005 case 0x2e: /* V9 popc */
97ea2859
RH
4006 gen_helper_popc(cpu_dst, cpu_src2);
4007 gen_store_gpr(dc, rd, cpu_dst);
4008 break;
0f8a249a
BS
4009 case 0x2f: /* V9 movr */
4010 {
4011 int cond = GET_FIELD_SP(insn, 10, 12);
c33f80f5 4012 DisasCompare cmp;
97ea2859 4013 TCGv dst;
00f219bf 4014
c33f80f5 4015 gen_compare_reg(&cmp, cond, cpu_src1);
2ea815ca 4016
c33f80f5
RH
4017 /* The get_src2 above loaded the normal 13-bit
4018 immediate field, not the 10-bit field we have
4019 in movr. But it did handle the reg case. */
4020 if (IS_IMM) {
67526b20 4021 simm = GET_FIELD_SPs(insn, 0, 9);
c33f80f5 4022 tcg_gen_movi_tl(cpu_src2, simm);
0f8a249a 4023 }
c33f80f5 4024
97ea2859
RH
4025 dst = gen_load_gpr(dc, rd);
4026 tcg_gen_movcond_tl(cmp.cond, dst,
c33f80f5 4027 cmp.c1, cmp.c2,
97ea2859 4028 cpu_src2, dst);
c33f80f5 4029 free_compare(&cmp);
97ea2859 4030 gen_store_gpr(dc, rd, dst);
0f8a249a
BS
4031 break;
4032 }
4033#endif
4034 default:
4035 goto illegal_insn;
4036 }
4037 }
3299908c
BS
4038 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4039#ifdef TARGET_SPARC64
4040 int opf = GET_FIELD_SP(insn, 5, 13);
4041 rs1 = GET_FIELD(insn, 13, 17);
4042 rs2 = GET_FIELD(insn, 27, 31);
5b12f1e8 4043 if (gen_trap_ifnofpu(dc)) {
e9ebed4d 4044 goto jmp_insn;
5b12f1e8 4045 }
3299908c
BS
4046
4047 switch (opf) {
e9ebed4d 4048 case 0x000: /* VIS I edge8cc */
6c073553 4049 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4050 cpu_src1 = gen_load_gpr(dc, rs1);
4051 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4052 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
97ea2859 4053 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4054 break;
e9ebed4d 4055 case 0x001: /* VIS II edge8n */
6c073553 4056 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4057 cpu_src1 = gen_load_gpr(dc, rs1);
4058 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4059 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
97ea2859 4060 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4061 break;
e9ebed4d 4062 case 0x002: /* VIS I edge8lcc */
6c073553 4063 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4064 cpu_src1 = gen_load_gpr(dc, rs1);
4065 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4066 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
97ea2859 4067 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4068 break;
e9ebed4d 4069 case 0x003: /* VIS II edge8ln */
6c073553 4070 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4071 cpu_src1 = gen_load_gpr(dc, rs1);
4072 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4073 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
97ea2859 4074 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4075 break;
e9ebed4d 4076 case 0x004: /* VIS I edge16cc */
6c073553 4077 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4078 cpu_src1 = gen_load_gpr(dc, rs1);
4079 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4080 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
97ea2859 4081 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4082 break;
e9ebed4d 4083 case 0x005: /* VIS II edge16n */
6c073553 4084 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4085 cpu_src1 = gen_load_gpr(dc, rs1);
4086 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4087 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
97ea2859 4088 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4089 break;
e9ebed4d 4090 case 0x006: /* VIS I edge16lcc */
6c073553 4091 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4092 cpu_src1 = gen_load_gpr(dc, rs1);
4093 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4094 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
97ea2859 4095 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4096 break;
e9ebed4d 4097 case 0x007: /* VIS II edge16ln */
6c073553 4098 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4099 cpu_src1 = gen_load_gpr(dc, rs1);
4100 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4101 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
97ea2859 4102 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4103 break;
e9ebed4d 4104 case 0x008: /* VIS I edge32cc */
6c073553 4105 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4106 cpu_src1 = gen_load_gpr(dc, rs1);
4107 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4108 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
97ea2859 4109 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4110 break;
e9ebed4d 4111 case 0x009: /* VIS II edge32n */
6c073553 4112 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4113 cpu_src1 = gen_load_gpr(dc, rs1);
4114 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4115 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
97ea2859 4116 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4117 break;
e9ebed4d 4118 case 0x00a: /* VIS I edge32lcc */
6c073553 4119 CHECK_FPU_FEATURE(dc, VIS1);
97ea2859
RH
4120 cpu_src1 = gen_load_gpr(dc, rs1);
4121 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4122 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
97ea2859 4123 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4124 break;
e9ebed4d 4125 case 0x00b: /* VIS II edge32ln */
6c073553 4126 CHECK_FPU_FEATURE(dc, VIS2);
97ea2859
RH
4127 cpu_src1 = gen_load_gpr(dc, rs1);
4128 cpu_src2 = gen_load_gpr(dc, rs2);
6c073553 4129 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
97ea2859 4130 gen_store_gpr(dc, rd, cpu_dst);
6c073553 4131 break;
e9ebed4d 4132 case 0x010: /* VIS I array8 */
64a88d5d 4133 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4134 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4135 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4136 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
97ea2859 4137 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4138 break;
4139 case 0x012: /* VIS I array16 */
64a88d5d 4140 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4141 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4142 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4143 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4144 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
97ea2859 4145 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4146 break;
4147 case 0x014: /* VIS I array32 */
64a88d5d 4148 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4149 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4150 cpu_src2 = gen_load_gpr(dc, rs2);
f027c3b1 4151 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
6ae20372 4152 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
97ea2859 4153 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d 4154 break;
3299908c 4155 case 0x018: /* VIS I alignaddr */
64a88d5d 4156 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4157 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4158 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4159 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
97ea2859 4160 gen_store_gpr(dc, rd, cpu_dst);
3299908c
BS
4161 break;
4162 case 0x01a: /* VIS I alignaddrl */
add545ab 4163 CHECK_FPU_FEATURE(dc, VIS1);
9d1d4e34 4164 cpu_src1 = gen_load_gpr(dc, rs1);
97ea2859 4165 cpu_src2 = gen_load_gpr(dc, rs2);
add545ab 4166 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
97ea2859 4167 gen_store_gpr(dc, rd, cpu_dst);
add545ab
RH
4168 break;
4169 case 0x019: /* VIS II bmask */
793a137a 4170 CHECK_FPU_FEATURE(dc, VIS2);
9d1d4e34
RH
4171 cpu_src1 = gen_load_gpr(dc, rs1);
4172 cpu_src2 = gen_load_gpr(dc, rs2);
793a137a
RH
4173 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4174 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
97ea2859 4175 gen_store_gpr(dc, rd, cpu_dst);
793a137a 4176 break;
e9ebed4d 4177 case 0x020: /* VIS I fcmple16 */
64a88d5d 4178 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4179 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4180 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4181 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4182 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4183 break;
4184 case 0x022: /* VIS I fcmpne16 */
64a88d5d 4185 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4186 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4187 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4188 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4189 gen_store_gpr(dc, rd, cpu_dst);
3299908c 4190 break;
e9ebed4d 4191 case 0x024: /* VIS I fcmple32 */
64a88d5d 4192 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4193 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4194 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4195 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4196 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4197 break;
4198 case 0x026: /* VIS I fcmpne32 */
64a88d5d 4199 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4200 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4201 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4202 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4203 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4204 break;
4205 case 0x028: /* VIS I fcmpgt16 */
64a88d5d 4206 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4207 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4208 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4209 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4210 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4211 break;
4212 case 0x02a: /* VIS I fcmpeq16 */
64a88d5d 4213 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4214 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4215 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4216 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4217 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4218 break;
4219 case 0x02c: /* VIS I fcmpgt32 */
64a88d5d 4220 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4221 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4222 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4223 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4224 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4225 break;
4226 case 0x02e: /* VIS I fcmpeq32 */
64a88d5d 4227 CHECK_FPU_FEATURE(dc, VIS1);
03fb8cfc
RH
4228 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4229 cpu_src2_64 = gen_load_fpr_D(dc, rs2);
f027c3b1 4230 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
97ea2859 4231 gen_store_gpr(dc, rd, cpu_dst);
e9ebed4d
BS
4232 break;
4233 case 0x031: /* VIS I fmul8x16 */
64a88d5d 4234 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4235 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
e9ebed4d
BS
4236 break;
4237 case 0x033: /* VIS I fmul8x16au */
64a88d5d 4238 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4239 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
e9ebed4d
BS
4240 break;
4241 case 0x035: /* VIS I fmul8x16al */
64a88d5d 4242 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4243 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
e9ebed4d
BS
4244 break;
4245 case 0x036: /* VIS I fmul8sux16 */
64a88d5d 4246 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4247 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
e9ebed4d
BS
4248 break;
4249 case 0x037: /* VIS I fmul8ulx16 */
64a88d5d 4250 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4251 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
e9ebed4d
BS
4252 break;
4253 case 0x038: /* VIS I fmuld8sux16 */
64a88d5d 4254 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4255 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
e9ebed4d
BS
4256 break;
4257 case 0x039: /* VIS I fmuld8ulx16 */
64a88d5d 4258 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4259 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
e9ebed4d
BS
4260 break;
4261 case 0x03a: /* VIS I fpack32 */
2dedf314
RH
4262 CHECK_FPU_FEATURE(dc, VIS1);
4263 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4264 break;
e9ebed4d 4265 case 0x03b: /* VIS I fpack16 */
2dedf314
RH
4266 CHECK_FPU_FEATURE(dc, VIS1);
4267 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4268 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4269 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4270 gen_store_fpr_F(dc, rd, cpu_dst_32);
4271 break;
e9ebed4d 4272 case 0x03d: /* VIS I fpackfix */
2dedf314
RH
4273 CHECK_FPU_FEATURE(dc, VIS1);
4274 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
ba5f5179 4275 cpu_dst_32 = gen_dest_fpr_F(dc);
2dedf314
RH
4276 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4277 gen_store_fpr_F(dc, rd, cpu_dst_32);
4278 break;
f888300b
RH
4279 case 0x03e: /* VIS I pdist */
4280 CHECK_FPU_FEATURE(dc, VIS1);
4281 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4282 break;
3299908c 4283 case 0x048: /* VIS I faligndata */
64a88d5d 4284 CHECK_FPU_FEATURE(dc, VIS1);
50c796f9 4285 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
3299908c 4286 break;
e9ebed4d 4287 case 0x04b: /* VIS I fpmerge */
64a88d5d 4288 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4289 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
e9ebed4d
BS
4290 break;
4291 case 0x04c: /* VIS II bshuffle */
793a137a
RH
4292 CHECK_FPU_FEATURE(dc, VIS2);
4293 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4294 break;
e9ebed4d 4295 case 0x04d: /* VIS I fexpand */
64a88d5d 4296 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4297 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
e9ebed4d
BS
4298 break;
4299 case 0x050: /* VIS I fpadd16 */
64a88d5d 4300 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4301 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
e9ebed4d
BS
4302 break;
4303 case 0x051: /* VIS I fpadd16s */
64a88d5d 4304 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4305 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
e9ebed4d
BS
4306 break;
4307 case 0x052: /* VIS I fpadd32 */
64a88d5d 4308 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4309 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
e9ebed4d
BS
4310 break;
4311 case 0x053: /* VIS I fpadd32s */
64a88d5d 4312 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4313 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
e9ebed4d
BS
4314 break;
4315 case 0x054: /* VIS I fpsub16 */
64a88d5d 4316 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4317 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
e9ebed4d
BS
4318 break;
4319 case 0x055: /* VIS I fpsub16s */
64a88d5d 4320 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4321 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
e9ebed4d
BS
4322 break;
4323 case 0x056: /* VIS I fpsub32 */
64a88d5d 4324 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4325 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
e9ebed4d
BS
4326 break;
4327 case 0x057: /* VIS I fpsub32s */
64a88d5d 4328 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4329 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
e9ebed4d 4330 break;
3299908c 4331 case 0x060: /* VIS I fzero */
64a88d5d 4332 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4333 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4334 tcg_gen_movi_i64(cpu_dst_64, 0);
4335 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4336 break;
4337 case 0x061: /* VIS I fzeros */
64a88d5d 4338 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4339 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4340 tcg_gen_movi_i32(cpu_dst_32, 0);
4341 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4342 break;
e9ebed4d 4343 case 0x062: /* VIS I fnor */
64a88d5d 4344 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4345 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
e9ebed4d
BS
4346 break;
4347 case 0x063: /* VIS I fnors */
64a88d5d 4348 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4349 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
e9ebed4d
BS
4350 break;
4351 case 0x064: /* VIS I fandnot2 */
64a88d5d 4352 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4353 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
e9ebed4d
BS
4354 break;
4355 case 0x065: /* VIS I fandnot2s */
64a88d5d 4356 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4357 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
e9ebed4d
BS
4358 break;
4359 case 0x066: /* VIS I fnot2 */
64a88d5d 4360 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4361 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
e9ebed4d
BS
4362 break;
4363 case 0x067: /* VIS I fnot2s */
64a88d5d 4364 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4365 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
e9ebed4d
BS
4366 break;
4367 case 0x068: /* VIS I fandnot1 */
64a88d5d 4368 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4369 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
e9ebed4d
BS
4370 break;
4371 case 0x069: /* VIS I fandnot1s */
64a88d5d 4372 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4373 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
e9ebed4d
BS
4374 break;
4375 case 0x06a: /* VIS I fnot1 */
64a88d5d 4376 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4377 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
e9ebed4d
BS
4378 break;
4379 case 0x06b: /* VIS I fnot1s */
64a88d5d 4380 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4381 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
e9ebed4d
BS
4382 break;
4383 case 0x06c: /* VIS I fxor */
64a88d5d 4384 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4385 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
e9ebed4d
BS
4386 break;
4387 case 0x06d: /* VIS I fxors */
64a88d5d 4388 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4389 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
e9ebed4d
BS
4390 break;
4391 case 0x06e: /* VIS I fnand */
64a88d5d 4392 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4393 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
e9ebed4d
BS
4394 break;
4395 case 0x06f: /* VIS I fnands */
64a88d5d 4396 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4397 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
e9ebed4d
BS
4398 break;
4399 case 0x070: /* VIS I fand */
64a88d5d 4400 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4401 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
e9ebed4d
BS
4402 break;
4403 case 0x071: /* VIS I fands */
64a88d5d 4404 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4405 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
e9ebed4d
BS
4406 break;
4407 case 0x072: /* VIS I fxnor */
64a88d5d 4408 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4409 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
e9ebed4d
BS
4410 break;
4411 case 0x073: /* VIS I fxnors */
64a88d5d 4412 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4413 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
e9ebed4d 4414 break;
3299908c 4415 case 0x074: /* VIS I fsrc1 */
64a88d5d 4416 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4417 cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4418 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4419 break;
4420 case 0x075: /* VIS I fsrc1s */
64a88d5d 4421 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4422 cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4423 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4424 break;
e9ebed4d 4425 case 0x076: /* VIS I fornot2 */
64a88d5d 4426 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4427 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
e9ebed4d
BS
4428 break;
4429 case 0x077: /* VIS I fornot2s */
64a88d5d 4430 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4431 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
e9ebed4d 4432 break;
3299908c 4433 case 0x078: /* VIS I fsrc2 */
64a88d5d 4434 CHECK_FPU_FEATURE(dc, VIS1);
96eda024
RH
4435 cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4436 gen_store_fpr_D(dc, rd, cpu_src1_64);
3299908c
BS
4437 break;
4438 case 0x079: /* VIS I fsrc2s */
64a88d5d 4439 CHECK_FPU_FEATURE(dc, VIS1);
208ae657
RH
4440 cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4441 gen_store_fpr_F(dc, rd, cpu_src1_32);
3299908c 4442 break;
e9ebed4d 4443 case 0x07a: /* VIS I fornot1 */
64a88d5d 4444 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4445 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
e9ebed4d
BS
4446 break;
4447 case 0x07b: /* VIS I fornot1s */
64a88d5d 4448 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4449 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
e9ebed4d
BS
4450 break;
4451 case 0x07c: /* VIS I for */
64a88d5d 4452 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4453 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
e9ebed4d
BS
4454 break;
4455 case 0x07d: /* VIS I fors */
64a88d5d 4456 CHECK_FPU_FEATURE(dc, VIS1);
61f17f6e 4457 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
e9ebed4d 4458 break;
3299908c 4459 case 0x07e: /* VIS I fone */
64a88d5d 4460 CHECK_FPU_FEATURE(dc, VIS1);
3886b8a3 4461 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
96eda024
RH
4462 tcg_gen_movi_i64(cpu_dst_64, -1);
4463 gen_store_fpr_D(dc, rd, cpu_dst_64);
3299908c
BS
4464 break;
4465 case 0x07f: /* VIS I fones */
64a88d5d 4466 CHECK_FPU_FEATURE(dc, VIS1);
ba5f5179 4467 cpu_dst_32 = gen_dest_fpr_F(dc);
208ae657
RH
4468 tcg_gen_movi_i32(cpu_dst_32, -1);
4469 gen_store_fpr_F(dc, rd, cpu_dst_32);
3299908c 4470 break;
e9ebed4d
BS
4471 case 0x080: /* VIS I shutdown */
4472 case 0x081: /* VIS II siam */
4473 // XXX
4474 goto illegal_insn;
3299908c
BS
4475 default:
4476 goto illegal_insn;
4477 }
4478#else
0f8a249a 4479 goto ncp_insn;
3299908c
BS
4480#endif
4481 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
fcc72045 4482#ifdef TARGET_SPARC64
0f8a249a 4483 goto illegal_insn;
fcc72045 4484#else
0f8a249a 4485 goto ncp_insn;
fcc72045 4486#endif
3475187d 4487#ifdef TARGET_SPARC64
0f8a249a 4488 } else if (xop == 0x39) { /* V9 return */
a7812ae4 4489 TCGv_i32 r_const;
2ea815ca 4490
66442b07 4491 save_state(dc);
9d1d4e34 4492 cpu_src1 = get_src1(dc, insn);
de9e9d9f 4493 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 4494 if (IS_IMM) { /* immediate */
67526b20 4495 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 4496 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 4497 } else { /* register */
3475187d 4498 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4499 if (rs2) {
97ea2859 4500 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 4501 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 4502 } else {
7b04bd5c 4503 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 4504 }
3475187d 4505 }
063c3675 4506 gen_helper_restore(cpu_env);
13a6dd00 4507 gen_mov_pc_npc(dc);
2ea815ca 4508 r_const = tcg_const_i32(3);
7b04bd5c 4509 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4510 tcg_temp_free_i32(r_const);
7b04bd5c 4511 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
4512 dc->npc = DYNAMIC_PC;
4513 goto jmp_insn;
3475187d 4514#endif
0f8a249a 4515 } else {
9d1d4e34 4516 cpu_src1 = get_src1(dc, insn);
de9e9d9f 4517 cpu_tmp0 = get_temp_tl(dc);
0f8a249a 4518 if (IS_IMM) { /* immediate */
67526b20 4519 simm = GET_FIELDs(insn, 19, 31);
7b04bd5c 4520 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
0f8a249a 4521 } else { /* register */
e80cfcfc 4522 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4523 if (rs2) {
97ea2859 4524 cpu_src2 = gen_load_gpr(dc, rs2);
7b04bd5c 4525 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
97ea2859 4526 } else {
7b04bd5c 4527 tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
97ea2859 4528 }
cf495bcf 4529 }
0f8a249a
BS
4530 switch (xop) {
4531 case 0x38: /* jmpl */
4532 {
97ea2859 4533 TCGv t;
a7812ae4 4534 TCGv_i32 r_const;
2ea815ca 4535
97ea2859
RH
4536 t = gen_dest_gpr(dc, rd);
4537 tcg_gen_movi_tl(t, dc->pc);
4538 gen_store_gpr(dc, rd, t);
13a6dd00 4539 gen_mov_pc_npc(dc);
2ea815ca 4540 r_const = tcg_const_i32(3);
7b04bd5c 4541 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4542 tcg_temp_free_i32(r_const);
7b04bd5c
RH
4543 gen_address_mask(dc, cpu_tmp0);
4544 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a
BS
4545 dc->npc = DYNAMIC_PC;
4546 }
4547 goto jmp_insn;
3475187d 4548#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
0f8a249a
BS
4549 case 0x39: /* rett, V9 return */
4550 {
a7812ae4 4551 TCGv_i32 r_const;
2ea815ca 4552
0f8a249a
BS
4553 if (!supervisor(dc))
4554 goto priv_insn;
13a6dd00 4555 gen_mov_pc_npc(dc);
2ea815ca 4556 r_const = tcg_const_i32(3);
7b04bd5c 4557 gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
a7812ae4 4558 tcg_temp_free_i32(r_const);
7b04bd5c 4559 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
0f8a249a 4560 dc->npc = DYNAMIC_PC;
063c3675 4561 gen_helper_rett(cpu_env);
0f8a249a
BS
4562 }
4563 goto jmp_insn;
4564#endif
4565 case 0x3b: /* flush */
5578ceab 4566 if (!((dc)->def->features & CPU_FEATURE_FLUSH))
64a88d5d 4567 goto unimp_flush;
dcfd14b3 4568 /* nop */
0f8a249a
BS
4569 break;
4570 case 0x3c: /* save */
66442b07 4571 save_state(dc);
063c3675 4572 gen_helper_save(cpu_env);
7b04bd5c 4573 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a
BS
4574 break;
4575 case 0x3d: /* restore */
66442b07 4576 save_state(dc);
063c3675 4577 gen_helper_restore(cpu_env);
7b04bd5c 4578 gen_store_gpr(dc, rd, cpu_tmp0);
0f8a249a 4579 break;
3475187d 4580#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
0f8a249a
BS
4581 case 0x3e: /* V9 done/retry */
4582 {
4583 switch (rd) {
4584 case 0:
4585 if (!supervisor(dc))
4586 goto priv_insn;
4587 dc->npc = DYNAMIC_PC;
4588 dc->pc = DYNAMIC_PC;
063c3675 4589 gen_helper_done(cpu_env);
0f8a249a
BS
4590 goto jmp_insn;
4591 case 1:
4592 if (!supervisor(dc))
4593 goto priv_insn;
4594 dc->npc = DYNAMIC_PC;
4595 dc->pc = DYNAMIC_PC;
063c3675 4596 gen_helper_retry(cpu_env);
0f8a249a
BS
4597 goto jmp_insn;
4598 default:
4599 goto illegal_insn;
4600 }
4601 }
4602 break;
4603#endif
4604 default:
4605 goto illegal_insn;
4606 }
cf495bcf 4607 }
0f8a249a
BS
4608 break;
4609 }
4610 break;
4611 case 3: /* load/store instructions */
4612 {
4613 unsigned int xop = GET_FIELD(insn, 7, 12);
5e6ed439
RH
4614 /* ??? gen_address_mask prevents us from using a source
4615 register directly. Always generate a temporary. */
4616 TCGv cpu_addr = get_temp_tl(dc);
9322a4bf 4617
5e6ed439
RH
4618 tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
4619 if (xop == 0x3c || xop == 0x3e) {
4620 /* V9 casa/casxa : no offset */
71817e48 4621 } else if (IS_IMM) { /* immediate */
67526b20 4622 simm = GET_FIELDs(insn, 19, 31);
5e6ed439
RH
4623 if (simm != 0) {
4624 tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
4625 }
0f8a249a
BS
4626 } else { /* register */
4627 rs2 = GET_FIELD(insn, 27, 31);
0f8a249a 4628 if (rs2 != 0) {
5e6ed439 4629 tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
97ea2859 4630 }
0f8a249a 4631 }
2f2ecb83
BS
4632 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
4633 (xop > 0x17 && xop <= 0x1d ) ||
4634 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
81634eea
RH
4635 TCGv cpu_val = gen_dest_gpr(dc, rd);
4636
0f8a249a 4637 switch (xop) {
b89e94af 4638 case 0x0: /* ld, V9 lduw, load unsigned word */
2cade6a3 4639 gen_address_mask(dc, cpu_addr);
6ae20372 4640 tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4641 break;
b89e94af 4642 case 0x1: /* ldub, load unsigned byte */
2cade6a3 4643 gen_address_mask(dc, cpu_addr);
6ae20372 4644 tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4645 break;
b89e94af 4646 case 0x2: /* lduh, load unsigned halfword */
2cade6a3 4647 gen_address_mask(dc, cpu_addr);
6ae20372 4648 tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4649 break;
b89e94af 4650 case 0x3: /* ldd, load double word */
0f8a249a 4651 if (rd & 1)
d4218d99 4652 goto illegal_insn;
1a2fb1c0 4653 else {
a7812ae4 4654 TCGv_i32 r_const;
abcc7191 4655 TCGv_i64 t64;
2ea815ca 4656
66442b07 4657 save_state(dc);
2ea815ca 4658 r_const = tcg_const_i32(7);
fe8d8f0f
BS
4659 /* XXX remove alignment check */
4660 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 4661 tcg_temp_free_i32(r_const);
2cade6a3 4662 gen_address_mask(dc, cpu_addr);
abcc7191
RH
4663 t64 = tcg_temp_new_i64();
4664 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
de9e9d9f
RH
4665 tcg_gen_trunc_i64_tl(cpu_val, t64);
4666 tcg_gen_ext32u_tl(cpu_val, cpu_val);
4667 gen_store_gpr(dc, rd + 1, cpu_val);
abcc7191
RH
4668 tcg_gen_shri_i64(t64, t64, 32);
4669 tcg_gen_trunc_i64_tl(cpu_val, t64);
4670 tcg_temp_free_i64(t64);
de9e9d9f 4671 tcg_gen_ext32u_tl(cpu_val, cpu_val);
1a2fb1c0 4672 }
0f8a249a 4673 break;
b89e94af 4674 case 0x9: /* ldsb, load signed byte */
2cade6a3 4675 gen_address_mask(dc, cpu_addr);
6ae20372 4676 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4677 break;
b89e94af 4678 case 0xa: /* ldsh, load signed halfword */
2cade6a3 4679 gen_address_mask(dc, cpu_addr);
6ae20372 4680 tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4681 break;
4682 case 0xd: /* ldstub -- XXX: should be atomically */
2ea815ca
BS
4683 {
4684 TCGv r_const;
4685
2cade6a3 4686 gen_address_mask(dc, cpu_addr);
2ea815ca
BS
4687 tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
4688 r_const = tcg_const_tl(0xff);
4689 tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
4690 tcg_temp_free(r_const);
4691 }
0f8a249a 4692 break;
de9e9d9f
RH
4693 case 0x0f:
4694 /* swap, swap register with memory. Also atomically */
4695 {
4696 TCGv t0 = get_temp_tl(dc);
4697 CHECK_IU_FEATURE(dc, SWAP);
4698 cpu_src1 = gen_load_gpr(dc, rd);
4699 gen_address_mask(dc, cpu_addr);
4700 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
4701 tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx);
4702 tcg_gen_mov_tl(cpu_val, t0);
4703 }
0f8a249a 4704 break;
3475187d 4705#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 4706 case 0x10: /* lda, V9 lduwa, load word alternate */
3475187d 4707#ifndef TARGET_SPARC64
0f8a249a
BS
4708 if (IS_IMM)
4709 goto illegal_insn;
4710 if (!supervisor(dc))
4711 goto priv_insn;
6ea4a6c8 4712#endif
66442b07 4713 save_state(dc);
6ae20372 4714 gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
0f8a249a 4715 break;
b89e94af 4716 case 0x11: /* lduba, load unsigned byte alternate */
3475187d 4717#ifndef TARGET_SPARC64
0f8a249a
BS
4718 if (IS_IMM)
4719 goto illegal_insn;
4720 if (!supervisor(dc))
4721 goto priv_insn;
4722#endif
66442b07 4723 save_state(dc);
6ae20372 4724 gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
0f8a249a 4725 break;
b89e94af 4726 case 0x12: /* lduha, load unsigned halfword alternate */
3475187d 4727#ifndef TARGET_SPARC64
0f8a249a
BS
4728 if (IS_IMM)
4729 goto illegal_insn;
4730 if (!supervisor(dc))
4731 goto priv_insn;
3475187d 4732#endif
66442b07 4733 save_state(dc);
6ae20372 4734 gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
0f8a249a 4735 break;
b89e94af 4736 case 0x13: /* ldda, load double word alternate */
3475187d 4737#ifndef TARGET_SPARC64
0f8a249a
BS
4738 if (IS_IMM)
4739 goto illegal_insn;
4740 if (!supervisor(dc))
4741 goto priv_insn;
3475187d 4742#endif
0f8a249a 4743 if (rd & 1)
d4218d99 4744 goto illegal_insn;
66442b07 4745 save_state(dc);
c7785e16 4746 gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
db166940 4747 goto skip_move;
b89e94af 4748 case 0x19: /* ldsba, load signed byte alternate */
3475187d 4749#ifndef TARGET_SPARC64
0f8a249a
BS
4750 if (IS_IMM)
4751 goto illegal_insn;
4752 if (!supervisor(dc))
4753 goto priv_insn;
4754#endif
66442b07 4755 save_state(dc);
6ae20372 4756 gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
0f8a249a 4757 break;
b89e94af 4758 case 0x1a: /* ldsha, load signed halfword alternate */
3475187d 4759#ifndef TARGET_SPARC64
0f8a249a
BS
4760 if (IS_IMM)
4761 goto illegal_insn;
4762 if (!supervisor(dc))
4763 goto priv_insn;
3475187d 4764#endif
66442b07 4765 save_state(dc);
6ae20372 4766 gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
0f8a249a
BS
4767 break;
4768 case 0x1d: /* ldstuba -- XXX: should be atomically */
3475187d 4769#ifndef TARGET_SPARC64
0f8a249a
BS
4770 if (IS_IMM)
4771 goto illegal_insn;
4772 if (!supervisor(dc))
4773 goto priv_insn;
4774#endif
66442b07 4775 save_state(dc);
6ae20372 4776 gen_ldstub_asi(cpu_val, cpu_addr, insn);
0f8a249a 4777 break;
b89e94af 4778 case 0x1f: /* swapa, swap reg with alt. memory. Also
77f193da 4779 atomically */
64a88d5d 4780 CHECK_IU_FEATURE(dc, SWAP);
3475187d 4781#ifndef TARGET_SPARC64
0f8a249a
BS
4782 if (IS_IMM)
4783 goto illegal_insn;
4784 if (!supervisor(dc))
4785 goto priv_insn;
6ea4a6c8 4786#endif
66442b07 4787 save_state(dc);
06828032
RH
4788 cpu_src1 = gen_load_gpr(dc, rd);
4789 gen_swap_asi(cpu_val, cpu_src1, cpu_addr, insn);
0f8a249a 4790 break;
3475187d
FB
4791
4792#ifndef TARGET_SPARC64
0f8a249a
BS
4793 case 0x30: /* ldc */
4794 case 0x31: /* ldcsr */
4795 case 0x33: /* lddc */
4796 goto ncp_insn;
3475187d
FB
4797#endif
4798#endif
4799#ifdef TARGET_SPARC64
0f8a249a 4800 case 0x08: /* V9 ldsw */
2cade6a3 4801 gen_address_mask(dc, cpu_addr);
6ae20372 4802 tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4803 break;
4804 case 0x0b: /* V9 ldx */
2cade6a3 4805 gen_address_mask(dc, cpu_addr);
6ae20372 4806 tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
4807 break;
4808 case 0x18: /* V9 ldswa */
66442b07 4809 save_state(dc);
6ae20372 4810 gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
0f8a249a
BS
4811 break;
4812 case 0x1b: /* V9 ldxa */
66442b07 4813 save_state(dc);
6ae20372 4814 gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
0f8a249a
BS
4815 break;
4816 case 0x2d: /* V9 prefetch, no effect */
4817 goto skip_move;
4818 case 0x30: /* V9 ldfa */
5b12f1e8 4819 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4820 goto jmp_insn;
4821 }
66442b07 4822 save_state(dc);
6ae20372 4823 gen_ldf_asi(cpu_addr, insn, 4, rd);
638737ad 4824 gen_update_fprs_dirty(rd);
81ad8ba2 4825 goto skip_move;
0f8a249a 4826 case 0x33: /* V9 lddfa */
5b12f1e8 4827 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4828 goto jmp_insn;
4829 }
66442b07 4830 save_state(dc);
6ae20372 4831 gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
638737ad 4832 gen_update_fprs_dirty(DFPREG(rd));
81ad8ba2 4833 goto skip_move;
0f8a249a
BS
4834 case 0x3d: /* V9 prefetcha, no effect */
4835 goto skip_move;
4836 case 0x32: /* V9 ldqfa */
64a88d5d 4837 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 4838 if (gen_trap_ifnofpu(dc)) {
8872eb4f
TS
4839 goto jmp_insn;
4840 }
66442b07 4841 save_state(dc);
6ae20372 4842 gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
638737ad 4843 gen_update_fprs_dirty(QFPREG(rd));
1f587329 4844 goto skip_move;
0f8a249a
BS
4845#endif
4846 default:
4847 goto illegal_insn;
4848 }
97ea2859 4849 gen_store_gpr(dc, rd, cpu_val);
db166940 4850#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
0f8a249a 4851 skip_move: ;
3475187d 4852#endif
0f8a249a 4853 } else if (xop >= 0x20 && xop < 0x24) {
de9e9d9f
RH
4854 TCGv t0;
4855
5b12f1e8 4856 if (gen_trap_ifnofpu(dc)) {
a80dde08 4857 goto jmp_insn;
5b12f1e8 4858 }
66442b07 4859 save_state(dc);
0f8a249a 4860 switch (xop) {
b89e94af 4861 case 0x20: /* ldf, load fpreg */
2cade6a3 4862 gen_address_mask(dc, cpu_addr);
de9e9d9f
RH
4863 t0 = get_temp_tl(dc);
4864 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
ba5f5179 4865 cpu_dst_32 = gen_dest_fpr_F(dc);
de9e9d9f 4866 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
208ae657 4867 gen_store_fpr_F(dc, rd, cpu_dst_32);
0f8a249a 4868 break;
3a3b925d
BS
4869 case 0x21: /* ldfsr, V9 ldxfsr */
4870#ifdef TARGET_SPARC64
2cade6a3 4871 gen_address_mask(dc, cpu_addr);
3a3b925d 4872 if (rd == 1) {
abcc7191
RH
4873 TCGv_i64 t64 = tcg_temp_new_i64();
4874 tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
4875 gen_helper_ldxfsr(cpu_env, t64);
4876 tcg_temp_free_i64(t64);
f8641947 4877 break;
fe987e23 4878 }
f8641947 4879#endif
de9e9d9f
RH
4880 cpu_dst_32 = get_temp_i32(dc);
4881 t0 = get_temp_tl(dc);
4882 tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
4883 tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
4884 gen_helper_ldfsr(cpu_env, cpu_dst_32);
0f8a249a 4885 break;
b89e94af 4886 case 0x22: /* ldqf, load quad fpreg */
2ea815ca 4887 {
a7812ae4 4888 TCGv_i32 r_const;
2ea815ca
BS
4889
4890 CHECK_FPU_FEATURE(dc, FLOAT128);
4891 r_const = tcg_const_i32(dc->mem_idx);
1295001c 4892 gen_address_mask(dc, cpu_addr);
fe8d8f0f 4893 gen_helper_ldqf(cpu_env, cpu_addr, r_const);
a7812ae4 4894 tcg_temp_free_i32(r_const);
2ea815ca 4895 gen_op_store_QT0_fpr(QFPREG(rd));
638737ad 4896 gen_update_fprs_dirty(QFPREG(rd));
2ea815ca 4897 }
1f587329 4898 break;
b89e94af 4899 case 0x23: /* lddf, load double fpreg */
03fb8cfc 4900 gen_address_mask(dc, cpu_addr);
3886b8a3 4901 cpu_dst_64 = gen_dest_fpr_D(dc, rd);
03fb8cfc
RH
4902 tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
4903 gen_store_fpr_D(dc, rd, cpu_dst_64);
0f8a249a
BS
4904 break;
4905 default:
4906 goto illegal_insn;
4907 }
dc1a6971 4908 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
0f8a249a 4909 xop == 0xe || xop == 0x1e) {
81634eea
RH
4910 TCGv cpu_val = gen_load_gpr(dc, rd);
4911
0f8a249a 4912 switch (xop) {
b89e94af 4913 case 0x4: /* st, store word */
2cade6a3 4914 gen_address_mask(dc, cpu_addr);
6ae20372 4915 tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4916 break;
b89e94af 4917 case 0x5: /* stb, store byte */
2cade6a3 4918 gen_address_mask(dc, cpu_addr);
6ae20372 4919 tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4920 break;
b89e94af 4921 case 0x6: /* sth, store halfword */
2cade6a3 4922 gen_address_mask(dc, cpu_addr);
6ae20372 4923 tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a 4924 break;
b89e94af 4925 case 0x7: /* std, store double word */
0f8a249a 4926 if (rd & 1)
d4218d99 4927 goto illegal_insn;
1a2fb1c0 4928 else {
a7812ae4 4929 TCGv_i32 r_const;
abcc7191 4930 TCGv_i64 t64;
81634eea 4931 TCGv lo;
1a2fb1c0 4932
66442b07 4933 save_state(dc);
2cade6a3 4934 gen_address_mask(dc, cpu_addr);
2ea815ca 4935 r_const = tcg_const_i32(7);
fe8d8f0f
BS
4936 /* XXX remove alignment check */
4937 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 4938 tcg_temp_free_i32(r_const);
81634eea 4939 lo = gen_load_gpr(dc, rd + 1);
abcc7191
RH
4940
4941 t64 = tcg_temp_new_i64();
4942 tcg_gen_concat_tl_i64(t64, lo, cpu_val);
4943 tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx);
4944 tcg_temp_free_i64(t64);
7fa76c0b 4945 }
0f8a249a 4946 break;
3475187d 4947#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
b89e94af 4948 case 0x14: /* sta, V9 stwa, store word alternate */
3475187d 4949#ifndef TARGET_SPARC64
0f8a249a
BS
4950 if (IS_IMM)
4951 goto illegal_insn;
4952 if (!supervisor(dc))
4953 goto priv_insn;
6ea4a6c8 4954#endif
66442b07 4955 save_state(dc);
6ae20372 4956 gen_st_asi(cpu_val, cpu_addr, insn, 4);
9fd1ae3a 4957 dc->npc = DYNAMIC_PC;
d39c0b99 4958 break;
b89e94af 4959 case 0x15: /* stba, store byte alternate */
3475187d 4960#ifndef TARGET_SPARC64
0f8a249a
BS
4961 if (IS_IMM)
4962 goto illegal_insn;
4963 if (!supervisor(dc))
4964 goto priv_insn;
3475187d 4965#endif
66442b07 4966 save_state(dc);
6ae20372 4967 gen_st_asi(cpu_val, cpu_addr, insn, 1);
9fd1ae3a 4968 dc->npc = DYNAMIC_PC;
d39c0b99 4969 break;
b89e94af 4970 case 0x16: /* stha, store halfword alternate */
3475187d 4971#ifndef TARGET_SPARC64
0f8a249a
BS
4972 if (IS_IMM)
4973 goto illegal_insn;
4974 if (!supervisor(dc))
4975 goto priv_insn;
6ea4a6c8 4976#endif
66442b07 4977 save_state(dc);
6ae20372 4978 gen_st_asi(cpu_val, cpu_addr, insn, 2);
9fd1ae3a 4979 dc->npc = DYNAMIC_PC;
d39c0b99 4980 break;
b89e94af 4981 case 0x17: /* stda, store double word alternate */
3475187d 4982#ifndef TARGET_SPARC64
0f8a249a
BS
4983 if (IS_IMM)
4984 goto illegal_insn;
4985 if (!supervisor(dc))
4986 goto priv_insn;
3475187d 4987#endif
0f8a249a 4988 if (rd & 1)
d4218d99 4989 goto illegal_insn;
1a2fb1c0 4990 else {
66442b07 4991 save_state(dc);
c7785e16 4992 gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
1a2fb1c0 4993 }
d39c0b99 4994 break;
e80cfcfc 4995#endif
3475187d 4996#ifdef TARGET_SPARC64
0f8a249a 4997 case 0x0e: /* V9 stx */
2cade6a3 4998 gen_address_mask(dc, cpu_addr);
6ae20372 4999 tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
0f8a249a
BS
5000 break;
5001 case 0x1e: /* V9 stxa */
66442b07 5002 save_state(dc);
6ae20372 5003 gen_st_asi(cpu_val, cpu_addr, insn, 8);
9fd1ae3a 5004 dc->npc = DYNAMIC_PC;
0f8a249a 5005 break;
3475187d 5006#endif
0f8a249a
BS
5007 default:
5008 goto illegal_insn;
5009 }
5010 } else if (xop > 0x23 && xop < 0x28) {
5b12f1e8 5011 if (gen_trap_ifnofpu(dc)) {
a80dde08 5012 goto jmp_insn;
5b12f1e8 5013 }
66442b07 5014 save_state(dc);
0f8a249a 5015 switch (xop) {
b89e94af 5016 case 0x24: /* stf, store fpreg */
de9e9d9f
RH
5017 {
5018 TCGv t = get_temp_tl(dc);
5019 gen_address_mask(dc, cpu_addr);
5020 cpu_src1_32 = gen_load_fpr_F(dc, rd);
5021 tcg_gen_ext_i32_tl(t, cpu_src1_32);
5022 tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
5023 }
0f8a249a
BS
5024 break;
5025 case 0x25: /* stfsr, V9 stxfsr */
f8641947
RH
5026 {
5027 TCGv t = get_temp_tl(dc);
5028
5029 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUSPARCState, fsr));
3a3b925d 5030#ifdef TARGET_SPARC64
f8641947
RH
5031 gen_address_mask(dc, cpu_addr);
5032 if (rd == 1) {
5033 tcg_gen_qemu_st64(t, cpu_addr, dc->mem_idx);
5034 break;
5035 }
3a3b925d 5036#endif
f8641947
RH
5037 tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
5038 }
0f8a249a 5039 break;
1f587329
BS
5040 case 0x26:
5041#ifdef TARGET_SPARC64
1f587329 5042 /* V9 stqf, store quad fpreg */
2ea815ca 5043 {
a7812ae4 5044 TCGv_i32 r_const;
2ea815ca
BS
5045
5046 CHECK_FPU_FEATURE(dc, FLOAT128);
5047 gen_op_load_fpr_QT0(QFPREG(rd));
5048 r_const = tcg_const_i32(dc->mem_idx);
1295001c 5049 gen_address_mask(dc, cpu_addr);
fe8d8f0f 5050 gen_helper_stqf(cpu_env, cpu_addr, r_const);
a7812ae4 5051 tcg_temp_free_i32(r_const);
2ea815ca 5052 }
1f587329 5053 break;
1f587329
BS
5054#else /* !TARGET_SPARC64 */
5055 /* stdfq, store floating point queue */
5056#if defined(CONFIG_USER_ONLY)
5057 goto illegal_insn;
5058#else
0f8a249a
BS
5059 if (!supervisor(dc))
5060 goto priv_insn;
5b12f1e8 5061 if (gen_trap_ifnofpu(dc)) {
0f8a249a 5062 goto jmp_insn;
5b12f1e8 5063 }
0f8a249a 5064 goto nfq_insn;
1f587329 5065#endif
0f8a249a 5066#endif
b89e94af 5067 case 0x27: /* stdf, store double fpreg */
03fb8cfc
RH
5068 gen_address_mask(dc, cpu_addr);
5069 cpu_src1_64 = gen_load_fpr_D(dc, rd);
5070 tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
0f8a249a
BS
5071 break;
5072 default:
5073 goto illegal_insn;
5074 }
5075 } else if (xop > 0x33 && xop < 0x3f) {
66442b07 5076 save_state(dc);
0f8a249a 5077 switch (xop) {
a4d17f19 5078#ifdef TARGET_SPARC64
0f8a249a 5079 case 0x34: /* V9 stfa */
5b12f1e8 5080 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5081 goto jmp_insn;
5082 }
6ae20372 5083 gen_stf_asi(cpu_addr, insn, 4, rd);
0f8a249a 5084 break;
1f587329 5085 case 0x36: /* V9 stqfa */
2ea815ca 5086 {
a7812ae4 5087 TCGv_i32 r_const;
2ea815ca
BS
5088
5089 CHECK_FPU_FEATURE(dc, FLOAT128);
5b12f1e8 5090 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5091 goto jmp_insn;
5092 }
2ea815ca 5093 r_const = tcg_const_i32(7);
fe8d8f0f 5094 gen_helper_check_align(cpu_env, cpu_addr, r_const);
a7812ae4 5095 tcg_temp_free_i32(r_const);
2ea815ca
BS
5096 gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
5097 }
1f587329 5098 break;
0f8a249a 5099 case 0x37: /* V9 stdfa */
5b12f1e8 5100 if (gen_trap_ifnofpu(dc)) {
5f06b547
TS
5101 goto jmp_insn;
5102 }
6ae20372 5103 gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
0f8a249a
BS
5104 break;
5105 case 0x3c: /* V9 casa */
a4273524
RH
5106 rs2 = GET_FIELD(insn, 27, 31);
5107 cpu_src2 = gen_load_gpr(dc, rs2);
81634eea 5108 gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
0f8a249a
BS
5109 break;
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;
5121#endif
5122 default:
5123 goto illegal_insn;
5124 }
a4273524 5125 } else {
0f8a249a 5126 goto illegal_insn;
a4273524 5127 }
0f8a249a
BS
5128 }
5129 break;
cf495bcf
FB
5130 }
5131 /* default case for non jump instructions */
72cbca10 5132 if (dc->npc == DYNAMIC_PC) {
0f8a249a
BS
5133 dc->pc = DYNAMIC_PC;
5134 gen_op_next_insn();
72cbca10
FB
5135 } else if (dc->npc == JUMP_PC) {
5136 /* we can do a static jump */
6ae20372 5137 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
72cbca10
FB
5138 dc->is_br = 1;
5139 } else {
0f8a249a
BS
5140 dc->pc = dc->npc;
5141 dc->npc = dc->npc + 4;
cf495bcf 5142 }
e80cfcfc 5143 jmp_insn:
42a8aa83 5144 goto egress;
cf495bcf 5145 illegal_insn:
2ea815ca 5146 {
a7812ae4 5147 TCGv_i32 r_const;
2ea815ca 5148
66442b07 5149 save_state(dc);
2ea815ca 5150 r_const = tcg_const_i32(TT_ILL_INSN);
bc265319 5151 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5152 tcg_temp_free_i32(r_const);
2ea815ca
BS
5153 dc->is_br = 1;
5154 }
42a8aa83 5155 goto egress;
64a88d5d 5156 unimp_flush:
2ea815ca 5157 {
a7812ae4 5158 TCGv_i32 r_const;
2ea815ca 5159
66442b07 5160 save_state(dc);
2ea815ca 5161 r_const = tcg_const_i32(TT_UNIMP_FLUSH);
bc265319 5162 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5163 tcg_temp_free_i32(r_const);
2ea815ca
BS
5164 dc->is_br = 1;
5165 }
42a8aa83 5166 goto egress;
e80cfcfc 5167#if !defined(CONFIG_USER_ONLY)
e8af50a3 5168 priv_insn:
2ea815ca 5169 {
a7812ae4 5170 TCGv_i32 r_const;
2ea815ca 5171
66442b07 5172 save_state(dc);
2ea815ca 5173 r_const = tcg_const_i32(TT_PRIV_INSN);
bc265319 5174 gen_helper_raise_exception(cpu_env, r_const);
a7812ae4 5175 tcg_temp_free_i32(r_const);
2ea815ca
BS
5176 dc->is_br = 1;
5177 }
42a8aa83 5178 goto egress;
64a88d5d 5179#endif
e80cfcfc 5180 nfpu_insn:
66442b07 5181 save_state(dc);
e80cfcfc
FB
5182 gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
5183 dc->is_br = 1;
42a8aa83 5184 goto egress;
64a88d5d 5185#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
9143e598 5186 nfq_insn:
66442b07 5187 save_state(dc);
9143e598
BS
5188 gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
5189 dc->is_br = 1;
42a8aa83 5190 goto egress;
9143e598 5191#endif
fcc72045
BS
5192#ifndef TARGET_SPARC64
5193 ncp_insn:
2ea815ca
BS
5194 {
5195 TCGv r_const;
5196
66442b07 5197 save_state(dc);
2ea815ca 5198 r_const = tcg_const_i32(TT_NCP_INSN);
bc265319 5199 gen_helper_raise_exception(cpu_env, r_const);
2ea815ca
BS
5200 tcg_temp_free(r_const);
5201 dc->is_br = 1;
5202 }
42a8aa83 5203 goto egress;
fcc72045 5204#endif
42a8aa83 5205 egress:
30038fd8
RH
5206 if (dc->n_t32 != 0) {
5207 int i;
5208 for (i = dc->n_t32 - 1; i >= 0; --i) {
5209 tcg_temp_free_i32(dc->t32[i]);
5210 }
5211 dc->n_t32 = 0;
5212 }
88023616
RH
5213 if (dc->n_ttl != 0) {
5214 int i;
5215 for (i = dc->n_ttl - 1; i >= 0; --i) {
5216 tcg_temp_free(dc->ttl[i]);
5217 }
5218 dc->n_ttl = 0;
5219 }
7a3f1944
FB
5220}
5221
68a47155
AF
5222static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
5223 TranslationBlock *tb,
5224 bool spc)
7a3f1944 5225{
ed2803da 5226 CPUState *cs = CPU(cpu);
68a47155 5227 CPUSPARCState *env = &cpu->env;
72cbca10 5228 target_ulong pc_start, last_pc;
cf495bcf
FB
5229 uint16_t *gen_opc_end;
5230 DisasContext dc1, *dc = &dc1;
a1d1bb31 5231 CPUBreakpoint *bp;
e8af50a3 5232 int j, lj = -1;
2e70f6ef
PB
5233 int num_insns;
5234 int max_insns;
0184e266 5235 unsigned int insn;
cf495bcf
FB
5236
5237 memset(dc, 0, sizeof(DisasContext));
cf495bcf 5238 dc->tb = tb;
72cbca10 5239 pc_start = tb->pc;
cf495bcf 5240 dc->pc = pc_start;
e80cfcfc 5241 last_pc = dc->pc;
72cbca10 5242 dc->npc = (target_ulong) tb->cs_base;
8393617c 5243 dc->cc_op = CC_OP_DYNAMIC;
6f27aba6 5244 dc->mem_idx = cpu_mmu_index(env);
5578ceab 5245 dc->def = env->def;
f838e2c5
BS
5246 dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5247 dc->address_mask_32bit = tb_am_enabled(tb->flags);
ed2803da 5248 dc->singlestep = (cs->singlestep_enabled || singlestep);
92414b31 5249 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
cf495bcf 5250
2e70f6ef
PB
5251 num_insns = 0;
5252 max_insns = tb->cflags & CF_COUNT_MASK;
5253 if (max_insns == 0)
5254 max_insns = CF_COUNT_MASK;
806f352d 5255 gen_tb_start();
cf495bcf 5256 do {
72cf2d4f
BS
5257 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5258 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 5259 if (bp->pc == dc->pc) {
0f8a249a 5260 if (dc->pc != pc_start)
66442b07 5261 save_state(dc);
bc265319 5262 gen_helper_debug(cpu_env);
57fec1fe 5263 tcg_gen_exit_tb(0);
0f8a249a 5264 dc->is_br = 1;
e80cfcfc 5265 goto exit_gen_loop;
e8af50a3
FB
5266 }
5267 }
5268 }
5269 if (spc) {
93fcfe39 5270 qemu_log("Search PC...\n");
92414b31 5271 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e8af50a3
FB
5272 if (lj < j) {
5273 lj++;
5274 while (lj < j)
ab1103de 5275 tcg_ctx.gen_opc_instr_start[lj++] = 0;
25983cad 5276 tcg_ctx.gen_opc_pc[lj] = dc->pc;
e8af50a3 5277 gen_opc_npc[lj] = dc->npc;
ab1103de 5278 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 5279 tcg_ctx.gen_opc_icount[lj] = num_insns;
e8af50a3
FB
5280 }
5281 }
2e70f6ef
PB
5282 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
5283 gen_io_start();
0f8a249a 5284 last_pc = dc->pc;
0184e266 5285 insn = cpu_ldl_code(env, dc->pc);
b09b2fd3 5286
0184e266 5287 disas_sparc_insn(dc, insn);
2e70f6ef 5288 num_insns++;
0f8a249a
BS
5289
5290 if (dc->is_br)
5291 break;
5292 /* if the next PC is different, we abort now */
5293 if (dc->pc != (last_pc + 4))
5294 break;
d39c0b99
FB
5295 /* if we reach a page boundary, we stop generation so that the
5296 PC of a TT_TFAULT exception is always in the right page */
5297 if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5298 break;
e80cfcfc
FB
5299 /* if single step mode, we generate only one instruction and
5300 generate an exception */
060718c1 5301 if (dc->singlestep) {
e80cfcfc
FB
5302 break;
5303 }
efd7f486 5304 } while ((tcg_ctx.gen_opc_ptr < gen_opc_end) &&
2e70f6ef
PB
5305 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5306 num_insns < max_insns);
e80cfcfc
FB
5307
5308 exit_gen_loop:
b09b2fd3 5309 if (tb->cflags & CF_LAST_IO) {
2e70f6ef 5310 gen_io_end();
b09b2fd3 5311 }
72cbca10 5312 if (!dc->is_br) {
5fafdf24 5313 if (dc->pc != DYNAMIC_PC &&
72cbca10
FB
5314 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5315 /* static PC and NPC: we can use direct chaining */
2f5680ee 5316 gen_goto_tb(dc, 0, dc->pc, dc->npc);
72cbca10 5317 } else {
b09b2fd3 5318 if (dc->pc != DYNAMIC_PC) {
2f5680ee 5319 tcg_gen_movi_tl(cpu_pc, dc->pc);
b09b2fd3 5320 }
934da7ee 5321 save_npc(dc);
57fec1fe 5322 tcg_gen_exit_tb(0);
72cbca10
FB
5323 }
5324 }
806f352d 5325 gen_tb_end(tb, num_insns);
efd7f486 5326 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
e8af50a3 5327 if (spc) {
92414b31 5328 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e8af50a3
FB
5329 lj++;
5330 while (lj <= j)
ab1103de 5331 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e8af50a3 5332#if 0
93fcfe39 5333 log_page_dump();
e8af50a3 5334#endif
c3278b7b
FB
5335 gen_opc_jump_pc[0] = dc->jump_pc[0];
5336 gen_opc_jump_pc[1] = dc->jump_pc[1];
e8af50a3 5337 } else {
e80cfcfc 5338 tb->size = last_pc + 4 - pc_start;
2e70f6ef 5339 tb->icount = num_insns;
e8af50a3 5340 }
7a3f1944 5341#ifdef DEBUG_DISAS
8fec2b8c 5342 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
5343 qemu_log("--------------\n");
5344 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 5345 log_target_disas(env, pc_start, last_pc + 4 - pc_start, 0);
93fcfe39 5346 qemu_log("\n");
cf495bcf 5347 }
7a3f1944 5348#endif
7a3f1944
FB
5349}
5350
2cfc5f17 5351void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5352{
68a47155 5353 gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false);
7a3f1944
FB
5354}
5355
2cfc5f17 5356void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
7a3f1944 5357{
68a47155 5358 gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true);
7a3f1944
FB
5359}
5360
c48fcb47 5361void gen_intermediate_code_init(CPUSPARCState *env)
e80cfcfc 5362{
f5069b26 5363 unsigned int i;
c48fcb47 5364 static int inited;
f5069b26
BS
5365 static const char * const gregnames[8] = {
5366 NULL, // g0 not used
5367 "g1",
5368 "g2",
5369 "g3",
5370 "g4",
5371 "g5",
5372 "g6",
5373 "g7",
5374 };
30038fd8
RH
5375 static const char * const fregnames[32] = {
5376 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5377 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5378 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5379 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
714547bb 5380 };
aaed909a 5381
1a2fb1c0
BS
5382 /* init various static tables */
5383 if (!inited) {
5384 inited = 1;
5385
a7812ae4
PB
5386 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
5387 cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
c5f9864e 5388 offsetof(CPUSPARCState, regwptr),
a7812ae4 5389 "regwptr");
1a2fb1c0 5390#ifdef TARGET_SPARC64
c5f9864e 5391 cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, xcc),
a7812ae4 5392 "xcc");
c5f9864e 5393 cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, asi),
a7812ae4 5394 "asi");
c5f9864e 5395 cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, fprs),
a7812ae4 5396 "fprs");
c5f9864e 5397 cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, gsr),
255e1fcb 5398 "gsr");
a7812ae4 5399 cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5400 offsetof(CPUSPARCState, tick_cmpr),
255e1fcb 5401 "tick_cmpr");
a7812ae4 5402 cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5403 offsetof(CPUSPARCState, stick_cmpr),
255e1fcb 5404 "stick_cmpr");
a7812ae4 5405 cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5406 offsetof(CPUSPARCState, hstick_cmpr),
255e1fcb 5407 "hstick_cmpr");
c5f9864e 5408 cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hintp),
255e1fcb 5409 "hintp");
c5f9864e 5410 cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, htba),
a7812ae4 5411 "htba");
c5f9864e 5412 cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hver),
a7812ae4
PB
5413 "hver");
5414 cpu_ssr = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5415 offsetof(CPUSPARCState, ssr), "ssr");
a7812ae4 5416 cpu_ver = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5417 offsetof(CPUSPARCState, version), "ver");
a7812ae4 5418 cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
c5f9864e 5419 offsetof(CPUSPARCState, softint),
a7812ae4 5420 "softint");
255e1fcb 5421#else
c5f9864e 5422 cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, wim),
255e1fcb 5423 "wim");
1a2fb1c0 5424#endif
c5f9864e 5425 cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cond),
77f193da 5426 "cond");
c5f9864e 5427 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_src),
dc99a3f2 5428 "cc_src");
a7812ae4 5429 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5430 offsetof(CPUSPARCState, cc_src2),
d9bdab86 5431 "cc_src2");
c5f9864e 5432 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_dst),
dc99a3f2 5433 "cc_dst");
c5f9864e 5434 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, cc_op),
8393617c 5435 "cc_op");
c5f9864e 5436 cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, psr),
a7812ae4 5437 "psr");
c5f9864e 5438 cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, fsr),
87e92502 5439 "fsr");
c5f9864e 5440 cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, pc),
48d5c82b 5441 "pc");
c5f9864e 5442 cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, npc),
a7812ae4 5443 "npc");
c5f9864e 5444 cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, y), "y");
255e1fcb 5445#ifndef CONFIG_USER_ONLY
c5f9864e 5446 cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, tbr),
255e1fcb
BS
5447 "tbr");
5448#endif
30038fd8 5449 for (i = 1; i < 8; i++) {
a7812ae4 5450 cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
c5f9864e 5451 offsetof(CPUSPARCState, gregs[i]),
f5069b26 5452 gregnames[i]);
30038fd8
RH
5453 }
5454 for (i = 0; i < TARGET_DPREGS; i++) {
5455 cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
c5f9864e 5456 offsetof(CPUSPARCState, fpr[i]),
45c7b743 5457 fregnames[i]);
30038fd8 5458 }
714547bb 5459
c9e03d8f
BS
5460 /* register helpers */
5461
a7812ae4 5462#define GEN_HELPER 2
c9e03d8f 5463#include "helper.h"
1a2fb1c0 5464 }
658138bc 5465}
d2856f1a 5466
c5f9864e 5467void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
5468{
5469 target_ulong npc;
25983cad 5470 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
d2856f1a
AJ
5471 npc = gen_opc_npc[pc_pos];
5472 if (npc == 1) {
5473 /* dynamic NPC: already stored */
5474 } else if (npc == 2) {
d7da2a10
BS
5475 /* jump PC: use 'cond' and the jump targets of the translation */
5476 if (env->cond) {
d2856f1a 5477 env->npc = gen_opc_jump_pc[0];
d7da2a10 5478 } else {
d2856f1a 5479 env->npc = gen_opc_jump_pc[1];
d7da2a10 5480 }
d2856f1a
AJ
5481 } else {
5482 env->npc = npc;
5483 }
5484}