]>
git.ipfire.org Git - thirdparty/qemu.git/blob - target/sparc/translate.c
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5 Copyright (C) 2003-2005 Fabrice Bellard
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.
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.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
24 #include "disas/disas.h"
25 #include "exec/helper-proto.h"
26 #include "exec/exec-all.h"
28 #include "exec/cpu_ldst.h"
30 #include "exec/helper-gen.h"
32 #include "trace-tcg.h"
33 #include "exec/translator.h"
40 #define DYNAMIC_PC 1 /* dynamic pc value */
41 #define JUMP_PC 2 /* dynamic pc value which takes only two values
42 according to jump_pc[T2] */
44 /* global register indexes */
45 static TCGv_ptr cpu_regwptr
;
46 static TCGv cpu_cc_src
, cpu_cc_src2
, cpu_cc_dst
;
47 static TCGv_i32 cpu_cc_op
;
48 static TCGv_i32 cpu_psr
;
49 static TCGv cpu_fsr
, cpu_pc
, cpu_npc
;
50 static TCGv cpu_regs
[32];
52 #ifndef CONFIG_USER_ONLY
57 static TCGv_i32 cpu_xcc
, cpu_fprs
;
59 static TCGv cpu_tick_cmpr
, cpu_stick_cmpr
, cpu_hstick_cmpr
;
60 static TCGv cpu_hintp
, cpu_htba
, cpu_hver
, cpu_ssr
, cpu_ver
;
64 /* Floating point registers */
65 static TCGv_i64 cpu_fpr
[TARGET_DPREGS
];
67 #include "exec/gen-icount.h"
69 typedef struct DisasContext
{
70 DisasContextBase base
;
71 target_ulong pc
; /* current Program Counter: integer or DYNAMIC_PC */
72 target_ulong npc
; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
73 target_ulong jump_pc
[2]; /* used when JUMP_PC pc value is used */
76 bool address_mask_32bit
;
77 #ifndef CONFIG_USER_ONLY
84 uint32_t cc_op
; /* current CC operation */
103 // This function uses non-native bit order
104 #define GET_FIELD(X, FROM, TO) \
105 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
107 // This function uses the order in the manuals, i.e. bit 0 is 2^0
108 #define GET_FIELD_SP(X, FROM, TO) \
109 GET_FIELD(X, 31 - (TO), 31 - (FROM))
111 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
112 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
114 #ifdef TARGET_SPARC64
115 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
116 #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
118 #define DFPREG(r) (r & 0x1e)
119 #define QFPREG(r) (r & 0x1c)
122 #define UA2005_HTRAP_MASK 0xff
123 #define V8_TRAP_MASK 0x7f
125 static int sign_extend(int x
, int len
)
128 return (x
<< len
) >> len
;
131 #define IS_IMM (insn & (1<<13))
133 static inline TCGv_i32
get_temp_i32(DisasContext
*dc
)
136 assert(dc
->n_t32
< ARRAY_SIZE(dc
->t32
));
137 dc
->t32
[dc
->n_t32
++] = t
= tcg_temp_new_i32();
141 static inline TCGv
get_temp_tl(DisasContext
*dc
)
144 assert(dc
->n_ttl
< ARRAY_SIZE(dc
->ttl
));
145 dc
->ttl
[dc
->n_ttl
++] = t
= tcg_temp_new();
149 static inline void gen_update_fprs_dirty(DisasContext
*dc
, int rd
)
151 #if defined(TARGET_SPARC64)
152 int bit
= (rd
< 32) ? 1 : 2;
153 /* If we know we've already set this bit within the TB,
154 we can avoid setting it again. */
155 if (!(dc
->fprs_dirty
& bit
)) {
156 dc
->fprs_dirty
|= bit
;
157 tcg_gen_ori_i32(cpu_fprs
, cpu_fprs
, bit
);
162 /* floating point registers moves */
163 static TCGv_i32
gen_load_fpr_F(DisasContext
*dc
, unsigned int src
)
165 #if TCG_TARGET_REG_BITS == 32
167 return TCGV_LOW(cpu_fpr
[src
/ 2]);
169 return TCGV_HIGH(cpu_fpr
[src
/ 2]);
172 TCGv_i32 ret
= get_temp_i32(dc
);
174 tcg_gen_extrl_i64_i32(ret
, cpu_fpr
[src
/ 2]);
176 tcg_gen_extrh_i64_i32(ret
, cpu_fpr
[src
/ 2]);
182 static void gen_store_fpr_F(DisasContext
*dc
, unsigned int dst
, TCGv_i32 v
)
184 #if TCG_TARGET_REG_BITS == 32
186 tcg_gen_mov_i32(TCGV_LOW(cpu_fpr
[dst
/ 2]), v
);
188 tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr
[dst
/ 2]), v
);
191 TCGv_i64 t
= (TCGv_i64
)v
;
192 tcg_gen_deposit_i64(cpu_fpr
[dst
/ 2], cpu_fpr
[dst
/ 2], t
,
193 (dst
& 1 ? 0 : 32), 32);
195 gen_update_fprs_dirty(dc
, dst
);
198 static TCGv_i32
gen_dest_fpr_F(DisasContext
*dc
)
200 return get_temp_i32(dc
);
203 static TCGv_i64
gen_load_fpr_D(DisasContext
*dc
, unsigned int src
)
206 return cpu_fpr
[src
/ 2];
209 static void gen_store_fpr_D(DisasContext
*dc
, unsigned int dst
, TCGv_i64 v
)
212 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2], v
);
213 gen_update_fprs_dirty(dc
, dst
);
216 static TCGv_i64
gen_dest_fpr_D(DisasContext
*dc
, unsigned int dst
)
218 return cpu_fpr
[DFPREG(dst
) / 2];
221 static void gen_op_load_fpr_QT0(unsigned int src
)
223 tcg_gen_st_i64(cpu_fpr
[src
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
224 offsetof(CPU_QuadU
, ll
.upper
));
225 tcg_gen_st_i64(cpu_fpr
[src
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
226 offsetof(CPU_QuadU
, ll
.lower
));
229 static void gen_op_load_fpr_QT1(unsigned int src
)
231 tcg_gen_st_i64(cpu_fpr
[src
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt1
) +
232 offsetof(CPU_QuadU
, ll
.upper
));
233 tcg_gen_st_i64(cpu_fpr
[src
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt1
) +
234 offsetof(CPU_QuadU
, ll
.lower
));
237 static void gen_op_store_QT0_fpr(unsigned int dst
)
239 tcg_gen_ld_i64(cpu_fpr
[dst
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
240 offsetof(CPU_QuadU
, ll
.upper
));
241 tcg_gen_ld_i64(cpu_fpr
[dst
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
242 offsetof(CPU_QuadU
, ll
.lower
));
245 static void gen_store_fpr_Q(DisasContext
*dc
, unsigned int dst
,
246 TCGv_i64 v1
, TCGv_i64 v2
)
250 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2], v1
);
251 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2 + 1], v2
);
252 gen_update_fprs_dirty(dc
, dst
);
255 #ifdef TARGET_SPARC64
256 static TCGv_i64
gen_load_fpr_Q0(DisasContext
*dc
, unsigned int src
)
259 return cpu_fpr
[src
/ 2];
262 static TCGv_i64
gen_load_fpr_Q1(DisasContext
*dc
, unsigned int src
)
265 return cpu_fpr
[src
/ 2 + 1];
268 static void gen_move_Q(DisasContext
*dc
, unsigned int rd
, unsigned int rs
)
273 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], cpu_fpr
[rs
/ 2]);
274 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2 + 1], cpu_fpr
[rs
/ 2 + 1]);
275 gen_update_fprs_dirty(dc
, rd
);
280 #ifdef CONFIG_USER_ONLY
281 #define supervisor(dc) 0
282 #ifdef TARGET_SPARC64
283 #define hypervisor(dc) 0
286 #ifdef TARGET_SPARC64
287 #define hypervisor(dc) (dc->hypervisor)
288 #define supervisor(dc) (dc->supervisor | dc->hypervisor)
290 #define supervisor(dc) (dc->supervisor)
294 #ifdef TARGET_SPARC64
296 #define AM_CHECK(dc) ((dc)->address_mask_32bit)
298 #define AM_CHECK(dc) (1)
302 static inline void gen_address_mask(DisasContext
*dc
, TCGv addr
)
304 #ifdef TARGET_SPARC64
306 tcg_gen_andi_tl(addr
, addr
, 0xffffffffULL
);
310 static inline TCGv
gen_load_gpr(DisasContext
*dc
, int reg
)
314 return cpu_regs
[reg
];
316 TCGv t
= get_temp_tl(dc
);
317 tcg_gen_movi_tl(t
, 0);
322 static inline void gen_store_gpr(DisasContext
*dc
, int reg
, TCGv v
)
326 tcg_gen_mov_tl(cpu_regs
[reg
], v
);
330 static inline TCGv
gen_dest_gpr(DisasContext
*dc
, int reg
)
334 return cpu_regs
[reg
];
336 return get_temp_tl(dc
);
340 static inline bool use_goto_tb(DisasContext
*s
, target_ulong pc
,
343 if (unlikely(s
->base
.singlestep_enabled
|| singlestep
)) {
347 #ifndef CONFIG_USER_ONLY
348 return (pc
& TARGET_PAGE_MASK
) == (s
->base
.tb
->pc
& TARGET_PAGE_MASK
) &&
349 (npc
& TARGET_PAGE_MASK
) == (s
->base
.tb
->pc
& TARGET_PAGE_MASK
);
355 static inline void gen_goto_tb(DisasContext
*s
, int tb_num
,
356 target_ulong pc
, target_ulong npc
)
358 if (use_goto_tb(s
, pc
, npc
)) {
359 /* jump to same page: we can use a direct jump */
360 tcg_gen_goto_tb(tb_num
);
361 tcg_gen_movi_tl(cpu_pc
, pc
);
362 tcg_gen_movi_tl(cpu_npc
, npc
);
363 tcg_gen_exit_tb((uintptr_t)s
->base
.tb
+ tb_num
);
365 /* jump to another page: currently not optimized */
366 tcg_gen_movi_tl(cpu_pc
, pc
);
367 tcg_gen_movi_tl(cpu_npc
, npc
);
373 static inline void gen_mov_reg_N(TCGv reg
, TCGv_i32 src
)
375 tcg_gen_extu_i32_tl(reg
, src
);
376 tcg_gen_extract_tl(reg
, reg
, PSR_NEG_SHIFT
, 1);
379 static inline void gen_mov_reg_Z(TCGv reg
, TCGv_i32 src
)
381 tcg_gen_extu_i32_tl(reg
, src
);
382 tcg_gen_extract_tl(reg
, reg
, PSR_ZERO_SHIFT
, 1);
385 static inline void gen_mov_reg_V(TCGv reg
, TCGv_i32 src
)
387 tcg_gen_extu_i32_tl(reg
, src
);
388 tcg_gen_extract_tl(reg
, reg
, PSR_OVF_SHIFT
, 1);
391 static inline void gen_mov_reg_C(TCGv reg
, TCGv_i32 src
)
393 tcg_gen_extu_i32_tl(reg
, src
);
394 tcg_gen_extract_tl(reg
, reg
, PSR_CARRY_SHIFT
, 1);
397 static inline void gen_op_add_cc(TCGv dst
, TCGv src1
, TCGv src2
)
399 tcg_gen_mov_tl(cpu_cc_src
, src1
);
400 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
401 tcg_gen_add_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
402 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
405 static TCGv_i32
gen_add32_carry32(void)
407 TCGv_i32 carry_32
, cc_src1_32
, cc_src2_32
;
409 /* Carry is computed from a previous add: (dst < src) */
410 #if TARGET_LONG_BITS == 64
411 cc_src1_32
= tcg_temp_new_i32();
412 cc_src2_32
= tcg_temp_new_i32();
413 tcg_gen_extrl_i64_i32(cc_src1_32
, cpu_cc_dst
);
414 tcg_gen_extrl_i64_i32(cc_src2_32
, cpu_cc_src
);
416 cc_src1_32
= cpu_cc_dst
;
417 cc_src2_32
= cpu_cc_src
;
420 carry_32
= tcg_temp_new_i32();
421 tcg_gen_setcond_i32(TCG_COND_LTU
, carry_32
, cc_src1_32
, cc_src2_32
);
423 #if TARGET_LONG_BITS == 64
424 tcg_temp_free_i32(cc_src1_32
);
425 tcg_temp_free_i32(cc_src2_32
);
431 static TCGv_i32
gen_sub32_carry32(void)
433 TCGv_i32 carry_32
, cc_src1_32
, cc_src2_32
;
435 /* Carry is computed from a previous borrow: (src1 < src2) */
436 #if TARGET_LONG_BITS == 64
437 cc_src1_32
= tcg_temp_new_i32();
438 cc_src2_32
= tcg_temp_new_i32();
439 tcg_gen_extrl_i64_i32(cc_src1_32
, cpu_cc_src
);
440 tcg_gen_extrl_i64_i32(cc_src2_32
, cpu_cc_src2
);
442 cc_src1_32
= cpu_cc_src
;
443 cc_src2_32
= cpu_cc_src2
;
446 carry_32
= tcg_temp_new_i32();
447 tcg_gen_setcond_i32(TCG_COND_LTU
, carry_32
, cc_src1_32
, cc_src2_32
);
449 #if TARGET_LONG_BITS == 64
450 tcg_temp_free_i32(cc_src1_32
);
451 tcg_temp_free_i32(cc_src2_32
);
457 static void gen_op_addx_int(DisasContext
*dc
, TCGv dst
, TCGv src1
,
458 TCGv src2
, int update_cc
)
466 /* Carry is known to be zero. Fall back to plain ADD. */
468 gen_op_add_cc(dst
, src1
, src2
);
470 tcg_gen_add_tl(dst
, src1
, src2
);
477 if (TARGET_LONG_BITS
== 32) {
478 /* We can re-use the host's hardware carry generation by using
479 an ADD2 opcode. We discard the low part of the output.
480 Ideally we'd combine this operation with the add that
481 generated the carry in the first place. */
482 carry
= tcg_temp_new();
483 tcg_gen_add2_tl(carry
, dst
, cpu_cc_src
, src1
, cpu_cc_src2
, src2
);
484 tcg_temp_free(carry
);
487 carry_32
= gen_add32_carry32();
493 carry_32
= gen_sub32_carry32();
497 /* We need external help to produce the carry. */
498 carry_32
= tcg_temp_new_i32();
499 gen_helper_compute_C_icc(carry_32
, cpu_env
);
503 #if TARGET_LONG_BITS == 64
504 carry
= tcg_temp_new();
505 tcg_gen_extu_i32_i64(carry
, carry_32
);
510 tcg_gen_add_tl(dst
, src1
, src2
);
511 tcg_gen_add_tl(dst
, dst
, carry
);
513 tcg_temp_free_i32(carry_32
);
514 #if TARGET_LONG_BITS == 64
515 tcg_temp_free(carry
);
520 tcg_gen_mov_tl(cpu_cc_src
, src1
);
521 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
522 tcg_gen_mov_tl(cpu_cc_dst
, dst
);
523 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADDX
);
524 dc
->cc_op
= CC_OP_ADDX
;
528 static inline void gen_op_sub_cc(TCGv dst
, TCGv src1
, TCGv src2
)
530 tcg_gen_mov_tl(cpu_cc_src
, src1
);
531 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
532 tcg_gen_sub_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
533 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
536 static void gen_op_subx_int(DisasContext
*dc
, TCGv dst
, TCGv src1
,
537 TCGv src2
, int update_cc
)
545 /* Carry is known to be zero. Fall back to plain SUB. */
547 gen_op_sub_cc(dst
, src1
, src2
);
549 tcg_gen_sub_tl(dst
, src1
, src2
);
556 carry_32
= gen_add32_carry32();
562 if (TARGET_LONG_BITS
== 32) {
563 /* We can re-use the host's hardware carry generation by using
564 a SUB2 opcode. We discard the low part of the output.
565 Ideally we'd combine this operation with the add that
566 generated the carry in the first place. */
567 carry
= tcg_temp_new();
568 tcg_gen_sub2_tl(carry
, dst
, cpu_cc_src
, src1
, cpu_cc_src2
, src2
);
569 tcg_temp_free(carry
);
572 carry_32
= gen_sub32_carry32();
576 /* We need external help to produce the carry. */
577 carry_32
= tcg_temp_new_i32();
578 gen_helper_compute_C_icc(carry_32
, cpu_env
);
582 #if TARGET_LONG_BITS == 64
583 carry
= tcg_temp_new();
584 tcg_gen_extu_i32_i64(carry
, carry_32
);
589 tcg_gen_sub_tl(dst
, src1
, src2
);
590 tcg_gen_sub_tl(dst
, dst
, carry
);
592 tcg_temp_free_i32(carry_32
);
593 #if TARGET_LONG_BITS == 64
594 tcg_temp_free(carry
);
599 tcg_gen_mov_tl(cpu_cc_src
, src1
);
600 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
601 tcg_gen_mov_tl(cpu_cc_dst
, dst
);
602 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUBX
);
603 dc
->cc_op
= CC_OP_SUBX
;
607 static inline void gen_op_mulscc(TCGv dst
, TCGv src1
, TCGv src2
)
609 TCGv r_temp
, zero
, t0
;
611 r_temp
= tcg_temp_new();
618 zero
= tcg_const_tl(0);
619 tcg_gen_andi_tl(cpu_cc_src
, src1
, 0xffffffff);
620 tcg_gen_andi_tl(r_temp
, cpu_y
, 0x1);
621 tcg_gen_andi_tl(cpu_cc_src2
, src2
, 0xffffffff);
622 tcg_gen_movcond_tl(TCG_COND_EQ
, cpu_cc_src2
, r_temp
, zero
,
627 // env->y = (b2 << 31) | (env->y >> 1);
628 tcg_gen_extract_tl(t0
, cpu_y
, 1, 31);
629 tcg_gen_deposit_tl(cpu_y
, t0
, cpu_cc_src
, 31, 1);
632 gen_mov_reg_N(t0
, cpu_psr
);
633 gen_mov_reg_V(r_temp
, cpu_psr
);
634 tcg_gen_xor_tl(t0
, t0
, r_temp
);
635 tcg_temp_free(r_temp
);
637 // T0 = (b1 << 31) | (T0 >> 1);
639 tcg_gen_shli_tl(t0
, t0
, 31);
640 tcg_gen_shri_tl(cpu_cc_src
, cpu_cc_src
, 1);
641 tcg_gen_or_tl(cpu_cc_src
, cpu_cc_src
, t0
);
644 tcg_gen_add_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
646 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
649 static inline void gen_op_multiply(TCGv dst
, TCGv src1
, TCGv src2
, int sign_ext
)
651 #if TARGET_LONG_BITS == 32
653 tcg_gen_muls2_tl(dst
, cpu_y
, src1
, src2
);
655 tcg_gen_mulu2_tl(dst
, cpu_y
, src1
, src2
);
658 TCGv t0
= tcg_temp_new_i64();
659 TCGv t1
= tcg_temp_new_i64();
662 tcg_gen_ext32s_i64(t0
, src1
);
663 tcg_gen_ext32s_i64(t1
, src2
);
665 tcg_gen_ext32u_i64(t0
, src1
);
666 tcg_gen_ext32u_i64(t1
, src2
);
669 tcg_gen_mul_i64(dst
, t0
, t1
);
673 tcg_gen_shri_i64(cpu_y
, dst
, 32);
677 static inline void gen_op_umul(TCGv dst
, TCGv src1
, TCGv src2
)
679 /* zero-extend truncated operands before multiplication */
680 gen_op_multiply(dst
, src1
, src2
, 0);
683 static inline void gen_op_smul(TCGv dst
, TCGv src1
, TCGv src2
)
685 /* sign-extend truncated operands before multiplication */
686 gen_op_multiply(dst
, src1
, src2
, 1);
690 static inline void gen_op_eval_ba(TCGv dst
)
692 tcg_gen_movi_tl(dst
, 1);
696 static inline void gen_op_eval_be(TCGv dst
, TCGv_i32 src
)
698 gen_mov_reg_Z(dst
, src
);
702 static inline void gen_op_eval_ble(TCGv dst
, TCGv_i32 src
)
704 TCGv t0
= tcg_temp_new();
705 gen_mov_reg_N(t0
, src
);
706 gen_mov_reg_V(dst
, src
);
707 tcg_gen_xor_tl(dst
, dst
, t0
);
708 gen_mov_reg_Z(t0
, src
);
709 tcg_gen_or_tl(dst
, dst
, t0
);
714 static inline void gen_op_eval_bl(TCGv dst
, TCGv_i32 src
)
716 TCGv t0
= tcg_temp_new();
717 gen_mov_reg_V(t0
, src
);
718 gen_mov_reg_N(dst
, src
);
719 tcg_gen_xor_tl(dst
, dst
, t0
);
724 static inline void gen_op_eval_bleu(TCGv dst
, TCGv_i32 src
)
726 TCGv t0
= tcg_temp_new();
727 gen_mov_reg_Z(t0
, src
);
728 gen_mov_reg_C(dst
, src
);
729 tcg_gen_or_tl(dst
, dst
, t0
);
734 static inline void gen_op_eval_bcs(TCGv dst
, TCGv_i32 src
)
736 gen_mov_reg_C(dst
, src
);
740 static inline void gen_op_eval_bvs(TCGv dst
, TCGv_i32 src
)
742 gen_mov_reg_V(dst
, src
);
746 static inline void gen_op_eval_bn(TCGv dst
)
748 tcg_gen_movi_tl(dst
, 0);
752 static inline void gen_op_eval_bneg(TCGv dst
, TCGv_i32 src
)
754 gen_mov_reg_N(dst
, src
);
758 static inline void gen_op_eval_bne(TCGv dst
, TCGv_i32 src
)
760 gen_mov_reg_Z(dst
, src
);
761 tcg_gen_xori_tl(dst
, dst
, 0x1);
765 static inline void gen_op_eval_bg(TCGv dst
, TCGv_i32 src
)
767 gen_op_eval_ble(dst
, src
);
768 tcg_gen_xori_tl(dst
, dst
, 0x1);
772 static inline void gen_op_eval_bge(TCGv dst
, TCGv_i32 src
)
774 gen_op_eval_bl(dst
, src
);
775 tcg_gen_xori_tl(dst
, dst
, 0x1);
779 static inline void gen_op_eval_bgu(TCGv dst
, TCGv_i32 src
)
781 gen_op_eval_bleu(dst
, src
);
782 tcg_gen_xori_tl(dst
, dst
, 0x1);
786 static inline void gen_op_eval_bcc(TCGv dst
, TCGv_i32 src
)
788 gen_mov_reg_C(dst
, src
);
789 tcg_gen_xori_tl(dst
, dst
, 0x1);
793 static inline void gen_op_eval_bpos(TCGv dst
, TCGv_i32 src
)
795 gen_mov_reg_N(dst
, src
);
796 tcg_gen_xori_tl(dst
, dst
, 0x1);
800 static inline void gen_op_eval_bvc(TCGv dst
, TCGv_i32 src
)
802 gen_mov_reg_V(dst
, src
);
803 tcg_gen_xori_tl(dst
, dst
, 0x1);
807 FPSR bit field FCC1 | FCC0:
813 static inline void gen_mov_reg_FCC0(TCGv reg
, TCGv src
,
814 unsigned int fcc_offset
)
816 tcg_gen_shri_tl(reg
, src
, FSR_FCC0_SHIFT
+ fcc_offset
);
817 tcg_gen_andi_tl(reg
, reg
, 0x1);
820 static inline void gen_mov_reg_FCC1(TCGv reg
, TCGv src
,
821 unsigned int fcc_offset
)
823 tcg_gen_shri_tl(reg
, src
, FSR_FCC1_SHIFT
+ fcc_offset
);
824 tcg_gen_andi_tl(reg
, reg
, 0x1);
828 static inline void gen_op_eval_fbne(TCGv dst
, TCGv src
,
829 unsigned int fcc_offset
)
831 TCGv t0
= tcg_temp_new();
832 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
833 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
834 tcg_gen_or_tl(dst
, dst
, t0
);
838 // 1 or 2: FCC0 ^ FCC1
839 static inline void gen_op_eval_fblg(TCGv dst
, TCGv src
,
840 unsigned int fcc_offset
)
842 TCGv t0
= tcg_temp_new();
843 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
844 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
845 tcg_gen_xor_tl(dst
, dst
, t0
);
850 static inline void gen_op_eval_fbul(TCGv dst
, TCGv src
,
851 unsigned int fcc_offset
)
853 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
857 static inline void gen_op_eval_fbl(TCGv dst
, TCGv src
,
858 unsigned int fcc_offset
)
860 TCGv t0
= tcg_temp_new();
861 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
862 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
863 tcg_gen_andc_tl(dst
, dst
, t0
);
868 static inline void gen_op_eval_fbug(TCGv dst
, TCGv src
,
869 unsigned int fcc_offset
)
871 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
875 static inline void gen_op_eval_fbg(TCGv dst
, TCGv src
,
876 unsigned int fcc_offset
)
878 TCGv t0
= tcg_temp_new();
879 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
880 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
881 tcg_gen_andc_tl(dst
, t0
, dst
);
886 static inline void gen_op_eval_fbu(TCGv dst
, TCGv src
,
887 unsigned int fcc_offset
)
889 TCGv t0
= tcg_temp_new();
890 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
891 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
892 tcg_gen_and_tl(dst
, dst
, t0
);
897 static inline void gen_op_eval_fbe(TCGv dst
, TCGv src
,
898 unsigned int fcc_offset
)
900 TCGv t0
= tcg_temp_new();
901 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
902 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
903 tcg_gen_or_tl(dst
, dst
, t0
);
904 tcg_gen_xori_tl(dst
, dst
, 0x1);
908 // 0 or 3: !(FCC0 ^ FCC1)
909 static inline void gen_op_eval_fbue(TCGv dst
, TCGv src
,
910 unsigned int fcc_offset
)
912 TCGv t0
= tcg_temp_new();
913 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
914 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
915 tcg_gen_xor_tl(dst
, dst
, t0
);
916 tcg_gen_xori_tl(dst
, dst
, 0x1);
921 static inline void gen_op_eval_fbge(TCGv dst
, TCGv src
,
922 unsigned int fcc_offset
)
924 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
925 tcg_gen_xori_tl(dst
, dst
, 0x1);
928 // !1: !(FCC0 & !FCC1)
929 static inline void gen_op_eval_fbuge(TCGv dst
, TCGv src
,
930 unsigned int fcc_offset
)
932 TCGv t0
= tcg_temp_new();
933 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
934 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
935 tcg_gen_andc_tl(dst
, dst
, t0
);
936 tcg_gen_xori_tl(dst
, dst
, 0x1);
941 static inline void gen_op_eval_fble(TCGv dst
, TCGv src
,
942 unsigned int fcc_offset
)
944 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
945 tcg_gen_xori_tl(dst
, dst
, 0x1);
948 // !2: !(!FCC0 & FCC1)
949 static inline void gen_op_eval_fbule(TCGv dst
, TCGv src
,
950 unsigned int fcc_offset
)
952 TCGv t0
= tcg_temp_new();
953 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
954 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
955 tcg_gen_andc_tl(dst
, t0
, dst
);
956 tcg_gen_xori_tl(dst
, dst
, 0x1);
960 // !3: !(FCC0 & FCC1)
961 static inline void gen_op_eval_fbo(TCGv dst
, TCGv src
,
962 unsigned int fcc_offset
)
964 TCGv t0
= tcg_temp_new();
965 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
966 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
967 tcg_gen_and_tl(dst
, dst
, t0
);
968 tcg_gen_xori_tl(dst
, dst
, 0x1);
972 static inline void gen_branch2(DisasContext
*dc
, target_ulong pc1
,
973 target_ulong pc2
, TCGv r_cond
)
975 TCGLabel
*l1
= gen_new_label();
977 tcg_gen_brcondi_tl(TCG_COND_EQ
, r_cond
, 0, l1
);
979 gen_goto_tb(dc
, 0, pc1
, pc1
+ 4);
982 gen_goto_tb(dc
, 1, pc2
, pc2
+ 4);
985 static void gen_branch_a(DisasContext
*dc
, target_ulong pc1
)
987 TCGLabel
*l1
= gen_new_label();
988 target_ulong npc
= dc
->npc
;
990 tcg_gen_brcondi_tl(TCG_COND_EQ
, cpu_cond
, 0, l1
);
992 gen_goto_tb(dc
, 0, npc
, pc1
);
995 gen_goto_tb(dc
, 1, npc
+ 4, npc
+ 8);
997 dc
->base
.is_jmp
= DISAS_NORETURN
;
1000 static void gen_branch_n(DisasContext
*dc
, target_ulong pc1
)
1002 target_ulong npc
= dc
->npc
;
1004 if (likely(npc
!= DYNAMIC_PC
)) {
1006 dc
->jump_pc
[0] = pc1
;
1007 dc
->jump_pc
[1] = npc
+ 4;
1012 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1014 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
1015 t
= tcg_const_tl(pc1
);
1016 z
= tcg_const_tl(0);
1017 tcg_gen_movcond_tl(TCG_COND_NE
, cpu_npc
, cpu_cond
, z
, t
, cpu_npc
);
1021 dc
->pc
= DYNAMIC_PC
;
1025 static inline void gen_generic_branch(DisasContext
*dc
)
1027 TCGv npc0
= tcg_const_tl(dc
->jump_pc
[0]);
1028 TCGv npc1
= tcg_const_tl(dc
->jump_pc
[1]);
1029 TCGv zero
= tcg_const_tl(0);
1031 tcg_gen_movcond_tl(TCG_COND_NE
, cpu_npc
, cpu_cond
, zero
, npc0
, npc1
);
1033 tcg_temp_free(npc0
);
1034 tcg_temp_free(npc1
);
1035 tcg_temp_free(zero
);
1038 /* call this function before using the condition register as it may
1039 have been set for a jump */
1040 static inline void flush_cond(DisasContext
*dc
)
1042 if (dc
->npc
== JUMP_PC
) {
1043 gen_generic_branch(dc
);
1044 dc
->npc
= DYNAMIC_PC
;
1048 static inline void save_npc(DisasContext
*dc
)
1050 if (dc
->npc
== JUMP_PC
) {
1051 gen_generic_branch(dc
);
1052 dc
->npc
= DYNAMIC_PC
;
1053 } else if (dc
->npc
!= DYNAMIC_PC
) {
1054 tcg_gen_movi_tl(cpu_npc
, dc
->npc
);
1058 static inline void update_psr(DisasContext
*dc
)
1060 if (dc
->cc_op
!= CC_OP_FLAGS
) {
1061 dc
->cc_op
= CC_OP_FLAGS
;
1062 gen_helper_compute_psr(cpu_env
);
1066 static inline void save_state(DisasContext
*dc
)
1068 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
1072 static void gen_exception(DisasContext
*dc
, int which
)
1077 t
= tcg_const_i32(which
);
1078 gen_helper_raise_exception(cpu_env
, t
);
1079 tcg_temp_free_i32(t
);
1080 dc
->base
.is_jmp
= DISAS_NORETURN
;
1083 static void gen_check_align(TCGv addr
, int mask
)
1085 TCGv_i32 r_mask
= tcg_const_i32(mask
);
1086 gen_helper_check_align(cpu_env
, addr
, r_mask
);
1087 tcg_temp_free_i32(r_mask
);
1090 static inline void gen_mov_pc_npc(DisasContext
*dc
)
1092 if (dc
->npc
== JUMP_PC
) {
1093 gen_generic_branch(dc
);
1094 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1095 dc
->pc
= DYNAMIC_PC
;
1096 } else if (dc
->npc
== DYNAMIC_PC
) {
1097 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1098 dc
->pc
= DYNAMIC_PC
;
1104 static inline void gen_op_next_insn(void)
1106 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1107 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
1110 static void free_compare(DisasCompare
*cmp
)
1113 tcg_temp_free(cmp
->c1
);
1116 tcg_temp_free(cmp
->c2
);
1120 static void gen_compare(DisasCompare
*cmp
, bool xcc
, unsigned int cond
,
1123 static int subcc_cond
[16] = {
1139 -1, /* no overflow */
1142 static int logic_cond
[16] = {
1144 TCG_COND_EQ
, /* eq: Z */
1145 TCG_COND_LE
, /* le: Z | (N ^ V) -> Z | N */
1146 TCG_COND_LT
, /* lt: N ^ V -> N */
1147 TCG_COND_EQ
, /* leu: C | Z -> Z */
1148 TCG_COND_NEVER
, /* ltu: C -> 0 */
1149 TCG_COND_LT
, /* neg: N */
1150 TCG_COND_NEVER
, /* vs: V -> 0 */
1152 TCG_COND_NE
, /* ne: !Z */
1153 TCG_COND_GT
, /* gt: !(Z | (N ^ V)) -> !(Z | N) */
1154 TCG_COND_GE
, /* ge: !(N ^ V) -> !N */
1155 TCG_COND_NE
, /* gtu: !(C | Z) -> !Z */
1156 TCG_COND_ALWAYS
, /* geu: !C -> 1 */
1157 TCG_COND_GE
, /* pos: !N */
1158 TCG_COND_ALWAYS
, /* vc: !V -> 1 */
1164 #ifdef TARGET_SPARC64
1174 switch (dc
->cc_op
) {
1176 cmp
->cond
= logic_cond
[cond
];
1178 cmp
->is_bool
= false;
1180 cmp
->c2
= tcg_const_tl(0);
1181 #ifdef TARGET_SPARC64
1184 cmp
->c1
= tcg_temp_new();
1185 tcg_gen_ext32s_tl(cmp
->c1
, cpu_cc_dst
);
1190 cmp
->c1
= cpu_cc_dst
;
1197 cmp
->cond
= (cond
== 6 ? TCG_COND_LT
: TCG_COND_GE
);
1198 goto do_compare_dst_0
;
1200 case 7: /* overflow */
1201 case 15: /* !overflow */
1205 cmp
->cond
= subcc_cond
[cond
];
1206 cmp
->is_bool
= false;
1207 #ifdef TARGET_SPARC64
1209 /* Note that sign-extension works for unsigned compares as
1210 long as both operands are sign-extended. */
1211 cmp
->g1
= cmp
->g2
= false;
1212 cmp
->c1
= tcg_temp_new();
1213 cmp
->c2
= tcg_temp_new();
1214 tcg_gen_ext32s_tl(cmp
->c1
, cpu_cc_src
);
1215 tcg_gen_ext32s_tl(cmp
->c2
, cpu_cc_src2
);
1219 cmp
->g1
= cmp
->g2
= true;
1220 cmp
->c1
= cpu_cc_src
;
1221 cmp
->c2
= cpu_cc_src2
;
1228 gen_helper_compute_psr(cpu_env
);
1229 dc
->cc_op
= CC_OP_FLAGS
;
1233 /* We're going to generate a boolean result. */
1234 cmp
->cond
= TCG_COND_NE
;
1235 cmp
->is_bool
= true;
1236 cmp
->g1
= cmp
->g2
= false;
1237 cmp
->c1
= r_dst
= tcg_temp_new();
1238 cmp
->c2
= tcg_const_tl(0);
1242 gen_op_eval_bn(r_dst
);
1245 gen_op_eval_be(r_dst
, r_src
);
1248 gen_op_eval_ble(r_dst
, r_src
);
1251 gen_op_eval_bl(r_dst
, r_src
);
1254 gen_op_eval_bleu(r_dst
, r_src
);
1257 gen_op_eval_bcs(r_dst
, r_src
);
1260 gen_op_eval_bneg(r_dst
, r_src
);
1263 gen_op_eval_bvs(r_dst
, r_src
);
1266 gen_op_eval_ba(r_dst
);
1269 gen_op_eval_bne(r_dst
, r_src
);
1272 gen_op_eval_bg(r_dst
, r_src
);
1275 gen_op_eval_bge(r_dst
, r_src
);
1278 gen_op_eval_bgu(r_dst
, r_src
);
1281 gen_op_eval_bcc(r_dst
, r_src
);
1284 gen_op_eval_bpos(r_dst
, r_src
);
1287 gen_op_eval_bvc(r_dst
, r_src
);
1294 static void gen_fcompare(DisasCompare
*cmp
, unsigned int cc
, unsigned int cond
)
1296 unsigned int offset
;
1299 /* For now we still generate a straight boolean result. */
1300 cmp
->cond
= TCG_COND_NE
;
1301 cmp
->is_bool
= true;
1302 cmp
->g1
= cmp
->g2
= false;
1303 cmp
->c1
= r_dst
= tcg_temp_new();
1304 cmp
->c2
= tcg_const_tl(0);
1324 gen_op_eval_bn(r_dst
);
1327 gen_op_eval_fbne(r_dst
, cpu_fsr
, offset
);
1330 gen_op_eval_fblg(r_dst
, cpu_fsr
, offset
);
1333 gen_op_eval_fbul(r_dst
, cpu_fsr
, offset
);
1336 gen_op_eval_fbl(r_dst
, cpu_fsr
, offset
);
1339 gen_op_eval_fbug(r_dst
, cpu_fsr
, offset
);
1342 gen_op_eval_fbg(r_dst
, cpu_fsr
, offset
);
1345 gen_op_eval_fbu(r_dst
, cpu_fsr
, offset
);
1348 gen_op_eval_ba(r_dst
);
1351 gen_op_eval_fbe(r_dst
, cpu_fsr
, offset
);
1354 gen_op_eval_fbue(r_dst
, cpu_fsr
, offset
);
1357 gen_op_eval_fbge(r_dst
, cpu_fsr
, offset
);
1360 gen_op_eval_fbuge(r_dst
, cpu_fsr
, offset
);
1363 gen_op_eval_fble(r_dst
, cpu_fsr
, offset
);
1366 gen_op_eval_fbule(r_dst
, cpu_fsr
, offset
);
1369 gen_op_eval_fbo(r_dst
, cpu_fsr
, offset
);
1374 static void gen_cond(TCGv r_dst
, unsigned int cc
, unsigned int cond
,
1378 gen_compare(&cmp
, cc
, cond
, dc
);
1380 /* The interface is to return a boolean in r_dst. */
1382 tcg_gen_mov_tl(r_dst
, cmp
.c1
);
1384 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1390 static void gen_fcond(TCGv r_dst
, unsigned int cc
, unsigned int cond
)
1393 gen_fcompare(&cmp
, cc
, cond
);
1395 /* The interface is to return a boolean in r_dst. */
1397 tcg_gen_mov_tl(r_dst
, cmp
.c1
);
1399 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1405 #ifdef TARGET_SPARC64
1407 static const int gen_tcg_cond_reg
[8] = {
1418 static void gen_compare_reg(DisasCompare
*cmp
, int cond
, TCGv r_src
)
1420 cmp
->cond
= tcg_invert_cond(gen_tcg_cond_reg
[cond
]);
1421 cmp
->is_bool
= false;
1425 cmp
->c2
= tcg_const_tl(0);
1428 static inline void gen_cond_reg(TCGv r_dst
, int cond
, TCGv r_src
)
1431 gen_compare_reg(&cmp
, cond
, r_src
);
1433 /* The interface is to return a boolean in r_dst. */
1434 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1440 static void do_branch(DisasContext
*dc
, int32_t offset
, uint32_t insn
, int cc
)
1442 unsigned int cond
= GET_FIELD(insn
, 3, 6), a
= (insn
& (1 << 29));
1443 target_ulong target
= dc
->pc
+ offset
;
1445 #ifdef TARGET_SPARC64
1446 if (unlikely(AM_CHECK(dc
))) {
1447 target
&= 0xffffffffULL
;
1451 /* unconditional not taken */
1453 dc
->pc
= dc
->npc
+ 4;
1454 dc
->npc
= dc
->pc
+ 4;
1457 dc
->npc
= dc
->pc
+ 4;
1459 } else if (cond
== 0x8) {
1460 /* unconditional taken */
1463 dc
->npc
= dc
->pc
+ 4;
1467 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1471 gen_cond(cpu_cond
, cc
, cond
, dc
);
1473 gen_branch_a(dc
, target
);
1475 gen_branch_n(dc
, target
);
1480 static void do_fbranch(DisasContext
*dc
, int32_t offset
, uint32_t insn
, int cc
)
1482 unsigned int cond
= GET_FIELD(insn
, 3, 6), a
= (insn
& (1 << 29));
1483 target_ulong target
= dc
->pc
+ offset
;
1485 #ifdef TARGET_SPARC64
1486 if (unlikely(AM_CHECK(dc
))) {
1487 target
&= 0xffffffffULL
;
1491 /* unconditional not taken */
1493 dc
->pc
= dc
->npc
+ 4;
1494 dc
->npc
= dc
->pc
+ 4;
1497 dc
->npc
= dc
->pc
+ 4;
1499 } else if (cond
== 0x8) {
1500 /* unconditional taken */
1503 dc
->npc
= dc
->pc
+ 4;
1507 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1511 gen_fcond(cpu_cond
, cc
, cond
);
1513 gen_branch_a(dc
, target
);
1515 gen_branch_n(dc
, target
);
1520 #ifdef TARGET_SPARC64
1521 static void do_branch_reg(DisasContext
*dc
, int32_t offset
, uint32_t insn
,
1524 unsigned int cond
= GET_FIELD_SP(insn
, 25, 27), a
= (insn
& (1 << 29));
1525 target_ulong target
= dc
->pc
+ offset
;
1527 if (unlikely(AM_CHECK(dc
))) {
1528 target
&= 0xffffffffULL
;
1531 gen_cond_reg(cpu_cond
, cond
, r_reg
);
1533 gen_branch_a(dc
, target
);
1535 gen_branch_n(dc
, target
);
1539 static inline void gen_op_fcmps(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1543 gen_helper_fcmps(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1546 gen_helper_fcmps_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1549 gen_helper_fcmps_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1552 gen_helper_fcmps_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1557 static inline void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1561 gen_helper_fcmpd(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1564 gen_helper_fcmpd_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1567 gen_helper_fcmpd_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1570 gen_helper_fcmpd_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1575 static inline void gen_op_fcmpq(int fccno
)
1579 gen_helper_fcmpq(cpu_fsr
, cpu_env
);
1582 gen_helper_fcmpq_fcc1(cpu_fsr
, cpu_env
);
1585 gen_helper_fcmpq_fcc2(cpu_fsr
, cpu_env
);
1588 gen_helper_fcmpq_fcc3(cpu_fsr
, cpu_env
);
1593 static inline void gen_op_fcmpes(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1597 gen_helper_fcmpes(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1600 gen_helper_fcmpes_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1603 gen_helper_fcmpes_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1606 gen_helper_fcmpes_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1611 static inline void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1615 gen_helper_fcmped(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1618 gen_helper_fcmped_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1621 gen_helper_fcmped_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1624 gen_helper_fcmped_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1629 static inline void gen_op_fcmpeq(int fccno
)
1633 gen_helper_fcmpeq(cpu_fsr
, cpu_env
);
1636 gen_helper_fcmpeq_fcc1(cpu_fsr
, cpu_env
);
1639 gen_helper_fcmpeq_fcc2(cpu_fsr
, cpu_env
);
1642 gen_helper_fcmpeq_fcc3(cpu_fsr
, cpu_env
);
1649 static inline void gen_op_fcmps(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1651 gen_helper_fcmps(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1654 static inline void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1656 gen_helper_fcmpd(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1659 static inline void gen_op_fcmpq(int fccno
)
1661 gen_helper_fcmpq(cpu_fsr
, cpu_env
);
1664 static inline void gen_op_fcmpes(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1666 gen_helper_fcmpes(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1669 static inline void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1671 gen_helper_fcmped(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1674 static inline void gen_op_fcmpeq(int fccno
)
1676 gen_helper_fcmpeq(cpu_fsr
, cpu_env
);
1680 static void gen_op_fpexception_im(DisasContext
*dc
, int fsr_flags
)
1682 tcg_gen_andi_tl(cpu_fsr
, cpu_fsr
, FSR_FTT_NMASK
);
1683 tcg_gen_ori_tl(cpu_fsr
, cpu_fsr
, fsr_flags
);
1684 gen_exception(dc
, TT_FP_EXCP
);
1687 static int gen_trap_ifnofpu(DisasContext
*dc
)
1689 #if !defined(CONFIG_USER_ONLY)
1690 if (!dc
->fpu_enabled
) {
1691 gen_exception(dc
, TT_NFPU_INSN
);
1698 static inline void gen_op_clear_ieee_excp_and_FTT(void)
1700 tcg_gen_andi_tl(cpu_fsr
, cpu_fsr
, FSR_FTT_CEXC_NMASK
);
1703 static inline void gen_fop_FF(DisasContext
*dc
, int rd
, int rs
,
1704 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i32
))
1708 src
= gen_load_fpr_F(dc
, rs
);
1709 dst
= gen_dest_fpr_F(dc
);
1711 gen(dst
, cpu_env
, src
);
1712 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1714 gen_store_fpr_F(dc
, rd
, dst
);
1717 static inline void gen_ne_fop_FF(DisasContext
*dc
, int rd
, int rs
,
1718 void (*gen
)(TCGv_i32
, TCGv_i32
))
1722 src
= gen_load_fpr_F(dc
, rs
);
1723 dst
= gen_dest_fpr_F(dc
);
1727 gen_store_fpr_F(dc
, rd
, dst
);
1730 static inline void gen_fop_FFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1731 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i32
, TCGv_i32
))
1733 TCGv_i32 dst
, src1
, src2
;
1735 src1
= gen_load_fpr_F(dc
, rs1
);
1736 src2
= gen_load_fpr_F(dc
, rs2
);
1737 dst
= gen_dest_fpr_F(dc
);
1739 gen(dst
, cpu_env
, src1
, src2
);
1740 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1742 gen_store_fpr_F(dc
, rd
, dst
);
1745 #ifdef TARGET_SPARC64
1746 static inline void gen_ne_fop_FFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1747 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
1749 TCGv_i32 dst
, src1
, src2
;
1751 src1
= gen_load_fpr_F(dc
, rs1
);
1752 src2
= gen_load_fpr_F(dc
, rs2
);
1753 dst
= gen_dest_fpr_F(dc
);
1755 gen(dst
, src1
, src2
);
1757 gen_store_fpr_F(dc
, rd
, dst
);
1761 static inline void gen_fop_DD(DisasContext
*dc
, int rd
, int rs
,
1762 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i64
))
1766 src
= gen_load_fpr_D(dc
, rs
);
1767 dst
= gen_dest_fpr_D(dc
, rd
);
1769 gen(dst
, cpu_env
, src
);
1770 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1772 gen_store_fpr_D(dc
, rd
, dst
);
1775 #ifdef TARGET_SPARC64
1776 static inline void gen_ne_fop_DD(DisasContext
*dc
, int rd
, int rs
,
1777 void (*gen
)(TCGv_i64
, TCGv_i64
))
1781 src
= gen_load_fpr_D(dc
, rs
);
1782 dst
= gen_dest_fpr_D(dc
, rd
);
1786 gen_store_fpr_D(dc
, rd
, dst
);
1790 static inline void gen_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1791 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i64
, TCGv_i64
))
1793 TCGv_i64 dst
, src1
, src2
;
1795 src1
= gen_load_fpr_D(dc
, rs1
);
1796 src2
= gen_load_fpr_D(dc
, rs2
);
1797 dst
= gen_dest_fpr_D(dc
, rd
);
1799 gen(dst
, cpu_env
, src1
, src2
);
1800 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1802 gen_store_fpr_D(dc
, rd
, dst
);
1805 #ifdef TARGET_SPARC64
1806 static inline void gen_ne_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1807 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
))
1809 TCGv_i64 dst
, src1
, src2
;
1811 src1
= gen_load_fpr_D(dc
, rs1
);
1812 src2
= gen_load_fpr_D(dc
, rs2
);
1813 dst
= gen_dest_fpr_D(dc
, rd
);
1815 gen(dst
, src1
, src2
);
1817 gen_store_fpr_D(dc
, rd
, dst
);
1820 static inline void gen_gsr_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1821 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_i64
))
1823 TCGv_i64 dst
, src1
, src2
;
1825 src1
= gen_load_fpr_D(dc
, rs1
);
1826 src2
= gen_load_fpr_D(dc
, rs2
);
1827 dst
= gen_dest_fpr_D(dc
, rd
);
1829 gen(dst
, cpu_gsr
, src1
, src2
);
1831 gen_store_fpr_D(dc
, rd
, dst
);
1834 static inline void gen_ne_fop_DDDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1835 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_i64
))
1837 TCGv_i64 dst
, src0
, src1
, src2
;
1839 src1
= gen_load_fpr_D(dc
, rs1
);
1840 src2
= gen_load_fpr_D(dc
, rs2
);
1841 src0
= gen_load_fpr_D(dc
, rd
);
1842 dst
= gen_dest_fpr_D(dc
, rd
);
1844 gen(dst
, src0
, src1
, src2
);
1846 gen_store_fpr_D(dc
, rd
, dst
);
1850 static inline void gen_fop_QQ(DisasContext
*dc
, int rd
, int rs
,
1851 void (*gen
)(TCGv_ptr
))
1853 gen_op_load_fpr_QT1(QFPREG(rs
));
1856 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1858 gen_op_store_QT0_fpr(QFPREG(rd
));
1859 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1862 #ifdef TARGET_SPARC64
1863 static inline void gen_ne_fop_QQ(DisasContext
*dc
, int rd
, int rs
,
1864 void (*gen
)(TCGv_ptr
))
1866 gen_op_load_fpr_QT1(QFPREG(rs
));
1870 gen_op_store_QT0_fpr(QFPREG(rd
));
1871 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1875 static inline void gen_fop_QQQ(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1876 void (*gen
)(TCGv_ptr
))
1878 gen_op_load_fpr_QT0(QFPREG(rs1
));
1879 gen_op_load_fpr_QT1(QFPREG(rs2
));
1882 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1884 gen_op_store_QT0_fpr(QFPREG(rd
));
1885 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1888 static inline void gen_fop_DFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1889 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
, TCGv_i32
))
1892 TCGv_i32 src1
, src2
;
1894 src1
= gen_load_fpr_F(dc
, rs1
);
1895 src2
= gen_load_fpr_F(dc
, rs2
);
1896 dst
= gen_dest_fpr_D(dc
, rd
);
1898 gen(dst
, cpu_env
, src1
, src2
);
1899 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1901 gen_store_fpr_D(dc
, rd
, dst
);
1904 static inline void gen_fop_QDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1905 void (*gen
)(TCGv_ptr
, TCGv_i64
, TCGv_i64
))
1907 TCGv_i64 src1
, src2
;
1909 src1
= gen_load_fpr_D(dc
, rs1
);
1910 src2
= gen_load_fpr_D(dc
, rs2
);
1912 gen(cpu_env
, src1
, src2
);
1913 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1915 gen_op_store_QT0_fpr(QFPREG(rd
));
1916 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1919 #ifdef TARGET_SPARC64
1920 static inline void gen_fop_DF(DisasContext
*dc
, int rd
, int rs
,
1921 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
))
1926 src
= gen_load_fpr_F(dc
, rs
);
1927 dst
= gen_dest_fpr_D(dc
, rd
);
1929 gen(dst
, cpu_env
, src
);
1930 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1932 gen_store_fpr_D(dc
, rd
, dst
);
1936 static inline void gen_ne_fop_DF(DisasContext
*dc
, int rd
, int rs
,
1937 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
))
1942 src
= gen_load_fpr_F(dc
, rs
);
1943 dst
= gen_dest_fpr_D(dc
, rd
);
1945 gen(dst
, cpu_env
, src
);
1947 gen_store_fpr_D(dc
, rd
, dst
);
1950 static inline void gen_fop_FD(DisasContext
*dc
, int rd
, int rs
,
1951 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i64
))
1956 src
= gen_load_fpr_D(dc
, rs
);
1957 dst
= gen_dest_fpr_F(dc
);
1959 gen(dst
, cpu_env
, src
);
1960 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1962 gen_store_fpr_F(dc
, rd
, dst
);
1965 static inline void gen_fop_FQ(DisasContext
*dc
, int rd
, int rs
,
1966 void (*gen
)(TCGv_i32
, TCGv_ptr
))
1970 gen_op_load_fpr_QT1(QFPREG(rs
));
1971 dst
= gen_dest_fpr_F(dc
);
1974 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1976 gen_store_fpr_F(dc
, rd
, dst
);
1979 static inline void gen_fop_DQ(DisasContext
*dc
, int rd
, int rs
,
1980 void (*gen
)(TCGv_i64
, TCGv_ptr
))
1984 gen_op_load_fpr_QT1(QFPREG(rs
));
1985 dst
= gen_dest_fpr_D(dc
, rd
);
1988 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1990 gen_store_fpr_D(dc
, rd
, dst
);
1993 static inline void gen_ne_fop_QF(DisasContext
*dc
, int rd
, int rs
,
1994 void (*gen
)(TCGv_ptr
, TCGv_i32
))
1998 src
= gen_load_fpr_F(dc
, rs
);
2002 gen_op_store_QT0_fpr(QFPREG(rd
));
2003 gen_update_fprs_dirty(dc
, QFPREG(rd
));
2006 static inline void gen_ne_fop_QD(DisasContext
*dc
, int rd
, int rs
,
2007 void (*gen
)(TCGv_ptr
, TCGv_i64
))
2011 src
= gen_load_fpr_D(dc
, rs
);
2015 gen_op_store_QT0_fpr(QFPREG(rd
));
2016 gen_update_fprs_dirty(dc
, QFPREG(rd
));
2019 static void gen_swap(DisasContext
*dc
, TCGv dst
, TCGv src
,
2020 TCGv addr
, int mmu_idx
, TCGMemOp memop
)
2022 gen_address_mask(dc
, addr
);
2023 tcg_gen_atomic_xchg_tl(dst
, addr
, src
, mmu_idx
, memop
);
2026 static void gen_ldstub(DisasContext
*dc
, TCGv dst
, TCGv addr
, int mmu_idx
)
2028 TCGv m1
= tcg_const_tl(0xff);
2029 gen_address_mask(dc
, addr
);
2030 tcg_gen_atomic_xchg_tl(dst
, addr
, m1
, mmu_idx
, MO_UB
);
2035 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2054 static DisasASI
get_asi(DisasContext
*dc
, int insn
, TCGMemOp memop
)
2056 int asi
= GET_FIELD(insn
, 19, 26);
2057 ASIType type
= GET_ASI_HELPER
;
2058 int mem_idx
= dc
->mem_idx
;
2060 #ifndef TARGET_SPARC64
2061 /* Before v9, all asis are immediate and privileged. */
2063 gen_exception(dc
, TT_ILL_INSN
);
2064 type
= GET_ASI_EXCP
;
2065 } else if (supervisor(dc
)
2066 /* Note that LEON accepts ASI_USERDATA in user mode, for
2067 use with CASA. Also note that previous versions of
2068 QEMU allowed (and old versions of gcc emitted) ASI_P
2069 for LEON, which is incorrect. */
2070 || (asi
== ASI_USERDATA
2071 && (dc
->def
->features
& CPU_FEATURE_CASA
))) {
2073 case ASI_USERDATA
: /* User data access */
2074 mem_idx
= MMU_USER_IDX
;
2075 type
= GET_ASI_DIRECT
;
2077 case ASI_KERNELDATA
: /* Supervisor data access */
2078 mem_idx
= MMU_KERNEL_IDX
;
2079 type
= GET_ASI_DIRECT
;
2081 case ASI_M_BYPASS
: /* MMU passthrough */
2082 case ASI_LEON_BYPASS
: /* LEON MMU passthrough */
2083 mem_idx
= MMU_PHYS_IDX
;
2084 type
= GET_ASI_DIRECT
;
2086 case ASI_M_BCOPY
: /* Block copy, sta access */
2087 mem_idx
= MMU_KERNEL_IDX
;
2088 type
= GET_ASI_BCOPY
;
2090 case ASI_M_BFILL
: /* Block fill, stda access */
2091 mem_idx
= MMU_KERNEL_IDX
;
2092 type
= GET_ASI_BFILL
;
2096 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
2097 * permissions check in get_physical_address(..).
2099 mem_idx
= (dc
->mem_idx
== MMU_PHYS_IDX
) ? MMU_PHYS_IDX
: mem_idx
;
2101 gen_exception(dc
, TT_PRIV_INSN
);
2102 type
= GET_ASI_EXCP
;
2108 /* With v9, all asis below 0x80 are privileged. */
2109 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
2110 down that bit into DisasContext. For the moment that's ok,
2111 since the direct implementations below doesn't have any ASIs
2112 in the restricted [0x30, 0x7f] range, and the check will be
2113 done properly in the helper. */
2114 if (!supervisor(dc
) && asi
< 0x80) {
2115 gen_exception(dc
, TT_PRIV_ACT
);
2116 type
= GET_ASI_EXCP
;
2119 case ASI_REAL
: /* Bypass */
2120 case ASI_REAL_IO
: /* Bypass, non-cacheable */
2121 case ASI_REAL_L
: /* Bypass LE */
2122 case ASI_REAL_IO_L
: /* Bypass, non-cacheable LE */
2123 case ASI_TWINX_REAL
: /* Real address, twinx */
2124 case ASI_TWINX_REAL_L
: /* Real address, twinx, LE */
2125 case ASI_QUAD_LDD_PHYS
:
2126 case ASI_QUAD_LDD_PHYS_L
:
2127 mem_idx
= MMU_PHYS_IDX
;
2129 case ASI_N
: /* Nucleus */
2130 case ASI_NL
: /* Nucleus LE */
2133 case ASI_NUCLEUS_QUAD_LDD
:
2134 case ASI_NUCLEUS_QUAD_LDD_L
:
2135 if (hypervisor(dc
)) {
2136 mem_idx
= MMU_PHYS_IDX
;
2138 mem_idx
= MMU_NUCLEUS_IDX
;
2141 case ASI_AIUP
: /* As if user primary */
2142 case ASI_AIUPL
: /* As if user primary LE */
2143 case ASI_TWINX_AIUP
:
2144 case ASI_TWINX_AIUP_L
:
2145 case ASI_BLK_AIUP_4V
:
2146 case ASI_BLK_AIUP_L_4V
:
2149 mem_idx
= MMU_USER_IDX
;
2151 case ASI_AIUS
: /* As if user secondary */
2152 case ASI_AIUSL
: /* As if user secondary LE */
2153 case ASI_TWINX_AIUS
:
2154 case ASI_TWINX_AIUS_L
:
2155 case ASI_BLK_AIUS_4V
:
2156 case ASI_BLK_AIUS_L_4V
:
2159 mem_idx
= MMU_USER_SECONDARY_IDX
;
2161 case ASI_S
: /* Secondary */
2162 case ASI_SL
: /* Secondary LE */
2165 case ASI_BLK_COMMIT_S
:
2172 if (mem_idx
== MMU_USER_IDX
) {
2173 mem_idx
= MMU_USER_SECONDARY_IDX
;
2174 } else if (mem_idx
== MMU_KERNEL_IDX
) {
2175 mem_idx
= MMU_KERNEL_SECONDARY_IDX
;
2178 case ASI_P
: /* Primary */
2179 case ASI_PL
: /* Primary LE */
2182 case ASI_BLK_COMMIT_P
:
2206 type
= GET_ASI_DIRECT
;
2208 case ASI_TWINX_REAL
:
2209 case ASI_TWINX_REAL_L
:
2212 case ASI_TWINX_AIUP
:
2213 case ASI_TWINX_AIUP_L
:
2214 case ASI_TWINX_AIUS
:
2215 case ASI_TWINX_AIUS_L
:
2220 case ASI_QUAD_LDD_PHYS
:
2221 case ASI_QUAD_LDD_PHYS_L
:
2222 case ASI_NUCLEUS_QUAD_LDD
:
2223 case ASI_NUCLEUS_QUAD_LDD_L
:
2224 type
= GET_ASI_DTWINX
;
2226 case ASI_BLK_COMMIT_P
:
2227 case ASI_BLK_COMMIT_S
:
2228 case ASI_BLK_AIUP_4V
:
2229 case ASI_BLK_AIUP_L_4V
:
2232 case ASI_BLK_AIUS_4V
:
2233 case ASI_BLK_AIUS_L_4V
:
2240 type
= GET_ASI_BLOCK
;
2247 type
= GET_ASI_SHORT
;
2254 type
= GET_ASI_SHORT
;
2257 /* The little-endian asis all have bit 3 set. */
2264 return (DisasASI
){ type
, asi
, mem_idx
, memop
};
2267 static void gen_ld_asi(DisasContext
*dc
, TCGv dst
, TCGv addr
,
2268 int insn
, TCGMemOp memop
)
2270 DisasASI da
= get_asi(dc
, insn
, memop
);
2275 case GET_ASI_DTWINX
: /* Reserved for ldda. */
2276 gen_exception(dc
, TT_ILL_INSN
);
2278 case GET_ASI_DIRECT
:
2279 gen_address_mask(dc
, addr
);
2280 tcg_gen_qemu_ld_tl(dst
, addr
, da
.mem_idx
, da
.memop
);
2284 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2285 TCGv_i32 r_mop
= tcg_const_i32(memop
);
2288 #ifdef TARGET_SPARC64
2289 gen_helper_ld_asi(dst
, cpu_env
, addr
, r_asi
, r_mop
);
2292 TCGv_i64 t64
= tcg_temp_new_i64();
2293 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2294 tcg_gen_trunc_i64_tl(dst
, t64
);
2295 tcg_temp_free_i64(t64
);
2298 tcg_temp_free_i32(r_mop
);
2299 tcg_temp_free_i32(r_asi
);
2305 static void gen_st_asi(DisasContext
*dc
, TCGv src
, TCGv addr
,
2306 int insn
, TCGMemOp memop
)
2308 DisasASI da
= get_asi(dc
, insn
, memop
);
2313 case GET_ASI_DTWINX
: /* Reserved for stda. */
2314 #ifndef TARGET_SPARC64
2315 gen_exception(dc
, TT_ILL_INSN
);
2318 if (!(dc
->def
->features
& CPU_FEATURE_HYPV
)) {
2319 /* Pre OpenSPARC CPUs don't have these */
2320 gen_exception(dc
, TT_ILL_INSN
);
2323 /* in OpenSPARC T1+ CPUs TWINX ASIs in store instructions
2324 * are ST_BLKINIT_ ASIs */
2327 case GET_ASI_DIRECT
:
2328 gen_address_mask(dc
, addr
);
2329 tcg_gen_qemu_st_tl(src
, addr
, da
.mem_idx
, da
.memop
);
2331 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
2333 /* Copy 32 bytes from the address in SRC to ADDR. */
2334 /* ??? The original qemu code suggests 4-byte alignment, dropping
2335 the low bits, but the only place I can see this used is in the
2336 Linux kernel with 32 byte alignment, which would make more sense
2337 as a cacheline-style operation. */
2339 TCGv saddr
= tcg_temp_new();
2340 TCGv daddr
= tcg_temp_new();
2341 TCGv four
= tcg_const_tl(4);
2342 TCGv_i32 tmp
= tcg_temp_new_i32();
2345 tcg_gen_andi_tl(saddr
, src
, -4);
2346 tcg_gen_andi_tl(daddr
, addr
, -4);
2347 for (i
= 0; i
< 32; i
+= 4) {
2348 /* Since the loads and stores are paired, allow the
2349 copy to happen in the host endianness. */
2350 tcg_gen_qemu_ld_i32(tmp
, saddr
, da
.mem_idx
, MO_UL
);
2351 tcg_gen_qemu_st_i32(tmp
, daddr
, da
.mem_idx
, MO_UL
);
2352 tcg_gen_add_tl(saddr
, saddr
, four
);
2353 tcg_gen_add_tl(daddr
, daddr
, four
);
2356 tcg_temp_free(saddr
);
2357 tcg_temp_free(daddr
);
2358 tcg_temp_free(four
);
2359 tcg_temp_free_i32(tmp
);
2365 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2366 TCGv_i32 r_mop
= tcg_const_i32(memop
& MO_SIZE
);
2369 #ifdef TARGET_SPARC64
2370 gen_helper_st_asi(cpu_env
, addr
, src
, r_asi
, r_mop
);
2373 TCGv_i64 t64
= tcg_temp_new_i64();
2374 tcg_gen_extu_tl_i64(t64
, src
);
2375 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2376 tcg_temp_free_i64(t64
);
2379 tcg_temp_free_i32(r_mop
);
2380 tcg_temp_free_i32(r_asi
);
2382 /* A write to a TLB register may alter page maps. End the TB. */
2383 dc
->npc
= DYNAMIC_PC
;
2389 static void gen_swap_asi(DisasContext
*dc
, TCGv dst
, TCGv src
,
2390 TCGv addr
, int insn
)
2392 DisasASI da
= get_asi(dc
, insn
, MO_TEUL
);
2397 case GET_ASI_DIRECT
:
2398 gen_swap(dc
, dst
, src
, addr
, da
.mem_idx
, da
.memop
);
2401 /* ??? Should be DAE_invalid_asi. */
2402 gen_exception(dc
, TT_DATA_ACCESS
);
2407 static void gen_cas_asi(DisasContext
*dc
, TCGv addr
, TCGv cmpv
,
2410 DisasASI da
= get_asi(dc
, insn
, MO_TEUL
);
2416 case GET_ASI_DIRECT
:
2417 oldv
= tcg_temp_new();
2418 tcg_gen_atomic_cmpxchg_tl(oldv
, addr
, cmpv
, gen_load_gpr(dc
, rd
),
2419 da
.mem_idx
, da
.memop
);
2420 gen_store_gpr(dc
, rd
, oldv
);
2421 tcg_temp_free(oldv
);
2424 /* ??? Should be DAE_invalid_asi. */
2425 gen_exception(dc
, TT_DATA_ACCESS
);
2430 static void gen_ldstub_asi(DisasContext
*dc
, TCGv dst
, TCGv addr
, int insn
)
2432 DisasASI da
= get_asi(dc
, insn
, MO_UB
);
2437 case GET_ASI_DIRECT
:
2438 gen_ldstub(dc
, dst
, addr
, da
.mem_idx
);
2441 /* ??? In theory, this should be raise DAE_invalid_asi.
2442 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
2443 if (tb_cflags(dc
->base
.tb
) & CF_PARALLEL
) {
2444 gen_helper_exit_atomic(cpu_env
);
2446 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2447 TCGv_i32 r_mop
= tcg_const_i32(MO_UB
);
2451 t64
= tcg_temp_new_i64();
2452 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2454 s64
= tcg_const_i64(0xff);
2455 gen_helper_st_asi(cpu_env
, addr
, s64
, r_asi
, r_mop
);
2456 tcg_temp_free_i64(s64
);
2457 tcg_temp_free_i32(r_mop
);
2458 tcg_temp_free_i32(r_asi
);
2460 tcg_gen_trunc_i64_tl(dst
, t64
);
2461 tcg_temp_free_i64(t64
);
2464 dc
->npc
= DYNAMIC_PC
;
2471 #ifdef TARGET_SPARC64
2472 static void gen_ldf_asi(DisasContext
*dc
, TCGv addr
,
2473 int insn
, int size
, int rd
)
2475 DisasASI da
= get_asi(dc
, insn
, (size
== 4 ? MO_TEUL
: MO_TEQ
));
2483 case GET_ASI_DIRECT
:
2484 gen_address_mask(dc
, addr
);
2487 d32
= gen_dest_fpr_F(dc
);
2488 tcg_gen_qemu_ld_i32(d32
, addr
, da
.mem_idx
, da
.memop
);
2489 gen_store_fpr_F(dc
, rd
, d32
);
2492 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2493 da
.memop
| MO_ALIGN_4
);
2496 d64
= tcg_temp_new_i64();
2497 tcg_gen_qemu_ld_i64(d64
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_4
);
2498 tcg_gen_addi_tl(addr
, addr
, 8);
2499 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/2+1], addr
, da
.mem_idx
,
2500 da
.memop
| MO_ALIGN_4
);
2501 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
2502 tcg_temp_free_i64(d64
);
2505 g_assert_not_reached();
2510 /* Valid for lddfa on aligned registers only. */
2511 if (size
== 8 && (rd
& 7) == 0) {
2516 gen_address_mask(dc
, addr
);
2518 /* The first operation checks required alignment. */
2519 memop
= da
.memop
| MO_ALIGN_64
;
2520 eight
= tcg_const_tl(8);
2521 for (i
= 0; ; ++i
) {
2522 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2 + i
], addr
,
2527 tcg_gen_add_tl(addr
, addr
, eight
);
2530 tcg_temp_free(eight
);
2532 gen_exception(dc
, TT_ILL_INSN
);
2537 /* Valid for lddfa only. */
2539 gen_address_mask(dc
, addr
);
2540 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
, da
.memop
);
2542 gen_exception(dc
, TT_ILL_INSN
);
2548 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2549 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2552 /* According to the table in the UA2011 manual, the only
2553 other asis that are valid for ldfa/lddfa/ldqfa are
2554 the NO_FAULT asis. We still need a helper for these,
2555 but we can just use the integer asi helper for them. */
2558 d64
= tcg_temp_new_i64();
2559 gen_helper_ld_asi(d64
, cpu_env
, addr
, r_asi
, r_mop
);
2560 d32
= gen_dest_fpr_F(dc
);
2561 tcg_gen_extrl_i64_i32(d32
, d64
);
2562 tcg_temp_free_i64(d64
);
2563 gen_store_fpr_F(dc
, rd
, d32
);
2566 gen_helper_ld_asi(cpu_fpr
[rd
/ 2], cpu_env
, addr
, r_asi
, r_mop
);
2569 d64
= tcg_temp_new_i64();
2570 gen_helper_ld_asi(d64
, cpu_env
, addr
, r_asi
, r_mop
);
2571 tcg_gen_addi_tl(addr
, addr
, 8);
2572 gen_helper_ld_asi(cpu_fpr
[rd
/2+1], cpu_env
, addr
, r_asi
, r_mop
);
2573 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
2574 tcg_temp_free_i64(d64
);
2577 g_assert_not_reached();
2579 tcg_temp_free_i32(r_mop
);
2580 tcg_temp_free_i32(r_asi
);
2586 static void gen_stf_asi(DisasContext
*dc
, TCGv addr
,
2587 int insn
, int size
, int rd
)
2589 DisasASI da
= get_asi(dc
, insn
, (size
== 4 ? MO_TEUL
: MO_TEQ
));
2596 case GET_ASI_DIRECT
:
2597 gen_address_mask(dc
, addr
);
2600 d32
= gen_load_fpr_F(dc
, rd
);
2601 tcg_gen_qemu_st_i32(d32
, addr
, da
.mem_idx
, da
.memop
);
2604 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2605 da
.memop
| MO_ALIGN_4
);
2608 /* Only 4-byte alignment required. However, it is legal for the
2609 cpu to signal the alignment fault, and the OS trap handler is
2610 required to fix it up. Requiring 16-byte alignment here avoids
2611 having to probe the second page before performing the first
2613 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2614 da
.memop
| MO_ALIGN_16
);
2615 tcg_gen_addi_tl(addr
, addr
, 8);
2616 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/2+1], addr
, da
.mem_idx
, da
.memop
);
2619 g_assert_not_reached();
2624 /* Valid for stdfa on aligned registers only. */
2625 if (size
== 8 && (rd
& 7) == 0) {
2630 gen_address_mask(dc
, addr
);
2632 /* The first operation checks required alignment. */
2633 memop
= da
.memop
| MO_ALIGN_64
;
2634 eight
= tcg_const_tl(8);
2635 for (i
= 0; ; ++i
) {
2636 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2 + i
], addr
,
2641 tcg_gen_add_tl(addr
, addr
, eight
);
2644 tcg_temp_free(eight
);
2646 gen_exception(dc
, TT_ILL_INSN
);
2651 /* Valid for stdfa only. */
2653 gen_address_mask(dc
, addr
);
2654 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
, da
.memop
);
2656 gen_exception(dc
, TT_ILL_INSN
);
2661 /* According to the table in the UA2011 manual, the only
2662 other asis that are valid for ldfa/lddfa/ldqfa are
2663 the PST* asis, which aren't currently handled. */
2664 gen_exception(dc
, TT_ILL_INSN
);
2669 static void gen_ldda_asi(DisasContext
*dc
, TCGv addr
, int insn
, int rd
)
2671 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2672 TCGv_i64 hi
= gen_dest_gpr(dc
, rd
);
2673 TCGv_i64 lo
= gen_dest_gpr(dc
, rd
+ 1);
2679 case GET_ASI_DTWINX
:
2680 gen_address_mask(dc
, addr
);
2681 tcg_gen_qemu_ld_i64(hi
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_16
);
2682 tcg_gen_addi_tl(addr
, addr
, 8);
2683 tcg_gen_qemu_ld_i64(lo
, addr
, da
.mem_idx
, da
.memop
);
2686 case GET_ASI_DIRECT
:
2688 TCGv_i64 tmp
= tcg_temp_new_i64();
2690 gen_address_mask(dc
, addr
);
2691 tcg_gen_qemu_ld_i64(tmp
, addr
, da
.mem_idx
, da
.memop
);
2693 /* Note that LE ldda acts as if each 32-bit register
2694 result is byte swapped. Having just performed one
2695 64-bit bswap, we need now to swap the writebacks. */
2696 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2697 tcg_gen_extr32_i64(lo
, hi
, tmp
);
2699 tcg_gen_extr32_i64(hi
, lo
, tmp
);
2701 tcg_temp_free_i64(tmp
);
2706 /* ??? In theory we've handled all of the ASIs that are valid
2707 for ldda, and this should raise DAE_invalid_asi. However,
2708 real hardware allows others. This can be seen with e.g.
2709 FreeBSD 10.3 wrt ASI_IC_TAG. */
2711 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2712 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2713 TCGv_i64 tmp
= tcg_temp_new_i64();
2716 gen_helper_ld_asi(tmp
, cpu_env
, addr
, r_asi
, r_mop
);
2717 tcg_temp_free_i32(r_asi
);
2718 tcg_temp_free_i32(r_mop
);
2721 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2722 tcg_gen_extr32_i64(lo
, hi
, tmp
);
2724 tcg_gen_extr32_i64(hi
, lo
, tmp
);
2726 tcg_temp_free_i64(tmp
);
2731 gen_store_gpr(dc
, rd
, hi
);
2732 gen_store_gpr(dc
, rd
+ 1, lo
);
2735 static void gen_stda_asi(DisasContext
*dc
, TCGv hi
, TCGv addr
,
2738 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2739 TCGv lo
= gen_load_gpr(dc
, rd
+ 1);
2745 case GET_ASI_DTWINX
:
2746 gen_address_mask(dc
, addr
);
2747 tcg_gen_qemu_st_i64(hi
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_16
);
2748 tcg_gen_addi_tl(addr
, addr
, 8);
2749 tcg_gen_qemu_st_i64(lo
, addr
, da
.mem_idx
, da
.memop
);
2752 case GET_ASI_DIRECT
:
2754 TCGv_i64 t64
= tcg_temp_new_i64();
2756 /* Note that LE stda acts as if each 32-bit register result is
2757 byte swapped. We will perform one 64-bit LE store, so now
2758 we must swap the order of the construction. */
2759 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2760 tcg_gen_concat32_i64(t64
, lo
, hi
);
2762 tcg_gen_concat32_i64(t64
, hi
, lo
);
2764 gen_address_mask(dc
, addr
);
2765 tcg_gen_qemu_st_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2766 tcg_temp_free_i64(t64
);
2771 /* ??? In theory we've handled all of the ASIs that are valid
2772 for stda, and this should raise DAE_invalid_asi. */
2774 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2775 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2776 TCGv_i64 t64
= tcg_temp_new_i64();
2779 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2780 tcg_gen_concat32_i64(t64
, lo
, hi
);
2782 tcg_gen_concat32_i64(t64
, hi
, lo
);
2786 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2787 tcg_temp_free_i32(r_mop
);
2788 tcg_temp_free_i32(r_asi
);
2789 tcg_temp_free_i64(t64
);
2795 static void gen_casx_asi(DisasContext
*dc
, TCGv addr
, TCGv cmpv
,
2798 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2804 case GET_ASI_DIRECT
:
2805 oldv
= tcg_temp_new();
2806 tcg_gen_atomic_cmpxchg_tl(oldv
, addr
, cmpv
, gen_load_gpr(dc
, rd
),
2807 da
.mem_idx
, da
.memop
);
2808 gen_store_gpr(dc
, rd
, oldv
);
2809 tcg_temp_free(oldv
);
2812 /* ??? Should be DAE_invalid_asi. */
2813 gen_exception(dc
, TT_DATA_ACCESS
);
2818 #elif !defined(CONFIG_USER_ONLY)
2819 static void gen_ldda_asi(DisasContext
*dc
, TCGv addr
, int insn
, int rd
)
2821 /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
2822 whereby "rd + 1" elicits "error: array subscript is above array".
2823 Since we have already asserted that rd is even, the semantics
2825 TCGv lo
= gen_dest_gpr(dc
, rd
| 1);
2826 TCGv hi
= gen_dest_gpr(dc
, rd
);
2827 TCGv_i64 t64
= tcg_temp_new_i64();
2828 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2832 tcg_temp_free_i64(t64
);
2834 case GET_ASI_DIRECT
:
2835 gen_address_mask(dc
, addr
);
2836 tcg_gen_qemu_ld_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2840 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2841 TCGv_i32 r_mop
= tcg_const_i32(MO_Q
);
2844 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2845 tcg_temp_free_i32(r_mop
);
2846 tcg_temp_free_i32(r_asi
);
2851 tcg_gen_extr_i64_i32(lo
, hi
, t64
);
2852 tcg_temp_free_i64(t64
);
2853 gen_store_gpr(dc
, rd
| 1, lo
);
2854 gen_store_gpr(dc
, rd
, hi
);
2857 static void gen_stda_asi(DisasContext
*dc
, TCGv hi
, TCGv addr
,
2860 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2861 TCGv lo
= gen_load_gpr(dc
, rd
+ 1);
2862 TCGv_i64 t64
= tcg_temp_new_i64();
2864 tcg_gen_concat_tl_i64(t64
, lo
, hi
);
2869 case GET_ASI_DIRECT
:
2870 gen_address_mask(dc
, addr
);
2871 tcg_gen_qemu_st_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2874 /* Store 32 bytes of T64 to ADDR. */
2875 /* ??? The original qemu code suggests 8-byte alignment, dropping
2876 the low bits, but the only place I can see this used is in the
2877 Linux kernel with 32 byte alignment, which would make more sense
2878 as a cacheline-style operation. */
2880 TCGv d_addr
= tcg_temp_new();
2881 TCGv eight
= tcg_const_tl(8);
2884 tcg_gen_andi_tl(d_addr
, addr
, -8);
2885 for (i
= 0; i
< 32; i
+= 8) {
2886 tcg_gen_qemu_st_i64(t64
, d_addr
, da
.mem_idx
, da
.memop
);
2887 tcg_gen_add_tl(d_addr
, d_addr
, eight
);
2890 tcg_temp_free(d_addr
);
2891 tcg_temp_free(eight
);
2896 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2897 TCGv_i32 r_mop
= tcg_const_i32(MO_Q
);
2900 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2901 tcg_temp_free_i32(r_mop
);
2902 tcg_temp_free_i32(r_asi
);
2907 tcg_temp_free_i64(t64
);
2911 static TCGv
get_src1(DisasContext
*dc
, unsigned int insn
)
2913 unsigned int rs1
= GET_FIELD(insn
, 13, 17);
2914 return gen_load_gpr(dc
, rs1
);
2917 static TCGv
get_src2(DisasContext
*dc
, unsigned int insn
)
2919 if (IS_IMM
) { /* immediate */
2920 target_long simm
= GET_FIELDs(insn
, 19, 31);
2921 TCGv t
= get_temp_tl(dc
);
2922 tcg_gen_movi_tl(t
, simm
);
2924 } else { /* register */
2925 unsigned int rs2
= GET_FIELD(insn
, 27, 31);
2926 return gen_load_gpr(dc
, rs2
);
2930 #ifdef TARGET_SPARC64
2931 static void gen_fmovs(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2933 TCGv_i32 c32
, zero
, dst
, s1
, s2
;
2935 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2936 or fold the comparison down to 32 bits and use movcond_i32. Choose
2938 c32
= tcg_temp_new_i32();
2940 tcg_gen_extrl_i64_i32(c32
, cmp
->c1
);
2942 TCGv_i64 c64
= tcg_temp_new_i64();
2943 tcg_gen_setcond_i64(cmp
->cond
, c64
, cmp
->c1
, cmp
->c2
);
2944 tcg_gen_extrl_i64_i32(c32
, c64
);
2945 tcg_temp_free_i64(c64
);
2948 s1
= gen_load_fpr_F(dc
, rs
);
2949 s2
= gen_load_fpr_F(dc
, rd
);
2950 dst
= gen_dest_fpr_F(dc
);
2951 zero
= tcg_const_i32(0);
2953 tcg_gen_movcond_i32(TCG_COND_NE
, dst
, c32
, zero
, s1
, s2
);
2955 tcg_temp_free_i32(c32
);
2956 tcg_temp_free_i32(zero
);
2957 gen_store_fpr_F(dc
, rd
, dst
);
2960 static void gen_fmovd(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2962 TCGv_i64 dst
= gen_dest_fpr_D(dc
, rd
);
2963 tcg_gen_movcond_i64(cmp
->cond
, dst
, cmp
->c1
, cmp
->c2
,
2964 gen_load_fpr_D(dc
, rs
),
2965 gen_load_fpr_D(dc
, rd
));
2966 gen_store_fpr_D(dc
, rd
, dst
);
2969 static void gen_fmovq(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2971 int qd
= QFPREG(rd
);
2972 int qs
= QFPREG(rs
);
2974 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2], cmp
->c1
, cmp
->c2
,
2975 cpu_fpr
[qs
/ 2], cpu_fpr
[qd
/ 2]);
2976 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2 + 1], cmp
->c1
, cmp
->c2
,
2977 cpu_fpr
[qs
/ 2 + 1], cpu_fpr
[qd
/ 2 + 1]);
2979 gen_update_fprs_dirty(dc
, qd
);
2982 #ifndef CONFIG_USER_ONLY
2983 static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr
, TCGv_env cpu_env
)
2985 TCGv_i32 r_tl
= tcg_temp_new_i32();
2987 /* load env->tl into r_tl */
2988 tcg_gen_ld_i32(r_tl
, cpu_env
, offsetof(CPUSPARCState
, tl
));
2990 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2991 tcg_gen_andi_i32(r_tl
, r_tl
, MAXTL_MASK
);
2993 /* calculate offset to current trap state from env->ts, reuse r_tl */
2994 tcg_gen_muli_i32(r_tl
, r_tl
, sizeof (trap_state
));
2995 tcg_gen_addi_ptr(r_tsptr
, cpu_env
, offsetof(CPUSPARCState
, ts
));
2997 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2999 TCGv_ptr r_tl_tmp
= tcg_temp_new_ptr();
3000 tcg_gen_ext_i32_ptr(r_tl_tmp
, r_tl
);
3001 tcg_gen_add_ptr(r_tsptr
, r_tsptr
, r_tl_tmp
);
3002 tcg_temp_free_ptr(r_tl_tmp
);
3005 tcg_temp_free_i32(r_tl
);
3009 static void gen_edge(DisasContext
*dc
, TCGv dst
, TCGv s1
, TCGv s2
,
3010 int width
, bool cc
, bool left
)
3012 TCGv lo1
, lo2
, t1
, t2
;
3013 uint64_t amask
, tabl
, tabr
;
3014 int shift
, imask
, omask
;
3017 tcg_gen_mov_tl(cpu_cc_src
, s1
);
3018 tcg_gen_mov_tl(cpu_cc_src2
, s2
);
3019 tcg_gen_sub_tl(cpu_cc_dst
, s1
, s2
);
3020 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUB
);
3021 dc
->cc_op
= CC_OP_SUB
;
3024 /* Theory of operation: there are two tables, left and right (not to
3025 be confused with the left and right versions of the opcode). These
3026 are indexed by the low 3 bits of the inputs. To make things "easy",
3027 these tables are loaded into two constants, TABL and TABR below.
3028 The operation index = (input & imask) << shift calculates the index
3029 into the constant, while val = (table >> index) & omask calculates
3030 the value we're looking for. */
3037 tabl
= 0x80c0e0f0f8fcfeffULL
;
3038 tabr
= 0xff7f3f1f0f070301ULL
;
3040 tabl
= 0x0103070f1f3f7fffULL
;
3041 tabr
= 0xfffefcf8f0e0c080ULL
;
3061 tabl
= (2 << 2) | 3;
3062 tabr
= (3 << 2) | 1;
3064 tabl
= (1 << 2) | 3;
3065 tabr
= (3 << 2) | 2;
3072 lo1
= tcg_temp_new();
3073 lo2
= tcg_temp_new();
3074 tcg_gen_andi_tl(lo1
, s1
, imask
);
3075 tcg_gen_andi_tl(lo2
, s2
, imask
);
3076 tcg_gen_shli_tl(lo1
, lo1
, shift
);
3077 tcg_gen_shli_tl(lo2
, lo2
, shift
);
3079 t1
= tcg_const_tl(tabl
);
3080 t2
= tcg_const_tl(tabr
);
3081 tcg_gen_shr_tl(lo1
, t1
, lo1
);
3082 tcg_gen_shr_tl(lo2
, t2
, lo2
);
3083 tcg_gen_andi_tl(dst
, lo1
, omask
);
3084 tcg_gen_andi_tl(lo2
, lo2
, omask
);
3088 amask
&= 0xffffffffULL
;
3090 tcg_gen_andi_tl(s1
, s1
, amask
);
3091 tcg_gen_andi_tl(s2
, s2
, amask
);
3093 /* We want to compute
3094 dst = (s1 == s2 ? lo1 : lo1 & lo2).
3095 We've already done dst = lo1, so this reduces to
3096 dst &= (s1 == s2 ? -1 : lo2)
3101 tcg_gen_setcond_tl(TCG_COND_EQ
, t1
, s1
, s2
);
3102 tcg_gen_neg_tl(t1
, t1
);
3103 tcg_gen_or_tl(lo2
, lo2
, t1
);
3104 tcg_gen_and_tl(dst
, dst
, lo2
);
3112 static void gen_alignaddr(TCGv dst
, TCGv s1
, TCGv s2
, bool left
)
3114 TCGv tmp
= tcg_temp_new();
3116 tcg_gen_add_tl(tmp
, s1
, s2
);
3117 tcg_gen_andi_tl(dst
, tmp
, -8);
3119 tcg_gen_neg_tl(tmp
, tmp
);
3121 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, tmp
, 0, 3);
3126 static void gen_faligndata(TCGv dst
, TCGv gsr
, TCGv s1
, TCGv s2
)
3130 t1
= tcg_temp_new();
3131 t2
= tcg_temp_new();
3132 shift
= tcg_temp_new();
3134 tcg_gen_andi_tl(shift
, gsr
, 7);
3135 tcg_gen_shli_tl(shift
, shift
, 3);
3136 tcg_gen_shl_tl(t1
, s1
, shift
);
3138 /* A shift of 64 does not produce 0 in TCG. Divide this into a
3139 shift of (up to 63) followed by a constant shift of 1. */
3140 tcg_gen_xori_tl(shift
, shift
, 63);
3141 tcg_gen_shr_tl(t2
, s2
, shift
);
3142 tcg_gen_shri_tl(t2
, t2
, 1);
3144 tcg_gen_or_tl(dst
, t1
, t2
);
3148 tcg_temp_free(shift
);
3152 #define CHECK_IU_FEATURE(dc, FEATURE) \
3153 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3155 #define CHECK_FPU_FEATURE(dc, FEATURE) \
3156 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3159 /* before an instruction, dc->pc must be static */
3160 static void disas_sparc_insn(DisasContext
* dc
, unsigned int insn
)
3162 unsigned int opc
, rs1
, rs2
, rd
;
3163 TCGv cpu_src1
, cpu_src2
;
3164 TCGv_i32 cpu_src1_32
, cpu_src2_32
, cpu_dst_32
;
3165 TCGv_i64 cpu_src1_64
, cpu_src2_64
, cpu_dst_64
;
3168 opc
= GET_FIELD(insn
, 0, 1);
3169 rd
= GET_FIELD(insn
, 2, 6);
3172 case 0: /* branches/sethi */
3174 unsigned int xop
= GET_FIELD(insn
, 7, 9);
3177 #ifdef TARGET_SPARC64
3178 case 0x1: /* V9 BPcc */
3182 target
= GET_FIELD_SP(insn
, 0, 18);
3183 target
= sign_extend(target
, 19);
3185 cc
= GET_FIELD_SP(insn
, 20, 21);
3187 do_branch(dc
, target
, insn
, 0);
3189 do_branch(dc
, target
, insn
, 1);
3194 case 0x3: /* V9 BPr */
3196 target
= GET_FIELD_SP(insn
, 0, 13) |
3197 (GET_FIELD_SP(insn
, 20, 21) << 14);
3198 target
= sign_extend(target
, 16);
3200 cpu_src1
= get_src1(dc
, insn
);
3201 do_branch_reg(dc
, target
, insn
, cpu_src1
);
3204 case 0x5: /* V9 FBPcc */
3206 int cc
= GET_FIELD_SP(insn
, 20, 21);
3207 if (gen_trap_ifnofpu(dc
)) {
3210 target
= GET_FIELD_SP(insn
, 0, 18);
3211 target
= sign_extend(target
, 19);
3213 do_fbranch(dc
, target
, insn
, cc
);
3217 case 0x7: /* CBN+x */
3222 case 0x2: /* BN+x */
3224 target
= GET_FIELD(insn
, 10, 31);
3225 target
= sign_extend(target
, 22);
3227 do_branch(dc
, target
, insn
, 0);
3230 case 0x6: /* FBN+x */
3232 if (gen_trap_ifnofpu(dc
)) {
3235 target
= GET_FIELD(insn
, 10, 31);
3236 target
= sign_extend(target
, 22);
3238 do_fbranch(dc
, target
, insn
, 0);
3241 case 0x4: /* SETHI */
3242 /* Special-case %g0 because that's the canonical nop. */
3244 uint32_t value
= GET_FIELD(insn
, 10, 31);
3245 TCGv t
= gen_dest_gpr(dc
, rd
);
3246 tcg_gen_movi_tl(t
, value
<< 10);
3247 gen_store_gpr(dc
, rd
, t
);
3250 case 0x0: /* UNIMPL */
3259 target_long target
= GET_FIELDs(insn
, 2, 31) << 2;
3260 TCGv o7
= gen_dest_gpr(dc
, 15);
3262 tcg_gen_movi_tl(o7
, dc
->pc
);
3263 gen_store_gpr(dc
, 15, o7
);
3266 #ifdef TARGET_SPARC64
3267 if (unlikely(AM_CHECK(dc
))) {
3268 target
&= 0xffffffffULL
;
3274 case 2: /* FPU & Logical Operations */
3276 unsigned int xop
= GET_FIELD(insn
, 7, 12);
3277 TCGv cpu_dst
= get_temp_tl(dc
);
3280 if (xop
== 0x3a) { /* generate trap */
3281 int cond
= GET_FIELD(insn
, 3, 6);
3283 TCGLabel
*l1
= NULL
;
3294 /* Conditional trap. */
3296 #ifdef TARGET_SPARC64
3298 int cc
= GET_FIELD_SP(insn
, 11, 12);
3300 gen_compare(&cmp
, 0, cond
, dc
);
3301 } else if (cc
== 2) {
3302 gen_compare(&cmp
, 1, cond
, dc
);
3307 gen_compare(&cmp
, 0, cond
, dc
);
3309 l1
= gen_new_label();
3310 tcg_gen_brcond_tl(tcg_invert_cond(cmp
.cond
),
3311 cmp
.c1
, cmp
.c2
, l1
);
3315 mask
= ((dc
->def
->features
& CPU_FEATURE_HYPV
) && supervisor(dc
)
3316 ? UA2005_HTRAP_MASK
: V8_TRAP_MASK
);
3318 /* Don't use the normal temporaries, as they may well have
3319 gone out of scope with the branch above. While we're
3320 doing that we might as well pre-truncate to 32-bit. */
3321 trap
= tcg_temp_new_i32();
3323 rs1
= GET_FIELD_SP(insn
, 14, 18);
3325 rs2
= GET_FIELD_SP(insn
, 0, 7);
3327 tcg_gen_movi_i32(trap
, (rs2
& mask
) + TT_TRAP
);
3328 /* Signal that the trap value is fully constant. */
3331 TCGv t1
= gen_load_gpr(dc
, rs1
);
3332 tcg_gen_trunc_tl_i32(trap
, t1
);
3333 tcg_gen_addi_i32(trap
, trap
, rs2
);
3337 rs2
= GET_FIELD_SP(insn
, 0, 4);
3338 t1
= gen_load_gpr(dc
, rs1
);
3339 t2
= gen_load_gpr(dc
, rs2
);
3340 tcg_gen_add_tl(t1
, t1
, t2
);
3341 tcg_gen_trunc_tl_i32(trap
, t1
);
3344 tcg_gen_andi_i32(trap
, trap
, mask
);
3345 tcg_gen_addi_i32(trap
, trap
, TT_TRAP
);
3348 gen_helper_raise_exception(cpu_env
, trap
);
3349 tcg_temp_free_i32(trap
);
3352 /* An unconditional trap ends the TB. */
3353 dc
->base
.is_jmp
= DISAS_NORETURN
;
3356 /* A conditional trap falls through to the next insn. */
3360 } else if (xop
== 0x28) {
3361 rs1
= GET_FIELD(insn
, 13, 17);
3364 #ifndef TARGET_SPARC64
3365 case 0x01 ... 0x0e: /* undefined in the SPARCv8
3366 manual, rdy on the microSPARC
3368 case 0x0f: /* stbar in the SPARCv8 manual,
3369 rdy on the microSPARC II */
3370 case 0x10 ... 0x1f: /* implementation-dependent in the
3371 SPARCv8 manual, rdy on the
3374 if (rs1
== 0x11 && dc
->def
->features
& CPU_FEATURE_ASR17
) {
3375 TCGv t
= gen_dest_gpr(dc
, rd
);
3376 /* Read Asr17 for a Leon3 monoprocessor */
3377 tcg_gen_movi_tl(t
, (1 << 8) | (dc
->def
->nwindows
- 1));
3378 gen_store_gpr(dc
, rd
, t
);
3382 gen_store_gpr(dc
, rd
, cpu_y
);
3384 #ifdef TARGET_SPARC64
3385 case 0x2: /* V9 rdccr */
3387 gen_helper_rdccr(cpu_dst
, cpu_env
);
3388 gen_store_gpr(dc
, rd
, cpu_dst
);
3390 case 0x3: /* V9 rdasi */
3391 tcg_gen_movi_tl(cpu_dst
, dc
->asi
);
3392 gen_store_gpr(dc
, rd
, cpu_dst
);
3394 case 0x4: /* V9 rdtick */
3399 r_tickptr
= tcg_temp_new_ptr();
3400 r_const
= tcg_const_i32(dc
->mem_idx
);
3401 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3402 offsetof(CPUSPARCState
, tick
));
3403 gen_helper_tick_get_count(cpu_dst
, cpu_env
, r_tickptr
,
3405 tcg_temp_free_ptr(r_tickptr
);
3406 tcg_temp_free_i32(r_const
);
3407 gen_store_gpr(dc
, rd
, cpu_dst
);
3410 case 0x5: /* V9 rdpc */
3412 TCGv t
= gen_dest_gpr(dc
, rd
);
3413 if (unlikely(AM_CHECK(dc
))) {
3414 tcg_gen_movi_tl(t
, dc
->pc
& 0xffffffffULL
);
3416 tcg_gen_movi_tl(t
, dc
->pc
);
3418 gen_store_gpr(dc
, rd
, t
);
3421 case 0x6: /* V9 rdfprs */
3422 tcg_gen_ext_i32_tl(cpu_dst
, cpu_fprs
);
3423 gen_store_gpr(dc
, rd
, cpu_dst
);
3425 case 0xf: /* V9 membar */
3426 break; /* no effect */
3427 case 0x13: /* Graphics Status */
3428 if (gen_trap_ifnofpu(dc
)) {
3431 gen_store_gpr(dc
, rd
, cpu_gsr
);
3433 case 0x16: /* Softint */
3434 tcg_gen_ld32s_tl(cpu_dst
, cpu_env
,
3435 offsetof(CPUSPARCState
, softint
));
3436 gen_store_gpr(dc
, rd
, cpu_dst
);
3438 case 0x17: /* Tick compare */
3439 gen_store_gpr(dc
, rd
, cpu_tick_cmpr
);
3441 case 0x18: /* System tick */
3446 r_tickptr
= tcg_temp_new_ptr();
3447 r_const
= tcg_const_i32(dc
->mem_idx
);
3448 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3449 offsetof(CPUSPARCState
, stick
));
3450 gen_helper_tick_get_count(cpu_dst
, cpu_env
, r_tickptr
,
3452 tcg_temp_free_ptr(r_tickptr
);
3453 tcg_temp_free_i32(r_const
);
3454 gen_store_gpr(dc
, rd
, cpu_dst
);
3457 case 0x19: /* System tick compare */
3458 gen_store_gpr(dc
, rd
, cpu_stick_cmpr
);
3460 case 0x1a: /* UltraSPARC-T1 Strand status */
3461 /* XXX HYPV check maybe not enough, UA2005 & UA2007 describe
3462 * this ASR as impl. dep
3464 CHECK_IU_FEATURE(dc
, HYPV
);
3466 TCGv t
= gen_dest_gpr(dc
, rd
);
3467 tcg_gen_movi_tl(t
, 1UL);
3468 gen_store_gpr(dc
, rd
, t
);
3471 case 0x10: /* Performance Control */
3472 case 0x11: /* Performance Instrumentation Counter */
3473 case 0x12: /* Dispatch Control */
3474 case 0x14: /* Softint set, WO */
3475 case 0x15: /* Softint clear, WO */
3480 #if !defined(CONFIG_USER_ONLY)
3481 } else if (xop
== 0x29) { /* rdpsr / UA2005 rdhpr */
3482 #ifndef TARGET_SPARC64
3483 if (!supervisor(dc
)) {
3487 gen_helper_rdpsr(cpu_dst
, cpu_env
);
3489 CHECK_IU_FEATURE(dc
, HYPV
);
3490 if (!hypervisor(dc
))
3492 rs1
= GET_FIELD(insn
, 13, 17);
3495 tcg_gen_ld_i64(cpu_dst
, cpu_env
,
3496 offsetof(CPUSPARCState
, hpstate
));
3499 // gen_op_rdhtstate();
3502 tcg_gen_mov_tl(cpu_dst
, cpu_hintp
);
3505 tcg_gen_mov_tl(cpu_dst
, cpu_htba
);
3508 tcg_gen_mov_tl(cpu_dst
, cpu_hver
);
3510 case 31: // hstick_cmpr
3511 tcg_gen_mov_tl(cpu_dst
, cpu_hstick_cmpr
);
3517 gen_store_gpr(dc
, rd
, cpu_dst
);
3519 } else if (xop
== 0x2a) { /* rdwim / V9 rdpr */
3520 if (!supervisor(dc
)) {
3523 cpu_tmp0
= get_temp_tl(dc
);
3524 #ifdef TARGET_SPARC64
3525 rs1
= GET_FIELD(insn
, 13, 17);
3531 r_tsptr
= tcg_temp_new_ptr();
3532 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3533 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3534 offsetof(trap_state
, tpc
));
3535 tcg_temp_free_ptr(r_tsptr
);
3542 r_tsptr
= tcg_temp_new_ptr();
3543 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3544 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3545 offsetof(trap_state
, tnpc
));
3546 tcg_temp_free_ptr(r_tsptr
);
3553 r_tsptr
= tcg_temp_new_ptr();
3554 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3555 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3556 offsetof(trap_state
, tstate
));
3557 tcg_temp_free_ptr(r_tsptr
);
3562 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3564 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3565 tcg_gen_ld32s_tl(cpu_tmp0
, r_tsptr
,
3566 offsetof(trap_state
, tt
));
3567 tcg_temp_free_ptr(r_tsptr
);
3575 r_tickptr
= tcg_temp_new_ptr();
3576 r_const
= tcg_const_i32(dc
->mem_idx
);
3577 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3578 offsetof(CPUSPARCState
, tick
));
3579 gen_helper_tick_get_count(cpu_tmp0
, cpu_env
,
3580 r_tickptr
, r_const
);
3581 tcg_temp_free_ptr(r_tickptr
);
3582 tcg_temp_free_i32(r_const
);
3586 tcg_gen_mov_tl(cpu_tmp0
, cpu_tbr
);
3589 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3590 offsetof(CPUSPARCState
, pstate
));
3593 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3594 offsetof(CPUSPARCState
, tl
));
3597 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3598 offsetof(CPUSPARCState
, psrpil
));
3601 gen_helper_rdcwp(cpu_tmp0
, cpu_env
);
3604 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3605 offsetof(CPUSPARCState
, cansave
));
3607 case 11: // canrestore
3608 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3609 offsetof(CPUSPARCState
, canrestore
));
3611 case 12: // cleanwin
3612 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3613 offsetof(CPUSPARCState
, cleanwin
));
3615 case 13: // otherwin
3616 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3617 offsetof(CPUSPARCState
, otherwin
));
3620 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3621 offsetof(CPUSPARCState
, wstate
));
3623 case 16: // UA2005 gl
3624 CHECK_IU_FEATURE(dc
, GL
);
3625 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3626 offsetof(CPUSPARCState
, gl
));
3628 case 26: // UA2005 strand status
3629 CHECK_IU_FEATURE(dc
, HYPV
);
3630 if (!hypervisor(dc
))
3632 tcg_gen_mov_tl(cpu_tmp0
, cpu_ssr
);
3635 tcg_gen_mov_tl(cpu_tmp0
, cpu_ver
);
3642 tcg_gen_ext_i32_tl(cpu_tmp0
, cpu_wim
);
3644 gen_store_gpr(dc
, rd
, cpu_tmp0
);
3646 } else if (xop
== 0x2b) { /* rdtbr / V9 flushw */
3647 #ifdef TARGET_SPARC64
3648 gen_helper_flushw(cpu_env
);
3650 if (!supervisor(dc
))
3652 gen_store_gpr(dc
, rd
, cpu_tbr
);
3656 } else if (xop
== 0x34) { /* FPU Operations */
3657 if (gen_trap_ifnofpu(dc
)) {
3660 gen_op_clear_ieee_excp_and_FTT();
3661 rs1
= GET_FIELD(insn
, 13, 17);
3662 rs2
= GET_FIELD(insn
, 27, 31);
3663 xop
= GET_FIELD(insn
, 18, 26);
3666 case 0x1: /* fmovs */
3667 cpu_src1_32
= gen_load_fpr_F(dc
, rs2
);
3668 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
3670 case 0x5: /* fnegs */
3671 gen_ne_fop_FF(dc
, rd
, rs2
, gen_helper_fnegs
);
3673 case 0x9: /* fabss */
3674 gen_ne_fop_FF(dc
, rd
, rs2
, gen_helper_fabss
);
3676 case 0x29: /* fsqrts */
3677 CHECK_FPU_FEATURE(dc
, FSQRT
);
3678 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fsqrts
);
3680 case 0x2a: /* fsqrtd */
3681 CHECK_FPU_FEATURE(dc
, FSQRT
);
3682 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fsqrtd
);
3684 case 0x2b: /* fsqrtq */
3685 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3686 gen_fop_QQ(dc
, rd
, rs2
, gen_helper_fsqrtq
);
3688 case 0x41: /* fadds */
3689 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fadds
);
3691 case 0x42: /* faddd */
3692 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_faddd
);
3694 case 0x43: /* faddq */
3695 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3696 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_faddq
);
3698 case 0x45: /* fsubs */
3699 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fsubs
);
3701 case 0x46: /* fsubd */
3702 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fsubd
);
3704 case 0x47: /* fsubq */
3705 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3706 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fsubq
);
3708 case 0x49: /* fmuls */
3709 CHECK_FPU_FEATURE(dc
, FMUL
);
3710 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fmuls
);
3712 case 0x4a: /* fmuld */
3713 CHECK_FPU_FEATURE(dc
, FMUL
);
3714 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld
);
3716 case 0x4b: /* fmulq */
3717 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3718 CHECK_FPU_FEATURE(dc
, FMUL
);
3719 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fmulq
);
3721 case 0x4d: /* fdivs */
3722 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fdivs
);
3724 case 0x4e: /* fdivd */
3725 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fdivd
);
3727 case 0x4f: /* fdivq */
3728 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3729 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fdivq
);
3731 case 0x69: /* fsmuld */
3732 CHECK_FPU_FEATURE(dc
, FSMULD
);
3733 gen_fop_DFF(dc
, rd
, rs1
, rs2
, gen_helper_fsmuld
);
3735 case 0x6e: /* fdmulq */
3736 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3737 gen_fop_QDD(dc
, rd
, rs1
, rs2
, gen_helper_fdmulq
);
3739 case 0xc4: /* fitos */
3740 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fitos
);
3742 case 0xc6: /* fdtos */
3743 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fdtos
);
3745 case 0xc7: /* fqtos */
3746 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3747 gen_fop_FQ(dc
, rd
, rs2
, gen_helper_fqtos
);
3749 case 0xc8: /* fitod */
3750 gen_ne_fop_DF(dc
, rd
, rs2
, gen_helper_fitod
);
3752 case 0xc9: /* fstod */
3753 gen_ne_fop_DF(dc
, rd
, rs2
, gen_helper_fstod
);
3755 case 0xcb: /* fqtod */
3756 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3757 gen_fop_DQ(dc
, rd
, rs2
, gen_helper_fqtod
);
3759 case 0xcc: /* fitoq */
3760 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3761 gen_ne_fop_QF(dc
, rd
, rs2
, gen_helper_fitoq
);
3763 case 0xcd: /* fstoq */
3764 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3765 gen_ne_fop_QF(dc
, rd
, rs2
, gen_helper_fstoq
);
3767 case 0xce: /* fdtoq */
3768 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3769 gen_ne_fop_QD(dc
, rd
, rs2
, gen_helper_fdtoq
);
3771 case 0xd1: /* fstoi */
3772 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fstoi
);
3774 case 0xd2: /* fdtoi */
3775 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fdtoi
);
3777 case 0xd3: /* fqtoi */
3778 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3779 gen_fop_FQ(dc
, rd
, rs2
, gen_helper_fqtoi
);
3781 #ifdef TARGET_SPARC64
3782 case 0x2: /* V9 fmovd */
3783 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
3784 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
3786 case 0x3: /* V9 fmovq */
3787 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3788 gen_move_Q(dc
, rd
, rs2
);
3790 case 0x6: /* V9 fnegd */
3791 gen_ne_fop_DD(dc
, rd
, rs2
, gen_helper_fnegd
);
3793 case 0x7: /* V9 fnegq */
3794 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3795 gen_ne_fop_QQ(dc
, rd
, rs2
, gen_helper_fnegq
);
3797 case 0xa: /* V9 fabsd */
3798 gen_ne_fop_DD(dc
, rd
, rs2
, gen_helper_fabsd
);
3800 case 0xb: /* V9 fabsq */
3801 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3802 gen_ne_fop_QQ(dc
, rd
, rs2
, gen_helper_fabsq
);
3804 case 0x81: /* V9 fstox */
3805 gen_fop_DF(dc
, rd
, rs2
, gen_helper_fstox
);
3807 case 0x82: /* V9 fdtox */
3808 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fdtox
);
3810 case 0x83: /* V9 fqtox */
3811 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3812 gen_fop_DQ(dc
, rd
, rs2
, gen_helper_fqtox
);
3814 case 0x84: /* V9 fxtos */
3815 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fxtos
);
3817 case 0x88: /* V9 fxtod */
3818 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fxtod
);
3820 case 0x8c: /* V9 fxtoq */
3821 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3822 gen_ne_fop_QD(dc
, rd
, rs2
, gen_helper_fxtoq
);
3828 } else if (xop
== 0x35) { /* FPU Operations */
3829 #ifdef TARGET_SPARC64
3832 if (gen_trap_ifnofpu(dc
)) {
3835 gen_op_clear_ieee_excp_and_FTT();
3836 rs1
= GET_FIELD(insn
, 13, 17);
3837 rs2
= GET_FIELD(insn
, 27, 31);
3838 xop
= GET_FIELD(insn
, 18, 26);
3840 #ifdef TARGET_SPARC64
3844 cond = GET_FIELD_SP(insn, 10, 12); \
3845 cpu_src1 = get_src1(dc, insn); \
3846 gen_compare_reg(&cmp, cond, cpu_src1); \
3847 gen_fmov##sz(dc, &cmp, rd, rs2); \
3848 free_compare(&cmp); \
3851 if ((xop
& 0x11f) == 0x005) { /* V9 fmovsr */
3854 } else if ((xop
& 0x11f) == 0x006) { // V9 fmovdr
3857 } else if ((xop
& 0x11f) == 0x007) { // V9 fmovqr
3858 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3865 #ifdef TARGET_SPARC64
3866 #define FMOVCC(fcc, sz) \
3869 cond = GET_FIELD_SP(insn, 14, 17); \
3870 gen_fcompare(&cmp, fcc, cond); \
3871 gen_fmov##sz(dc, &cmp, rd, rs2); \
3872 free_compare(&cmp); \
3875 case 0x001: /* V9 fmovscc %fcc0 */
3878 case 0x002: /* V9 fmovdcc %fcc0 */
3881 case 0x003: /* V9 fmovqcc %fcc0 */
3882 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3885 case 0x041: /* V9 fmovscc %fcc1 */
3888 case 0x042: /* V9 fmovdcc %fcc1 */
3891 case 0x043: /* V9 fmovqcc %fcc1 */
3892 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3895 case 0x081: /* V9 fmovscc %fcc2 */
3898 case 0x082: /* V9 fmovdcc %fcc2 */
3901 case 0x083: /* V9 fmovqcc %fcc2 */
3902 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3905 case 0x0c1: /* V9 fmovscc %fcc3 */
3908 case 0x0c2: /* V9 fmovdcc %fcc3 */
3911 case 0x0c3: /* V9 fmovqcc %fcc3 */
3912 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3916 #define FMOVCC(xcc, sz) \
3919 cond = GET_FIELD_SP(insn, 14, 17); \
3920 gen_compare(&cmp, xcc, cond, dc); \
3921 gen_fmov##sz(dc, &cmp, rd, rs2); \
3922 free_compare(&cmp); \
3925 case 0x101: /* V9 fmovscc %icc */
3928 case 0x102: /* V9 fmovdcc %icc */
3931 case 0x103: /* V9 fmovqcc %icc */
3932 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3935 case 0x181: /* V9 fmovscc %xcc */
3938 case 0x182: /* V9 fmovdcc %xcc */
3941 case 0x183: /* V9 fmovqcc %xcc */
3942 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3947 case 0x51: /* fcmps, V9 %fcc */
3948 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
3949 cpu_src2_32
= gen_load_fpr_F(dc
, rs2
);
3950 gen_op_fcmps(rd
& 3, cpu_src1_32
, cpu_src2_32
);
3952 case 0x52: /* fcmpd, V9 %fcc */
3953 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
3954 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
3955 gen_op_fcmpd(rd
& 3, cpu_src1_64
, cpu_src2_64
);
3957 case 0x53: /* fcmpq, V9 %fcc */
3958 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3959 gen_op_load_fpr_QT0(QFPREG(rs1
));
3960 gen_op_load_fpr_QT1(QFPREG(rs2
));
3961 gen_op_fcmpq(rd
& 3);
3963 case 0x55: /* fcmpes, V9 %fcc */
3964 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
3965 cpu_src2_32
= gen_load_fpr_F(dc
, rs2
);
3966 gen_op_fcmpes(rd
& 3, cpu_src1_32
, cpu_src2_32
);
3968 case 0x56: /* fcmped, V9 %fcc */
3969 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
3970 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
3971 gen_op_fcmped(rd
& 3, cpu_src1_64
, cpu_src2_64
);
3973 case 0x57: /* fcmpeq, V9 %fcc */
3974 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3975 gen_op_load_fpr_QT0(QFPREG(rs1
));
3976 gen_op_load_fpr_QT1(QFPREG(rs2
));
3977 gen_op_fcmpeq(rd
& 3);
3982 } else if (xop
== 0x2) {
3983 TCGv dst
= gen_dest_gpr(dc
, rd
);
3984 rs1
= GET_FIELD(insn
, 13, 17);
3986 /* clr/mov shortcut : or %g0, x, y -> mov x, y */
3987 if (IS_IMM
) { /* immediate */
3988 simm
= GET_FIELDs(insn
, 19, 31);
3989 tcg_gen_movi_tl(dst
, simm
);
3990 gen_store_gpr(dc
, rd
, dst
);
3991 } else { /* register */
3992 rs2
= GET_FIELD(insn
, 27, 31);
3994 tcg_gen_movi_tl(dst
, 0);
3995 gen_store_gpr(dc
, rd
, dst
);
3997 cpu_src2
= gen_load_gpr(dc
, rs2
);
3998 gen_store_gpr(dc
, rd
, cpu_src2
);
4002 cpu_src1
= get_src1(dc
, insn
);
4003 if (IS_IMM
) { /* immediate */
4004 simm
= GET_FIELDs(insn
, 19, 31);
4005 tcg_gen_ori_tl(dst
, cpu_src1
, simm
);
4006 gen_store_gpr(dc
, rd
, dst
);
4007 } else { /* register */
4008 rs2
= GET_FIELD(insn
, 27, 31);
4010 /* mov shortcut: or x, %g0, y -> mov x, y */
4011 gen_store_gpr(dc
, rd
, cpu_src1
);
4013 cpu_src2
= gen_load_gpr(dc
, rs2
);
4014 tcg_gen_or_tl(dst
, cpu_src1
, cpu_src2
);
4015 gen_store_gpr(dc
, rd
, dst
);
4019 #ifdef TARGET_SPARC64
4020 } else if (xop
== 0x25) { /* sll, V9 sllx */
4021 cpu_src1
= get_src1(dc
, insn
);
4022 if (IS_IMM
) { /* immediate */
4023 simm
= GET_FIELDs(insn
, 20, 31);
4024 if (insn
& (1 << 12)) {
4025 tcg_gen_shli_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4027 tcg_gen_shli_i64(cpu_dst
, cpu_src1
, simm
& 0x1f);
4029 } else { /* register */
4030 rs2
= GET_FIELD(insn
, 27, 31);
4031 cpu_src2
= gen_load_gpr(dc
, rs2
);
4032 cpu_tmp0
= get_temp_tl(dc
);
4033 if (insn
& (1 << 12)) {
4034 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4036 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4038 tcg_gen_shl_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4040 gen_store_gpr(dc
, rd
, cpu_dst
);
4041 } else if (xop
== 0x26) { /* srl, V9 srlx */
4042 cpu_src1
= get_src1(dc
, insn
);
4043 if (IS_IMM
) { /* immediate */
4044 simm
= GET_FIELDs(insn
, 20, 31);
4045 if (insn
& (1 << 12)) {
4046 tcg_gen_shri_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4048 tcg_gen_andi_i64(cpu_dst
, cpu_src1
, 0xffffffffULL
);
4049 tcg_gen_shri_i64(cpu_dst
, cpu_dst
, simm
& 0x1f);
4051 } else { /* register */
4052 rs2
= GET_FIELD(insn
, 27, 31);
4053 cpu_src2
= gen_load_gpr(dc
, rs2
);
4054 cpu_tmp0
= get_temp_tl(dc
);
4055 if (insn
& (1 << 12)) {
4056 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4057 tcg_gen_shr_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4059 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4060 tcg_gen_andi_i64(cpu_dst
, cpu_src1
, 0xffffffffULL
);
4061 tcg_gen_shr_i64(cpu_dst
, cpu_dst
, cpu_tmp0
);
4064 gen_store_gpr(dc
, rd
, cpu_dst
);
4065 } else if (xop
== 0x27) { /* sra, V9 srax */
4066 cpu_src1
= get_src1(dc
, insn
);
4067 if (IS_IMM
) { /* immediate */
4068 simm
= GET_FIELDs(insn
, 20, 31);
4069 if (insn
& (1 << 12)) {
4070 tcg_gen_sari_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4072 tcg_gen_ext32s_i64(cpu_dst
, cpu_src1
);
4073 tcg_gen_sari_i64(cpu_dst
, cpu_dst
, simm
& 0x1f);
4075 } else { /* register */
4076 rs2
= GET_FIELD(insn
, 27, 31);
4077 cpu_src2
= gen_load_gpr(dc
, rs2
);
4078 cpu_tmp0
= get_temp_tl(dc
);
4079 if (insn
& (1 << 12)) {
4080 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4081 tcg_gen_sar_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4083 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4084 tcg_gen_ext32s_i64(cpu_dst
, cpu_src1
);
4085 tcg_gen_sar_i64(cpu_dst
, cpu_dst
, cpu_tmp0
);
4088 gen_store_gpr(dc
, rd
, cpu_dst
);
4090 } else if (xop
< 0x36) {
4092 cpu_src1
= get_src1(dc
, insn
);
4093 cpu_src2
= get_src2(dc
, insn
);
4094 switch (xop
& ~0x10) {
4097 gen_op_add_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4098 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADD
);
4099 dc
->cc_op
= CC_OP_ADD
;
4101 tcg_gen_add_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4105 tcg_gen_and_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4107 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4108 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4109 dc
->cc_op
= CC_OP_LOGIC
;
4113 tcg_gen_or_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4115 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4116 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4117 dc
->cc_op
= CC_OP_LOGIC
;
4121 tcg_gen_xor_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4123 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4124 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4125 dc
->cc_op
= CC_OP_LOGIC
;
4130 gen_op_sub_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4131 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUB
);
4132 dc
->cc_op
= CC_OP_SUB
;
4134 tcg_gen_sub_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4137 case 0x5: /* andn */
4138 tcg_gen_andc_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4140 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4141 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4142 dc
->cc_op
= CC_OP_LOGIC
;
4146 tcg_gen_orc_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4148 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4149 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4150 dc
->cc_op
= CC_OP_LOGIC
;
4153 case 0x7: /* xorn */
4154 tcg_gen_eqv_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4156 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4157 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4158 dc
->cc_op
= CC_OP_LOGIC
;
4161 case 0x8: /* addx, V9 addc */
4162 gen_op_addx_int(dc
, cpu_dst
, cpu_src1
, cpu_src2
,
4165 #ifdef TARGET_SPARC64
4166 case 0x9: /* V9 mulx */
4167 tcg_gen_mul_i64(cpu_dst
, cpu_src1
, cpu_src2
);
4170 case 0xa: /* umul */
4171 CHECK_IU_FEATURE(dc
, MUL
);
4172 gen_op_umul(cpu_dst
, cpu_src1
, cpu_src2
);
4174 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4175 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4176 dc
->cc_op
= CC_OP_LOGIC
;
4179 case 0xb: /* smul */
4180 CHECK_IU_FEATURE(dc
, MUL
);
4181 gen_op_smul(cpu_dst
, cpu_src1
, cpu_src2
);
4183 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4184 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4185 dc
->cc_op
= CC_OP_LOGIC
;
4188 case 0xc: /* subx, V9 subc */
4189 gen_op_subx_int(dc
, cpu_dst
, cpu_src1
, cpu_src2
,
4192 #ifdef TARGET_SPARC64
4193 case 0xd: /* V9 udivx */
4194 gen_helper_udivx(cpu_dst
, cpu_env
, cpu_src1
, cpu_src2
);
4197 case 0xe: /* udiv */
4198 CHECK_IU_FEATURE(dc
, DIV
);
4200 gen_helper_udiv_cc(cpu_dst
, cpu_env
, cpu_src1
,
4202 dc
->cc_op
= CC_OP_DIV
;
4204 gen_helper_udiv(cpu_dst
, cpu_env
, cpu_src1
,
4208 case 0xf: /* sdiv */
4209 CHECK_IU_FEATURE(dc
, DIV
);
4211 gen_helper_sdiv_cc(cpu_dst
, cpu_env
, cpu_src1
,
4213 dc
->cc_op
= CC_OP_DIV
;
4215 gen_helper_sdiv(cpu_dst
, cpu_env
, cpu_src1
,
4222 gen_store_gpr(dc
, rd
, cpu_dst
);
4224 cpu_src1
= get_src1(dc
, insn
);
4225 cpu_src2
= get_src2(dc
, insn
);
4227 case 0x20: /* taddcc */
4228 gen_op_add_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4229 gen_store_gpr(dc
, rd
, cpu_dst
);
4230 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_TADD
);
4231 dc
->cc_op
= CC_OP_TADD
;
4233 case 0x21: /* tsubcc */
4234 gen_op_sub_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4235 gen_store_gpr(dc
, rd
, cpu_dst
);
4236 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_TSUB
);
4237 dc
->cc_op
= CC_OP_TSUB
;
4239 case 0x22: /* taddcctv */
4240 gen_helper_taddcctv(cpu_dst
, cpu_env
,
4241 cpu_src1
, cpu_src2
);
4242 gen_store_gpr(dc
, rd
, cpu_dst
);
4243 dc
->cc_op
= CC_OP_TADDTV
;
4245 case 0x23: /* tsubcctv */
4246 gen_helper_tsubcctv(cpu_dst
, cpu_env
,
4247 cpu_src1
, cpu_src2
);
4248 gen_store_gpr(dc
, rd
, cpu_dst
);
4249 dc
->cc_op
= CC_OP_TSUBTV
;
4251 case 0x24: /* mulscc */
4253 gen_op_mulscc(cpu_dst
, cpu_src1
, cpu_src2
);
4254 gen_store_gpr(dc
, rd
, cpu_dst
);
4255 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADD
);
4256 dc
->cc_op
= CC_OP_ADD
;
4258 #ifndef TARGET_SPARC64
4259 case 0x25: /* sll */
4260 if (IS_IMM
) { /* immediate */
4261 simm
= GET_FIELDs(insn
, 20, 31);
4262 tcg_gen_shli_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4263 } else { /* register */
4264 cpu_tmp0
= get_temp_tl(dc
);
4265 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4266 tcg_gen_shl_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4268 gen_store_gpr(dc
, rd
, cpu_dst
);
4270 case 0x26: /* srl */
4271 if (IS_IMM
) { /* immediate */
4272 simm
= GET_FIELDs(insn
, 20, 31);
4273 tcg_gen_shri_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4274 } else { /* register */
4275 cpu_tmp0
= get_temp_tl(dc
);
4276 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4277 tcg_gen_shr_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4279 gen_store_gpr(dc
, rd
, cpu_dst
);
4281 case 0x27: /* sra */
4282 if (IS_IMM
) { /* immediate */
4283 simm
= GET_FIELDs(insn
, 20, 31);
4284 tcg_gen_sari_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4285 } else { /* register */
4286 cpu_tmp0
= get_temp_tl(dc
);
4287 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4288 tcg_gen_sar_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4290 gen_store_gpr(dc
, rd
, cpu_dst
);
4295 cpu_tmp0
= get_temp_tl(dc
);
4298 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4299 tcg_gen_andi_tl(cpu_y
, cpu_tmp0
, 0xffffffff);
4301 #ifndef TARGET_SPARC64
4302 case 0x01 ... 0x0f: /* undefined in the
4306 case 0x10 ... 0x1f: /* implementation-dependent
4310 if ((rd
== 0x13) && (dc
->def
->features
&
4311 CPU_FEATURE_POWERDOWN
)) {
4312 /* LEON3 power-down */
4314 gen_helper_power_down(cpu_env
);
4318 case 0x2: /* V9 wrccr */
4319 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4320 gen_helper_wrccr(cpu_env
, cpu_tmp0
);
4321 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_FLAGS
);
4322 dc
->cc_op
= CC_OP_FLAGS
;
4324 case 0x3: /* V9 wrasi */
4325 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4326 tcg_gen_andi_tl(cpu_tmp0
, cpu_tmp0
, 0xff);
4327 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4328 offsetof(CPUSPARCState
, asi
));
4329 /* End TB to notice changed ASI. */
4333 dc
->base
.is_jmp
= DISAS_NORETURN
;
4335 case 0x6: /* V9 wrfprs */
4336 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4337 tcg_gen_trunc_tl_i32(cpu_fprs
, cpu_tmp0
);
4342 dc
->base
.is_jmp
= DISAS_NORETURN
;
4344 case 0xf: /* V9 sir, nop if user */
4345 #if !defined(CONFIG_USER_ONLY)
4346 if (supervisor(dc
)) {
4351 case 0x13: /* Graphics Status */
4352 if (gen_trap_ifnofpu(dc
)) {
4355 tcg_gen_xor_tl(cpu_gsr
, cpu_src1
, cpu_src2
);
4357 case 0x14: /* Softint set */
4358 if (!supervisor(dc
))
4360 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4361 gen_helper_set_softint(cpu_env
, cpu_tmp0
);
4363 case 0x15: /* Softint clear */
4364 if (!supervisor(dc
))
4366 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4367 gen_helper_clear_softint(cpu_env
, cpu_tmp0
);
4369 case 0x16: /* Softint write */
4370 if (!supervisor(dc
))
4372 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4373 gen_helper_write_softint(cpu_env
, cpu_tmp0
);
4375 case 0x17: /* Tick compare */
4376 #if !defined(CONFIG_USER_ONLY)
4377 if (!supervisor(dc
))
4383 tcg_gen_xor_tl(cpu_tick_cmpr
, cpu_src1
,
4385 r_tickptr
= tcg_temp_new_ptr();
4386 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4387 offsetof(CPUSPARCState
, tick
));
4388 gen_helper_tick_set_limit(r_tickptr
,
4390 tcg_temp_free_ptr(r_tickptr
);
4393 case 0x18: /* System tick */
4394 #if !defined(CONFIG_USER_ONLY)
4395 if (!supervisor(dc
))
4401 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
,
4403 r_tickptr
= tcg_temp_new_ptr();
4404 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4405 offsetof(CPUSPARCState
, stick
));
4406 gen_helper_tick_set_count(r_tickptr
,
4408 tcg_temp_free_ptr(r_tickptr
);
4411 case 0x19: /* System tick compare */
4412 #if !defined(CONFIG_USER_ONLY)
4413 if (!supervisor(dc
))
4419 tcg_gen_xor_tl(cpu_stick_cmpr
, cpu_src1
,
4421 r_tickptr
= tcg_temp_new_ptr();
4422 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4423 offsetof(CPUSPARCState
, stick
));
4424 gen_helper_tick_set_limit(r_tickptr
,
4426 tcg_temp_free_ptr(r_tickptr
);
4430 case 0x10: /* Performance Control */
4431 case 0x11: /* Performance Instrumentation
4433 case 0x12: /* Dispatch Control */
4440 #if !defined(CONFIG_USER_ONLY)
4441 case 0x31: /* wrpsr, V9 saved, restored */
4443 if (!supervisor(dc
))
4445 #ifdef TARGET_SPARC64
4448 gen_helper_saved(cpu_env
);
4451 gen_helper_restored(cpu_env
);
4453 case 2: /* UA2005 allclean */
4454 case 3: /* UA2005 otherw */
4455 case 4: /* UA2005 normalw */
4456 case 5: /* UA2005 invalw */
4462 cpu_tmp0
= get_temp_tl(dc
);
4463 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4464 gen_helper_wrpsr(cpu_env
, cpu_tmp0
);
4465 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_FLAGS
);
4466 dc
->cc_op
= CC_OP_FLAGS
;
4470 dc
->base
.is_jmp
= DISAS_NORETURN
;
4474 case 0x32: /* wrwim, V9 wrpr */
4476 if (!supervisor(dc
))
4478 cpu_tmp0
= get_temp_tl(dc
);
4479 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4480 #ifdef TARGET_SPARC64
4486 r_tsptr
= tcg_temp_new_ptr();
4487 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4488 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4489 offsetof(trap_state
, tpc
));
4490 tcg_temp_free_ptr(r_tsptr
);
4497 r_tsptr
= tcg_temp_new_ptr();
4498 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4499 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4500 offsetof(trap_state
, tnpc
));
4501 tcg_temp_free_ptr(r_tsptr
);
4508 r_tsptr
= tcg_temp_new_ptr();
4509 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4510 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4511 offsetof(trap_state
,
4513 tcg_temp_free_ptr(r_tsptr
);
4520 r_tsptr
= tcg_temp_new_ptr();
4521 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4522 tcg_gen_st32_tl(cpu_tmp0
, r_tsptr
,
4523 offsetof(trap_state
, tt
));
4524 tcg_temp_free_ptr(r_tsptr
);
4531 r_tickptr
= tcg_temp_new_ptr();
4532 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4533 offsetof(CPUSPARCState
, tick
));
4534 gen_helper_tick_set_count(r_tickptr
,
4536 tcg_temp_free_ptr(r_tickptr
);
4540 tcg_gen_mov_tl(cpu_tbr
, cpu_tmp0
);
4544 gen_helper_wrpstate(cpu_env
, cpu_tmp0
);
4545 dc
->npc
= DYNAMIC_PC
;
4549 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4550 offsetof(CPUSPARCState
, tl
));
4551 dc
->npc
= DYNAMIC_PC
;
4554 gen_helper_wrpil(cpu_env
, cpu_tmp0
);
4557 gen_helper_wrcwp(cpu_env
, cpu_tmp0
);
4560 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4561 offsetof(CPUSPARCState
,
4564 case 11: // canrestore
4565 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4566 offsetof(CPUSPARCState
,
4569 case 12: // cleanwin
4570 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4571 offsetof(CPUSPARCState
,
4574 case 13: // otherwin
4575 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4576 offsetof(CPUSPARCState
,
4580 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4581 offsetof(CPUSPARCState
,
4584 case 16: // UA2005 gl
4585 CHECK_IU_FEATURE(dc
, GL
);
4586 gen_helper_wrgl(cpu_env
, cpu_tmp0
);
4588 case 26: // UA2005 strand status
4589 CHECK_IU_FEATURE(dc
, HYPV
);
4590 if (!hypervisor(dc
))
4592 tcg_gen_mov_tl(cpu_ssr
, cpu_tmp0
);
4598 tcg_gen_trunc_tl_i32(cpu_wim
, cpu_tmp0
);
4599 if (dc
->def
->nwindows
!= 32) {
4600 tcg_gen_andi_tl(cpu_wim
, cpu_wim
,
4601 (1 << dc
->def
->nwindows
) - 1);
4606 case 0x33: /* wrtbr, UA2005 wrhpr */
4608 #ifndef TARGET_SPARC64
4609 if (!supervisor(dc
))
4611 tcg_gen_xor_tl(cpu_tbr
, cpu_src1
, cpu_src2
);
4613 CHECK_IU_FEATURE(dc
, HYPV
);
4614 if (!hypervisor(dc
))
4616 cpu_tmp0
= get_temp_tl(dc
);
4617 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4620 tcg_gen_st_i64(cpu_tmp0
, cpu_env
,
4621 offsetof(CPUSPARCState
,
4626 dc
->base
.is_jmp
= DISAS_NORETURN
;
4629 // XXX gen_op_wrhtstate();
4632 tcg_gen_mov_tl(cpu_hintp
, cpu_tmp0
);
4635 tcg_gen_mov_tl(cpu_htba
, cpu_tmp0
);
4637 case 31: // hstick_cmpr
4641 tcg_gen_mov_tl(cpu_hstick_cmpr
, cpu_tmp0
);
4642 r_tickptr
= tcg_temp_new_ptr();
4643 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4644 offsetof(CPUSPARCState
, hstick
));
4645 gen_helper_tick_set_limit(r_tickptr
,
4647 tcg_temp_free_ptr(r_tickptr
);
4650 case 6: // hver readonly
4658 #ifdef TARGET_SPARC64
4659 case 0x2c: /* V9 movcc */
4661 int cc
= GET_FIELD_SP(insn
, 11, 12);
4662 int cond
= GET_FIELD_SP(insn
, 14, 17);
4666 if (insn
& (1 << 18)) {
4668 gen_compare(&cmp
, 0, cond
, dc
);
4669 } else if (cc
== 2) {
4670 gen_compare(&cmp
, 1, cond
, dc
);
4675 gen_fcompare(&cmp
, cc
, cond
);
4678 /* The get_src2 above loaded the normal 13-bit
4679 immediate field, not the 11-bit field we have
4680 in movcc. But it did handle the reg case. */
4682 simm
= GET_FIELD_SPs(insn
, 0, 10);
4683 tcg_gen_movi_tl(cpu_src2
, simm
);
4686 dst
= gen_load_gpr(dc
, rd
);
4687 tcg_gen_movcond_tl(cmp
.cond
, dst
,
4691 gen_store_gpr(dc
, rd
, dst
);
4694 case 0x2d: /* V9 sdivx */
4695 gen_helper_sdivx(cpu_dst
, cpu_env
, cpu_src1
, cpu_src2
);
4696 gen_store_gpr(dc
, rd
, cpu_dst
);
4698 case 0x2e: /* V9 popc */
4699 tcg_gen_ctpop_tl(cpu_dst
, cpu_src2
);
4700 gen_store_gpr(dc
, rd
, cpu_dst
);
4702 case 0x2f: /* V9 movr */
4704 int cond
= GET_FIELD_SP(insn
, 10, 12);
4708 gen_compare_reg(&cmp
, cond
, cpu_src1
);
4710 /* The get_src2 above loaded the normal 13-bit
4711 immediate field, not the 10-bit field we have
4712 in movr. But it did handle the reg case. */
4714 simm
= GET_FIELD_SPs(insn
, 0, 9);
4715 tcg_gen_movi_tl(cpu_src2
, simm
);
4718 dst
= gen_load_gpr(dc
, rd
);
4719 tcg_gen_movcond_tl(cmp
.cond
, dst
,
4723 gen_store_gpr(dc
, rd
, dst
);
4731 } else if (xop
== 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4732 #ifdef TARGET_SPARC64
4733 int opf
= GET_FIELD_SP(insn
, 5, 13);
4734 rs1
= GET_FIELD(insn
, 13, 17);
4735 rs2
= GET_FIELD(insn
, 27, 31);
4736 if (gen_trap_ifnofpu(dc
)) {
4741 case 0x000: /* VIS I edge8cc */
4742 CHECK_FPU_FEATURE(dc
, VIS1
);
4743 cpu_src1
= gen_load_gpr(dc
, rs1
);
4744 cpu_src2
= gen_load_gpr(dc
, rs2
);
4745 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 1, 0);
4746 gen_store_gpr(dc
, rd
, cpu_dst
);
4748 case 0x001: /* VIS II edge8n */
4749 CHECK_FPU_FEATURE(dc
, VIS2
);
4750 cpu_src1
= gen_load_gpr(dc
, rs1
);
4751 cpu_src2
= gen_load_gpr(dc
, rs2
);
4752 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 0, 0);
4753 gen_store_gpr(dc
, rd
, cpu_dst
);
4755 case 0x002: /* VIS I edge8lcc */
4756 CHECK_FPU_FEATURE(dc
, VIS1
);
4757 cpu_src1
= gen_load_gpr(dc
, rs1
);
4758 cpu_src2
= gen_load_gpr(dc
, rs2
);
4759 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 1, 1);
4760 gen_store_gpr(dc
, rd
, cpu_dst
);
4762 case 0x003: /* VIS II edge8ln */
4763 CHECK_FPU_FEATURE(dc
, VIS2
);
4764 cpu_src1
= gen_load_gpr(dc
, rs1
);
4765 cpu_src2
= gen_load_gpr(dc
, rs2
);
4766 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 0, 1);
4767 gen_store_gpr(dc
, rd
, cpu_dst
);
4769 case 0x004: /* VIS I edge16cc */
4770 CHECK_FPU_FEATURE(dc
, VIS1
);
4771 cpu_src1
= gen_load_gpr(dc
, rs1
);
4772 cpu_src2
= gen_load_gpr(dc
, rs2
);
4773 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 1, 0);
4774 gen_store_gpr(dc
, rd
, cpu_dst
);
4776 case 0x005: /* VIS II edge16n */
4777 CHECK_FPU_FEATURE(dc
, VIS2
);
4778 cpu_src1
= gen_load_gpr(dc
, rs1
);
4779 cpu_src2
= gen_load_gpr(dc
, rs2
);
4780 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 0, 0);
4781 gen_store_gpr(dc
, rd
, cpu_dst
);
4783 case 0x006: /* VIS I edge16lcc */
4784 CHECK_FPU_FEATURE(dc
, VIS1
);
4785 cpu_src1
= gen_load_gpr(dc
, rs1
);
4786 cpu_src2
= gen_load_gpr(dc
, rs2
);
4787 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 1, 1);
4788 gen_store_gpr(dc
, rd
, cpu_dst
);
4790 case 0x007: /* VIS II edge16ln */
4791 CHECK_FPU_FEATURE(dc
, VIS2
);
4792 cpu_src1
= gen_load_gpr(dc
, rs1
);
4793 cpu_src2
= gen_load_gpr(dc
, rs2
);
4794 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 0, 1);
4795 gen_store_gpr(dc
, rd
, cpu_dst
);
4797 case 0x008: /* VIS I edge32cc */
4798 CHECK_FPU_FEATURE(dc
, VIS1
);
4799 cpu_src1
= gen_load_gpr(dc
, rs1
);
4800 cpu_src2
= gen_load_gpr(dc
, rs2
);
4801 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 1, 0);
4802 gen_store_gpr(dc
, rd
, cpu_dst
);
4804 case 0x009: /* VIS II edge32n */
4805 CHECK_FPU_FEATURE(dc
, VIS2
);
4806 cpu_src1
= gen_load_gpr(dc
, rs1
);
4807 cpu_src2
= gen_load_gpr(dc
, rs2
);
4808 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 0, 0);
4809 gen_store_gpr(dc
, rd
, cpu_dst
);
4811 case 0x00a: /* VIS I edge32lcc */
4812 CHECK_FPU_FEATURE(dc
, VIS1
);
4813 cpu_src1
= gen_load_gpr(dc
, rs1
);
4814 cpu_src2
= gen_load_gpr(dc
, rs2
);
4815 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 1, 1);
4816 gen_store_gpr(dc
, rd
, cpu_dst
);
4818 case 0x00b: /* VIS II edge32ln */
4819 CHECK_FPU_FEATURE(dc
, VIS2
);
4820 cpu_src1
= gen_load_gpr(dc
, rs1
);
4821 cpu_src2
= gen_load_gpr(dc
, rs2
);
4822 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 0, 1);
4823 gen_store_gpr(dc
, rd
, cpu_dst
);
4825 case 0x010: /* VIS I array8 */
4826 CHECK_FPU_FEATURE(dc
, VIS1
);
4827 cpu_src1
= gen_load_gpr(dc
, rs1
);
4828 cpu_src2
= gen_load_gpr(dc
, rs2
);
4829 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4830 gen_store_gpr(dc
, rd
, cpu_dst
);
4832 case 0x012: /* VIS I array16 */
4833 CHECK_FPU_FEATURE(dc
, VIS1
);
4834 cpu_src1
= gen_load_gpr(dc
, rs1
);
4835 cpu_src2
= gen_load_gpr(dc
, rs2
);
4836 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4837 tcg_gen_shli_i64(cpu_dst
, cpu_dst
, 1);
4838 gen_store_gpr(dc
, rd
, cpu_dst
);
4840 case 0x014: /* VIS I array32 */
4841 CHECK_FPU_FEATURE(dc
, VIS1
);
4842 cpu_src1
= gen_load_gpr(dc
, rs1
);
4843 cpu_src2
= gen_load_gpr(dc
, rs2
);
4844 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4845 tcg_gen_shli_i64(cpu_dst
, cpu_dst
, 2);
4846 gen_store_gpr(dc
, rd
, cpu_dst
);
4848 case 0x018: /* VIS I alignaddr */
4849 CHECK_FPU_FEATURE(dc
, VIS1
);
4850 cpu_src1
= gen_load_gpr(dc
, rs1
);
4851 cpu_src2
= gen_load_gpr(dc
, rs2
);
4852 gen_alignaddr(cpu_dst
, cpu_src1
, cpu_src2
, 0);
4853 gen_store_gpr(dc
, rd
, cpu_dst
);
4855 case 0x01a: /* VIS I alignaddrl */
4856 CHECK_FPU_FEATURE(dc
, VIS1
);
4857 cpu_src1
= gen_load_gpr(dc
, rs1
);
4858 cpu_src2
= gen_load_gpr(dc
, rs2
);
4859 gen_alignaddr(cpu_dst
, cpu_src1
, cpu_src2
, 1);
4860 gen_store_gpr(dc
, rd
, cpu_dst
);
4862 case 0x019: /* VIS II bmask */
4863 CHECK_FPU_FEATURE(dc
, VIS2
);
4864 cpu_src1
= gen_load_gpr(dc
, rs1
);
4865 cpu_src2
= gen_load_gpr(dc
, rs2
);
4866 tcg_gen_add_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4867 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, cpu_dst
, 32, 32);
4868 gen_store_gpr(dc
, rd
, cpu_dst
);
4870 case 0x020: /* VIS I fcmple16 */
4871 CHECK_FPU_FEATURE(dc
, VIS1
);
4872 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4873 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4874 gen_helper_fcmple16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4875 gen_store_gpr(dc
, rd
, cpu_dst
);
4877 case 0x022: /* VIS I fcmpne16 */
4878 CHECK_FPU_FEATURE(dc
, VIS1
);
4879 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4880 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4881 gen_helper_fcmpne16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4882 gen_store_gpr(dc
, rd
, cpu_dst
);
4884 case 0x024: /* VIS I fcmple32 */
4885 CHECK_FPU_FEATURE(dc
, VIS1
);
4886 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4887 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4888 gen_helper_fcmple32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4889 gen_store_gpr(dc
, rd
, cpu_dst
);
4891 case 0x026: /* VIS I fcmpne32 */
4892 CHECK_FPU_FEATURE(dc
, VIS1
);
4893 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4894 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4895 gen_helper_fcmpne32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4896 gen_store_gpr(dc
, rd
, cpu_dst
);
4898 case 0x028: /* VIS I fcmpgt16 */
4899 CHECK_FPU_FEATURE(dc
, VIS1
);
4900 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4901 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4902 gen_helper_fcmpgt16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4903 gen_store_gpr(dc
, rd
, cpu_dst
);
4905 case 0x02a: /* VIS I fcmpeq16 */
4906 CHECK_FPU_FEATURE(dc
, VIS1
);
4907 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4908 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4909 gen_helper_fcmpeq16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4910 gen_store_gpr(dc
, rd
, cpu_dst
);
4912 case 0x02c: /* VIS I fcmpgt32 */
4913 CHECK_FPU_FEATURE(dc
, VIS1
);
4914 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4915 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4916 gen_helper_fcmpgt32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4917 gen_store_gpr(dc
, rd
, cpu_dst
);
4919 case 0x02e: /* VIS I fcmpeq32 */
4920 CHECK_FPU_FEATURE(dc
, VIS1
);
4921 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4922 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4923 gen_helper_fcmpeq32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4924 gen_store_gpr(dc
, rd
, cpu_dst
);
4926 case 0x031: /* VIS I fmul8x16 */
4927 CHECK_FPU_FEATURE(dc
, VIS1
);
4928 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16
);
4930 case 0x033: /* VIS I fmul8x16au */
4931 CHECK_FPU_FEATURE(dc
, VIS1
);
4932 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16au
);
4934 case 0x035: /* VIS I fmul8x16al */
4935 CHECK_FPU_FEATURE(dc
, VIS1
);
4936 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16al
);
4938 case 0x036: /* VIS I fmul8sux16 */
4939 CHECK_FPU_FEATURE(dc
, VIS1
);
4940 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8sux16
);
4942 case 0x037: /* VIS I fmul8ulx16 */
4943 CHECK_FPU_FEATURE(dc
, VIS1
);
4944 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8ulx16
);
4946 case 0x038: /* VIS I fmuld8sux16 */
4947 CHECK_FPU_FEATURE(dc
, VIS1
);
4948 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld8sux16
);
4950 case 0x039: /* VIS I fmuld8ulx16 */
4951 CHECK_FPU_FEATURE(dc
, VIS1
);
4952 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld8ulx16
);
4954 case 0x03a: /* VIS I fpack32 */
4955 CHECK_FPU_FEATURE(dc
, VIS1
);
4956 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpack32
);
4958 case 0x03b: /* VIS I fpack16 */
4959 CHECK_FPU_FEATURE(dc
, VIS1
);
4960 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
4961 cpu_dst_32
= gen_dest_fpr_F(dc
);
4962 gen_helper_fpack16(cpu_dst_32
, cpu_gsr
, cpu_src1_64
);
4963 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
4965 case 0x03d: /* VIS I fpackfix */
4966 CHECK_FPU_FEATURE(dc
, VIS1
);
4967 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
4968 cpu_dst_32
= gen_dest_fpr_F(dc
);
4969 gen_helper_fpackfix(cpu_dst_32
, cpu_gsr
, cpu_src1_64
);
4970 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
4972 case 0x03e: /* VIS I pdist */
4973 CHECK_FPU_FEATURE(dc
, VIS1
);
4974 gen_ne_fop_DDDD(dc
, rd
, rs1
, rs2
, gen_helper_pdist
);
4976 case 0x048: /* VIS I faligndata */
4977 CHECK_FPU_FEATURE(dc
, VIS1
);
4978 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_faligndata
);
4980 case 0x04b: /* VIS I fpmerge */
4981 CHECK_FPU_FEATURE(dc
, VIS1
);
4982 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpmerge
);
4984 case 0x04c: /* VIS II bshuffle */
4985 CHECK_FPU_FEATURE(dc
, VIS2
);
4986 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_bshuffle
);
4988 case 0x04d: /* VIS I fexpand */
4989 CHECK_FPU_FEATURE(dc
, VIS1
);
4990 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fexpand
);
4992 case 0x050: /* VIS I fpadd16 */
4993 CHECK_FPU_FEATURE(dc
, VIS1
);
4994 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpadd16
);
4996 case 0x051: /* VIS I fpadd16s */
4997 CHECK_FPU_FEATURE(dc
, VIS1
);
4998 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fpadd16s
);
5000 case 0x052: /* VIS I fpadd32 */
5001 CHECK_FPU_FEATURE(dc
, VIS1
);
5002 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpadd32
);
5004 case 0x053: /* VIS I fpadd32s */
5005 CHECK_FPU_FEATURE(dc
, VIS1
);
5006 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_add_i32
);
5008 case 0x054: /* VIS I fpsub16 */
5009 CHECK_FPU_FEATURE(dc
, VIS1
);
5010 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpsub16
);
5012 case 0x055: /* VIS I fpsub16s */
5013 CHECK_FPU_FEATURE(dc
, VIS1
);
5014 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fpsub16s
);
5016 case 0x056: /* VIS I fpsub32 */
5017 CHECK_FPU_FEATURE(dc
, VIS1
);
5018 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpsub32
);
5020 case 0x057: /* VIS I fpsub32s */
5021 CHECK_FPU_FEATURE(dc
, VIS1
);
5022 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_sub_i32
);
5024 case 0x060: /* VIS I fzero */
5025 CHECK_FPU_FEATURE(dc
, VIS1
);
5026 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5027 tcg_gen_movi_i64(cpu_dst_64
, 0);
5028 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5030 case 0x061: /* VIS I fzeros */
5031 CHECK_FPU_FEATURE(dc
, VIS1
);
5032 cpu_dst_32
= gen_dest_fpr_F(dc
);
5033 tcg_gen_movi_i32(cpu_dst_32
, 0);
5034 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5036 case 0x062: /* VIS I fnor */
5037 CHECK_FPU_FEATURE(dc
, VIS1
);
5038 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_nor_i64
);
5040 case 0x063: /* VIS I fnors */
5041 CHECK_FPU_FEATURE(dc
, VIS1
);
5042 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_nor_i32
);
5044 case 0x064: /* VIS I fandnot2 */
5045 CHECK_FPU_FEATURE(dc
, VIS1
);
5046 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_andc_i64
);
5048 case 0x065: /* VIS I fandnot2s */
5049 CHECK_FPU_FEATURE(dc
, VIS1
);
5050 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_andc_i32
);
5052 case 0x066: /* VIS I fnot2 */
5053 CHECK_FPU_FEATURE(dc
, VIS1
);
5054 gen_ne_fop_DD(dc
, rd
, rs2
, tcg_gen_not_i64
);
5056 case 0x067: /* VIS I fnot2s */
5057 CHECK_FPU_FEATURE(dc
, VIS1
);
5058 gen_ne_fop_FF(dc
, rd
, rs2
, tcg_gen_not_i32
);
5060 case 0x068: /* VIS I fandnot1 */
5061 CHECK_FPU_FEATURE(dc
, VIS1
);
5062 gen_ne_fop_DDD(dc
, rd
, rs2
, rs1
, tcg_gen_andc_i64
);
5064 case 0x069: /* VIS I fandnot1s */
5065 CHECK_FPU_FEATURE(dc
, VIS1
);
5066 gen_ne_fop_FFF(dc
, rd
, rs2
, rs1
, tcg_gen_andc_i32
);
5068 case 0x06a: /* VIS I fnot1 */
5069 CHECK_FPU_FEATURE(dc
, VIS1
);
5070 gen_ne_fop_DD(dc
, rd
, rs1
, tcg_gen_not_i64
);
5072 case 0x06b: /* VIS I fnot1s */
5073 CHECK_FPU_FEATURE(dc
, VIS1
);
5074 gen_ne_fop_FF(dc
, rd
, rs1
, tcg_gen_not_i32
);
5076 case 0x06c: /* VIS I fxor */
5077 CHECK_FPU_FEATURE(dc
, VIS1
);
5078 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_xor_i64
);
5080 case 0x06d: /* VIS I fxors */
5081 CHECK_FPU_FEATURE(dc
, VIS1
);
5082 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_xor_i32
);
5084 case 0x06e: /* VIS I fnand */
5085 CHECK_FPU_FEATURE(dc
, VIS1
);
5086 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_nand_i64
);
5088 case 0x06f: /* VIS I fnands */
5089 CHECK_FPU_FEATURE(dc
, VIS1
);
5090 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_nand_i32
);
5092 case 0x070: /* VIS I fand */
5093 CHECK_FPU_FEATURE(dc
, VIS1
);
5094 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_and_i64
);
5096 case 0x071: /* VIS I fands */
5097 CHECK_FPU_FEATURE(dc
, VIS1
);
5098 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_and_i32
);
5100 case 0x072: /* VIS I fxnor */
5101 CHECK_FPU_FEATURE(dc
, VIS1
);
5102 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_eqv_i64
);
5104 case 0x073: /* VIS I fxnors */
5105 CHECK_FPU_FEATURE(dc
, VIS1
);
5106 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_eqv_i32
);
5108 case 0x074: /* VIS I fsrc1 */
5109 CHECK_FPU_FEATURE(dc
, VIS1
);
5110 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
5111 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
5113 case 0x075: /* VIS I fsrc1s */
5114 CHECK_FPU_FEATURE(dc
, VIS1
);
5115 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
5116 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
5118 case 0x076: /* VIS I fornot2 */
5119 CHECK_FPU_FEATURE(dc
, VIS1
);
5120 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_orc_i64
);
5122 case 0x077: /* VIS I fornot2s */
5123 CHECK_FPU_FEATURE(dc
, VIS1
);
5124 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_orc_i32
);
5126 case 0x078: /* VIS I fsrc2 */
5127 CHECK_FPU_FEATURE(dc
, VIS1
);
5128 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
5129 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
5131 case 0x079: /* VIS I fsrc2s */
5132 CHECK_FPU_FEATURE(dc
, VIS1
);
5133 cpu_src1_32
= gen_load_fpr_F(dc
, rs2
);
5134 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
5136 case 0x07a: /* VIS I fornot1 */
5137 CHECK_FPU_FEATURE(dc
, VIS1
);
5138 gen_ne_fop_DDD(dc
, rd
, rs2
, rs1
, tcg_gen_orc_i64
);
5140 case 0x07b: /* VIS I fornot1s */
5141 CHECK_FPU_FEATURE(dc
, VIS1
);
5142 gen_ne_fop_FFF(dc
, rd
, rs2
, rs1
, tcg_gen_orc_i32
);
5144 case 0x07c: /* VIS I for */
5145 CHECK_FPU_FEATURE(dc
, VIS1
);
5146 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_or_i64
);
5148 case 0x07d: /* VIS I fors */
5149 CHECK_FPU_FEATURE(dc
, VIS1
);
5150 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_or_i32
);
5152 case 0x07e: /* VIS I fone */
5153 CHECK_FPU_FEATURE(dc
, VIS1
);
5154 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5155 tcg_gen_movi_i64(cpu_dst_64
, -1);
5156 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5158 case 0x07f: /* VIS I fones */
5159 CHECK_FPU_FEATURE(dc
, VIS1
);
5160 cpu_dst_32
= gen_dest_fpr_F(dc
);
5161 tcg_gen_movi_i32(cpu_dst_32
, -1);
5162 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5164 case 0x080: /* VIS I shutdown */
5165 case 0x081: /* VIS II siam */
5174 } else if (xop
== 0x37) { /* V8 CPop2, V9 impdep2 */
5175 #ifdef TARGET_SPARC64
5180 #ifdef TARGET_SPARC64
5181 } else if (xop
== 0x39) { /* V9 return */
5183 cpu_src1
= get_src1(dc
, insn
);
5184 cpu_tmp0
= get_temp_tl(dc
);
5185 if (IS_IMM
) { /* immediate */
5186 simm
= GET_FIELDs(insn
, 19, 31);
5187 tcg_gen_addi_tl(cpu_tmp0
, cpu_src1
, simm
);
5188 } else { /* register */
5189 rs2
= GET_FIELD(insn
, 27, 31);
5191 cpu_src2
= gen_load_gpr(dc
, rs2
);
5192 tcg_gen_add_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
5194 tcg_gen_mov_tl(cpu_tmp0
, cpu_src1
);
5197 gen_helper_restore(cpu_env
);
5199 gen_check_align(cpu_tmp0
, 3);
5200 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5201 dc
->npc
= DYNAMIC_PC
;
5205 cpu_src1
= get_src1(dc
, insn
);
5206 cpu_tmp0
= get_temp_tl(dc
);
5207 if (IS_IMM
) { /* immediate */
5208 simm
= GET_FIELDs(insn
, 19, 31);
5209 tcg_gen_addi_tl(cpu_tmp0
, cpu_src1
, simm
);
5210 } else { /* register */
5211 rs2
= GET_FIELD(insn
, 27, 31);
5213 cpu_src2
= gen_load_gpr(dc
, rs2
);
5214 tcg_gen_add_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
5216 tcg_gen_mov_tl(cpu_tmp0
, cpu_src1
);
5220 case 0x38: /* jmpl */
5222 TCGv t
= gen_dest_gpr(dc
, rd
);
5223 tcg_gen_movi_tl(t
, dc
->pc
);
5224 gen_store_gpr(dc
, rd
, t
);
5227 gen_check_align(cpu_tmp0
, 3);
5228 gen_address_mask(dc
, cpu_tmp0
);
5229 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5230 dc
->npc
= DYNAMIC_PC
;
5233 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5234 case 0x39: /* rett, V9 return */
5236 if (!supervisor(dc
))
5239 gen_check_align(cpu_tmp0
, 3);
5240 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5241 dc
->npc
= DYNAMIC_PC
;
5242 gen_helper_rett(cpu_env
);
5246 case 0x3b: /* flush */
5247 if (!((dc
)->def
->features
& CPU_FEATURE_FLUSH
))
5251 case 0x3c: /* save */
5252 gen_helper_save(cpu_env
);
5253 gen_store_gpr(dc
, rd
, cpu_tmp0
);
5255 case 0x3d: /* restore */
5256 gen_helper_restore(cpu_env
);
5257 gen_store_gpr(dc
, rd
, cpu_tmp0
);
5259 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
5260 case 0x3e: /* V9 done/retry */
5264 if (!supervisor(dc
))
5266 dc
->npc
= DYNAMIC_PC
;
5267 dc
->pc
= DYNAMIC_PC
;
5268 gen_helper_done(cpu_env
);
5271 if (!supervisor(dc
))
5273 dc
->npc
= DYNAMIC_PC
;
5274 dc
->pc
= DYNAMIC_PC
;
5275 gen_helper_retry(cpu_env
);
5290 case 3: /* load/store instructions */
5292 unsigned int xop
= GET_FIELD(insn
, 7, 12);
5293 /* ??? gen_address_mask prevents us from using a source
5294 register directly. Always generate a temporary. */
5295 TCGv cpu_addr
= get_temp_tl(dc
);
5297 tcg_gen_mov_tl(cpu_addr
, get_src1(dc
, insn
));
5298 if (xop
== 0x3c || xop
== 0x3e) {
5299 /* V9 casa/casxa : no offset */
5300 } else if (IS_IMM
) { /* immediate */
5301 simm
= GET_FIELDs(insn
, 19, 31);
5303 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, simm
);
5305 } else { /* register */
5306 rs2
= GET_FIELD(insn
, 27, 31);
5308 tcg_gen_add_tl(cpu_addr
, cpu_addr
, gen_load_gpr(dc
, rs2
));
5311 if (xop
< 4 || (xop
> 7 && xop
< 0x14 && xop
!= 0x0e) ||
5312 (xop
> 0x17 && xop
<= 0x1d ) ||
5313 (xop
> 0x2c && xop
<= 0x33) || xop
== 0x1f || xop
== 0x3d) {
5314 TCGv cpu_val
= gen_dest_gpr(dc
, rd
);
5317 case 0x0: /* ld, V9 lduw, load unsigned word */
5318 gen_address_mask(dc
, cpu_addr
);
5319 tcg_gen_qemu_ld32u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5321 case 0x1: /* ldub, load unsigned byte */
5322 gen_address_mask(dc
, cpu_addr
);
5323 tcg_gen_qemu_ld8u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5325 case 0x2: /* lduh, load unsigned halfword */
5326 gen_address_mask(dc
, cpu_addr
);
5327 tcg_gen_qemu_ld16u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5329 case 0x3: /* ldd, load double word */
5335 gen_address_mask(dc
, cpu_addr
);
5336 t64
= tcg_temp_new_i64();
5337 tcg_gen_qemu_ld64(t64
, cpu_addr
, dc
->mem_idx
);
5338 tcg_gen_trunc_i64_tl(cpu_val
, t64
);
5339 tcg_gen_ext32u_tl(cpu_val
, cpu_val
);
5340 gen_store_gpr(dc
, rd
+ 1, cpu_val
);
5341 tcg_gen_shri_i64(t64
, t64
, 32);
5342 tcg_gen_trunc_i64_tl(cpu_val
, t64
);
5343 tcg_temp_free_i64(t64
);
5344 tcg_gen_ext32u_tl(cpu_val
, cpu_val
);
5347 case 0x9: /* ldsb, load signed byte */
5348 gen_address_mask(dc
, cpu_addr
);
5349 tcg_gen_qemu_ld8s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5351 case 0xa: /* ldsh, load signed halfword */
5352 gen_address_mask(dc
, cpu_addr
);
5353 tcg_gen_qemu_ld16s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5355 case 0xd: /* ldstub */
5356 gen_ldstub(dc
, cpu_val
, cpu_addr
, dc
->mem_idx
);
5359 /* swap, swap register with memory. Also atomically */
5360 CHECK_IU_FEATURE(dc
, SWAP
);
5361 cpu_src1
= gen_load_gpr(dc
, rd
);
5362 gen_swap(dc
, cpu_val
, cpu_src1
, cpu_addr
,
5363 dc
->mem_idx
, MO_TEUL
);
5365 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5366 case 0x10: /* lda, V9 lduwa, load word alternate */
5367 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUL
);
5369 case 0x11: /* lduba, load unsigned byte alternate */
5370 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_UB
);
5372 case 0x12: /* lduha, load unsigned halfword alternate */
5373 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUW
);
5375 case 0x13: /* ldda, load double word alternate */
5379 gen_ldda_asi(dc
, cpu_addr
, insn
, rd
);
5381 case 0x19: /* ldsba, load signed byte alternate */
5382 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_SB
);
5384 case 0x1a: /* ldsha, load signed halfword alternate */
5385 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TESW
);
5387 case 0x1d: /* ldstuba -- XXX: should be atomically */
5388 gen_ldstub_asi(dc
, cpu_val
, cpu_addr
, insn
);
5390 case 0x1f: /* swapa, swap reg with alt. memory. Also
5392 CHECK_IU_FEATURE(dc
, SWAP
);
5393 cpu_src1
= gen_load_gpr(dc
, rd
);
5394 gen_swap_asi(dc
, cpu_val
, cpu_src1
, cpu_addr
, insn
);
5397 #ifndef TARGET_SPARC64
5398 case 0x30: /* ldc */
5399 case 0x31: /* ldcsr */
5400 case 0x33: /* lddc */
5404 #ifdef TARGET_SPARC64
5405 case 0x08: /* V9 ldsw */
5406 gen_address_mask(dc
, cpu_addr
);
5407 tcg_gen_qemu_ld32s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5409 case 0x0b: /* V9 ldx */
5410 gen_address_mask(dc
, cpu_addr
);
5411 tcg_gen_qemu_ld64(cpu_val
, cpu_addr
, dc
->mem_idx
);
5413 case 0x18: /* V9 ldswa */
5414 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TESL
);
5416 case 0x1b: /* V9 ldxa */
5417 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEQ
);
5419 case 0x2d: /* V9 prefetch, no effect */
5421 case 0x30: /* V9 ldfa */
5422 if (gen_trap_ifnofpu(dc
)) {
5425 gen_ldf_asi(dc
, cpu_addr
, insn
, 4, rd
);
5426 gen_update_fprs_dirty(dc
, rd
);
5428 case 0x33: /* V9 lddfa */
5429 if (gen_trap_ifnofpu(dc
)) {
5432 gen_ldf_asi(dc
, cpu_addr
, insn
, 8, DFPREG(rd
));
5433 gen_update_fprs_dirty(dc
, DFPREG(rd
));
5435 case 0x3d: /* V9 prefetcha, no effect */
5437 case 0x32: /* V9 ldqfa */
5438 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5439 if (gen_trap_ifnofpu(dc
)) {
5442 gen_ldf_asi(dc
, cpu_addr
, insn
, 16, QFPREG(rd
));
5443 gen_update_fprs_dirty(dc
, QFPREG(rd
));
5449 gen_store_gpr(dc
, rd
, cpu_val
);
5450 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5453 } else if (xop
>= 0x20 && xop
< 0x24) {
5454 if (gen_trap_ifnofpu(dc
)) {
5458 case 0x20: /* ldf, load fpreg */
5459 gen_address_mask(dc
, cpu_addr
);
5460 cpu_dst_32
= gen_dest_fpr_F(dc
);
5461 tcg_gen_qemu_ld_i32(cpu_dst_32
, cpu_addr
,
5462 dc
->mem_idx
, MO_TEUL
);
5463 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5465 case 0x21: /* ldfsr, V9 ldxfsr */
5466 #ifdef TARGET_SPARC64
5467 gen_address_mask(dc
, cpu_addr
);
5469 TCGv_i64 t64
= tcg_temp_new_i64();
5470 tcg_gen_qemu_ld_i64(t64
, cpu_addr
,
5471 dc
->mem_idx
, MO_TEQ
);
5472 gen_helper_ldxfsr(cpu_fsr
, cpu_env
, cpu_fsr
, t64
);
5473 tcg_temp_free_i64(t64
);
5477 cpu_dst_32
= get_temp_i32(dc
);
5478 tcg_gen_qemu_ld_i32(cpu_dst_32
, cpu_addr
,
5479 dc
->mem_idx
, MO_TEUL
);
5480 gen_helper_ldfsr(cpu_fsr
, cpu_env
, cpu_fsr
, cpu_dst_32
);
5482 case 0x22: /* ldqf, load quad fpreg */
5483 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5484 gen_address_mask(dc
, cpu_addr
);
5485 cpu_src1_64
= tcg_temp_new_i64();
5486 tcg_gen_qemu_ld_i64(cpu_src1_64
, cpu_addr
, dc
->mem_idx
,
5487 MO_TEQ
| MO_ALIGN_4
);
5488 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, 8);
5489 cpu_src2_64
= tcg_temp_new_i64();
5490 tcg_gen_qemu_ld_i64(cpu_src2_64
, cpu_addr
, dc
->mem_idx
,
5491 MO_TEQ
| MO_ALIGN_4
);
5492 gen_store_fpr_Q(dc
, rd
, cpu_src1_64
, cpu_src2_64
);
5493 tcg_temp_free_i64(cpu_src1_64
);
5494 tcg_temp_free_i64(cpu_src2_64
);
5496 case 0x23: /* lddf, load double fpreg */
5497 gen_address_mask(dc
, cpu_addr
);
5498 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5499 tcg_gen_qemu_ld_i64(cpu_dst_64
, cpu_addr
, dc
->mem_idx
,
5500 MO_TEQ
| MO_ALIGN_4
);
5501 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5506 } else if (xop
< 8 || (xop
>= 0x14 && xop
< 0x18) ||
5507 xop
== 0xe || xop
== 0x1e) {
5508 TCGv cpu_val
= gen_load_gpr(dc
, rd
);
5511 case 0x4: /* st, store word */
5512 gen_address_mask(dc
, cpu_addr
);
5513 tcg_gen_qemu_st32(cpu_val
, cpu_addr
, dc
->mem_idx
);
5515 case 0x5: /* stb, store byte */
5516 gen_address_mask(dc
, cpu_addr
);
5517 tcg_gen_qemu_st8(cpu_val
, cpu_addr
, dc
->mem_idx
);
5519 case 0x6: /* sth, store halfword */
5520 gen_address_mask(dc
, cpu_addr
);
5521 tcg_gen_qemu_st16(cpu_val
, cpu_addr
, dc
->mem_idx
);
5523 case 0x7: /* std, store double word */
5530 gen_address_mask(dc
, cpu_addr
);
5531 lo
= gen_load_gpr(dc
, rd
+ 1);
5532 t64
= tcg_temp_new_i64();
5533 tcg_gen_concat_tl_i64(t64
, lo
, cpu_val
);
5534 tcg_gen_qemu_st64(t64
, cpu_addr
, dc
->mem_idx
);
5535 tcg_temp_free_i64(t64
);
5538 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5539 case 0x14: /* sta, V9 stwa, store word alternate */
5540 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUL
);
5542 case 0x15: /* stba, store byte alternate */
5543 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_UB
);
5545 case 0x16: /* stha, store halfword alternate */
5546 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUW
);
5548 case 0x17: /* stda, store double word alternate */
5552 gen_stda_asi(dc
, cpu_val
, cpu_addr
, insn
, rd
);
5555 #ifdef TARGET_SPARC64
5556 case 0x0e: /* V9 stx */
5557 gen_address_mask(dc
, cpu_addr
);
5558 tcg_gen_qemu_st64(cpu_val
, cpu_addr
, dc
->mem_idx
);
5560 case 0x1e: /* V9 stxa */
5561 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEQ
);
5567 } else if (xop
> 0x23 && xop
< 0x28) {
5568 if (gen_trap_ifnofpu(dc
)) {
5572 case 0x24: /* stf, store fpreg */
5573 gen_address_mask(dc
, cpu_addr
);
5574 cpu_src1_32
= gen_load_fpr_F(dc
, rd
);
5575 tcg_gen_qemu_st_i32(cpu_src1_32
, cpu_addr
,
5576 dc
->mem_idx
, MO_TEUL
);
5578 case 0x25: /* stfsr, V9 stxfsr */
5580 #ifdef TARGET_SPARC64
5581 gen_address_mask(dc
, cpu_addr
);
5583 tcg_gen_qemu_st64(cpu_fsr
, cpu_addr
, dc
->mem_idx
);
5587 tcg_gen_qemu_st32(cpu_fsr
, cpu_addr
, dc
->mem_idx
);
5591 #ifdef TARGET_SPARC64
5592 /* V9 stqf, store quad fpreg */
5593 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5594 gen_address_mask(dc
, cpu_addr
);
5595 /* ??? While stqf only requires 4-byte alignment, it is
5596 legal for the cpu to signal the unaligned exception.
5597 The OS trap handler is then required to fix it up.
5598 For qemu, this avoids having to probe the second page
5599 before performing the first write. */
5600 cpu_src1_64
= gen_load_fpr_Q0(dc
, rd
);
5601 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
,
5602 dc
->mem_idx
, MO_TEQ
| MO_ALIGN_16
);
5603 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, 8);
5604 cpu_src2_64
= gen_load_fpr_Q1(dc
, rd
);
5605 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
,
5606 dc
->mem_idx
, MO_TEQ
);
5608 #else /* !TARGET_SPARC64 */
5609 /* stdfq, store floating point queue */
5610 #if defined(CONFIG_USER_ONLY)
5613 if (!supervisor(dc
))
5615 if (gen_trap_ifnofpu(dc
)) {
5621 case 0x27: /* stdf, store double fpreg */
5622 gen_address_mask(dc
, cpu_addr
);
5623 cpu_src1_64
= gen_load_fpr_D(dc
, rd
);
5624 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
, dc
->mem_idx
,
5625 MO_TEQ
| MO_ALIGN_4
);
5630 } else if (xop
> 0x33 && xop
< 0x3f) {
5632 #ifdef TARGET_SPARC64
5633 case 0x34: /* V9 stfa */
5634 if (gen_trap_ifnofpu(dc
)) {
5637 gen_stf_asi(dc
, cpu_addr
, insn
, 4, rd
);
5639 case 0x36: /* V9 stqfa */
5641 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5642 if (gen_trap_ifnofpu(dc
)) {
5645 gen_stf_asi(dc
, cpu_addr
, insn
, 16, QFPREG(rd
));
5648 case 0x37: /* V9 stdfa */
5649 if (gen_trap_ifnofpu(dc
)) {
5652 gen_stf_asi(dc
, cpu_addr
, insn
, 8, DFPREG(rd
));
5654 case 0x3e: /* V9 casxa */
5655 rs2
= GET_FIELD(insn
, 27, 31);
5656 cpu_src2
= gen_load_gpr(dc
, rs2
);
5657 gen_casx_asi(dc
, cpu_addr
, cpu_src2
, insn
, rd
);
5660 case 0x34: /* stc */
5661 case 0x35: /* stcsr */
5662 case 0x36: /* stdcq */
5663 case 0x37: /* stdc */
5666 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5667 case 0x3c: /* V9 or LEON3 casa */
5668 #ifndef TARGET_SPARC64
5669 CHECK_IU_FEATURE(dc
, CASA
);
5671 rs2
= GET_FIELD(insn
, 27, 31);
5672 cpu_src2
= gen_load_gpr(dc
, rs2
);
5673 gen_cas_asi(dc
, cpu_addr
, cpu_src2
, insn
, rd
);
5685 /* default case for non jump instructions */
5686 if (dc
->npc
== DYNAMIC_PC
) {
5687 dc
->pc
= DYNAMIC_PC
;
5689 } else if (dc
->npc
== JUMP_PC
) {
5690 /* we can do a static jump */
5691 gen_branch2(dc
, dc
->jump_pc
[0], dc
->jump_pc
[1], cpu_cond
);
5692 dc
->base
.is_jmp
= DISAS_NORETURN
;
5695 dc
->npc
= dc
->npc
+ 4;
5700 gen_exception(dc
, TT_ILL_INSN
);
5703 gen_exception(dc
, TT_UNIMP_FLUSH
);
5705 #if !defined(CONFIG_USER_ONLY)
5707 gen_exception(dc
, TT_PRIV_INSN
);
5711 gen_op_fpexception_im(dc
, FSR_FTT_UNIMPFPOP
);
5713 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5715 gen_op_fpexception_im(dc
, FSR_FTT_SEQ_ERROR
);
5718 #ifndef TARGET_SPARC64
5720 gen_exception(dc
, TT_NCP_INSN
);
5724 if (dc
->n_t32
!= 0) {
5726 for (i
= dc
->n_t32
- 1; i
>= 0; --i
) {
5727 tcg_temp_free_i32(dc
->t32
[i
]);
5731 if (dc
->n_ttl
!= 0) {
5733 for (i
= dc
->n_ttl
- 1; i
>= 0; --i
) {
5734 tcg_temp_free(dc
->ttl
[i
]);
5740 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
* tb
)
5742 CPUSPARCState
*env
= cs
->env_ptr
;
5743 DisasContext dc1
, *dc
= &dc1
;
5747 memset(dc
, 0, sizeof(DisasContext
));
5749 dc
->base
.pc_first
= tb
->pc
;
5750 dc
->base
.pc_next
= tb
->pc
;
5751 dc
->base
.is_jmp
= DISAS_NEXT
;
5752 dc
->base
.num_insns
= 0;
5753 dc
->base
.singlestep_enabled
= cs
->singlestep_enabled
;
5755 dc
->pc
= dc
->base
.pc_first
;
5756 dc
->npc
= (target_ulong
) tb
->cs_base
;
5757 dc
->cc_op
= CC_OP_DYNAMIC
;
5758 dc
->mem_idx
= tb
->flags
& TB_FLAG_MMU_MASK
;
5759 dc
->def
= &env
->def
;
5760 dc
->fpu_enabled
= tb_fpu_enabled(tb
->flags
);
5761 dc
->address_mask_32bit
= tb_am_enabled(tb
->flags
);
5762 #ifndef CONFIG_USER_ONLY
5763 dc
->supervisor
= (tb
->flags
& TB_FLAG_SUPER
) != 0;
5765 #ifdef TARGET_SPARC64
5767 dc
->asi
= (tb
->flags
>> TB_FLAG_ASI_SHIFT
) & 0xff;
5768 #ifndef CONFIG_USER_ONLY
5769 dc
->hypervisor
= (tb
->flags
& TB_FLAG_HYPER
) != 0;
5773 max_insns
= tb_cflags(tb
) & CF_COUNT_MASK
;
5774 if (max_insns
== 0) {
5775 max_insns
= CF_COUNT_MASK
;
5777 if (max_insns
> TCG_MAX_INSNS
) {
5778 max_insns
= TCG_MAX_INSNS
;
5780 if (dc
->base
.singlestep_enabled
|| singlestep
) {
5786 if (dc
->npc
& JUMP_PC
) {
5787 assert(dc
->jump_pc
[1] == dc
->pc
+ 4);
5788 tcg_gen_insn_start(dc
->pc
, dc
->jump_pc
[0] | JUMP_PC
);
5790 tcg_gen_insn_start(dc
->pc
, dc
->npc
);
5792 dc
->base
.num_insns
++;
5794 if (unlikely(cpu_breakpoint_test(cs
, dc
->base
.pc_next
, BP_ANY
))) {
5795 if (dc
->pc
!= dc
->base
.pc_first
) {
5798 gen_helper_debug(cpu_env
);
5800 dc
->base
.is_jmp
= DISAS_NORETURN
;
5801 dc
->base
.pc_next
+= 4;
5805 if (dc
->base
.num_insns
== max_insns
&& (tb_cflags(tb
) & CF_LAST_IO
)) {
5809 insn
= cpu_ldl_code(env
, dc
->pc
);
5810 dc
->base
.pc_next
+= 4;
5812 disas_sparc_insn(dc
, insn
);
5814 if (dc
->base
.is_jmp
== DISAS_NORETURN
) {
5817 /* if the next PC is different, we abort now */
5818 if (dc
->pc
!= dc
->base
.pc_next
) {
5821 /* if we reach a page boundary, we stop generation so that the
5822 PC of a TT_TFAULT exception is always in the right page */
5823 if ((dc
->pc
& (TARGET_PAGE_SIZE
- 1)) == 0)
5825 } while (!tcg_op_buf_full() &&
5826 (dc
->pc
- dc
->base
.pc_first
) < (TARGET_PAGE_SIZE
- 32) &&
5827 dc
->base
.num_insns
< max_insns
);
5830 if (tb_cflags(tb
) & CF_LAST_IO
) {
5833 if (dc
->base
.is_jmp
!= DISAS_NORETURN
) {
5834 if (dc
->pc
!= DYNAMIC_PC
&&
5835 (dc
->npc
!= DYNAMIC_PC
&& dc
->npc
!= JUMP_PC
)) {
5836 /* static PC and NPC: we can use direct chaining */
5837 gen_goto_tb(dc
, 0, dc
->pc
, dc
->npc
);
5839 if (dc
->pc
!= DYNAMIC_PC
) {
5840 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
5846 gen_tb_end(tb
, dc
->base
.num_insns
);
5848 tb
->size
= dc
->base
.pc_next
- dc
->base
.pc_first
;
5849 tb
->icount
= dc
->base
.num_insns
;
5852 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)
5853 && qemu_log_in_addr_range(dc
->base
.pc_first
)) {
5855 qemu_log("--------------\n");
5856 qemu_log("IN: %s\n", lookup_symbol(dc
->base
.pc_first
));
5857 log_target_disas(cs
, dc
->base
.pc_first
,
5858 dc
->base
.pc_next
- dc
->base
.pc_first
);
5865 void sparc_tcg_init(void)
5867 static const char gregnames
[32][4] = {
5868 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5869 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5870 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5871 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5873 static const char fregnames
[32][4] = {
5874 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5875 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5876 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5877 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5880 static const struct { TCGv_i32
*ptr
; int off
; const char *name
; } r32
[] = {
5881 #ifdef TARGET_SPARC64
5882 { &cpu_xcc
, offsetof(CPUSPARCState
, xcc
), "xcc" },
5883 { &cpu_fprs
, offsetof(CPUSPARCState
, fprs
), "fprs" },
5885 { &cpu_wim
, offsetof(CPUSPARCState
, wim
), "wim" },
5887 { &cpu_cc_op
, offsetof(CPUSPARCState
, cc_op
), "cc_op" },
5888 { &cpu_psr
, offsetof(CPUSPARCState
, psr
), "psr" },
5891 static const struct { TCGv
*ptr
; int off
; const char *name
; } rtl
[] = {
5892 #ifdef TARGET_SPARC64
5893 { &cpu_gsr
, offsetof(CPUSPARCState
, gsr
), "gsr" },
5894 { &cpu_tick_cmpr
, offsetof(CPUSPARCState
, tick_cmpr
), "tick_cmpr" },
5895 { &cpu_stick_cmpr
, offsetof(CPUSPARCState
, stick_cmpr
), "stick_cmpr" },
5896 { &cpu_hstick_cmpr
, offsetof(CPUSPARCState
, hstick_cmpr
),
5898 { &cpu_hintp
, offsetof(CPUSPARCState
, hintp
), "hintp" },
5899 { &cpu_htba
, offsetof(CPUSPARCState
, htba
), "htba" },
5900 { &cpu_hver
, offsetof(CPUSPARCState
, hver
), "hver" },
5901 { &cpu_ssr
, offsetof(CPUSPARCState
, ssr
), "ssr" },
5902 { &cpu_ver
, offsetof(CPUSPARCState
, version
), "ver" },
5904 { &cpu_cond
, offsetof(CPUSPARCState
, cond
), "cond" },
5905 { &cpu_cc_src
, offsetof(CPUSPARCState
, cc_src
), "cc_src" },
5906 { &cpu_cc_src2
, offsetof(CPUSPARCState
, cc_src2
), "cc_src2" },
5907 { &cpu_cc_dst
, offsetof(CPUSPARCState
, cc_dst
), "cc_dst" },
5908 { &cpu_fsr
, offsetof(CPUSPARCState
, fsr
), "fsr" },
5909 { &cpu_pc
, offsetof(CPUSPARCState
, pc
), "pc" },
5910 { &cpu_npc
, offsetof(CPUSPARCState
, npc
), "npc" },
5911 { &cpu_y
, offsetof(CPUSPARCState
, y
), "y" },
5912 #ifndef CONFIG_USER_ONLY
5913 { &cpu_tbr
, offsetof(CPUSPARCState
, tbr
), "tbr" },
5919 cpu_regwptr
= tcg_global_mem_new_ptr(cpu_env
,
5920 offsetof(CPUSPARCState
, regwptr
),
5923 for (i
= 0; i
< ARRAY_SIZE(r32
); ++i
) {
5924 *r32
[i
].ptr
= tcg_global_mem_new_i32(cpu_env
, r32
[i
].off
, r32
[i
].name
);
5927 for (i
= 0; i
< ARRAY_SIZE(rtl
); ++i
) {
5928 *rtl
[i
].ptr
= tcg_global_mem_new(cpu_env
, rtl
[i
].off
, rtl
[i
].name
);
5932 for (i
= 1; i
< 8; ++i
) {
5933 cpu_regs
[i
] = tcg_global_mem_new(cpu_env
,
5934 offsetof(CPUSPARCState
, gregs
[i
]),
5938 for (i
= 8; i
< 32; ++i
) {
5939 cpu_regs
[i
] = tcg_global_mem_new(cpu_regwptr
,
5940 (i
- 8) * sizeof(target_ulong
),
5944 for (i
= 0; i
< TARGET_DPREGS
; i
++) {
5945 cpu_fpr
[i
] = tcg_global_mem_new_i64(cpu_env
,
5946 offsetof(CPUSPARCState
, fpr
[i
]),
5951 void restore_state_to_opc(CPUSPARCState
*env
, TranslationBlock
*tb
,
5954 target_ulong pc
= data
[0];
5955 target_ulong npc
= data
[1];
5958 if (npc
== DYNAMIC_PC
) {
5959 /* dynamic NPC: already stored */
5960 } else if (npc
& JUMP_PC
) {
5961 /* jump PC: use 'cond' and the jump targets of the translation */
5963 env
->npc
= npc
& ~3;