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