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