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"
39 #define DYNAMIC_PC 1 /* dynamic pc value */
40 #define JUMP_PC 2 /* dynamic pc value which takes only two values
41 according to jump_pc[T2] */
43 /* global register indexes */
44 static TCGv_ptr cpu_regwptr
;
45 static TCGv cpu_cc_src
, cpu_cc_src2
, cpu_cc_dst
;
46 static TCGv_i32 cpu_cc_op
;
47 static TCGv_i32 cpu_psr
;
48 static TCGv cpu_fsr
, cpu_pc
, cpu_npc
;
49 static TCGv cpu_regs
[32];
51 #ifndef CONFIG_USER_ONLY
56 static TCGv_i32 cpu_xcc
, cpu_fprs
;
58 static TCGv cpu_tick_cmpr
, cpu_stick_cmpr
, cpu_hstick_cmpr
;
59 static TCGv cpu_hintp
, cpu_htba
, cpu_hver
, cpu_ssr
, cpu_ver
;
63 /* Floating point registers */
64 static TCGv_i64 cpu_fpr
[TARGET_DPREGS
];
66 #include "exec/gen-icount.h"
68 typedef struct DisasContext
{
69 target_ulong pc
; /* current Program Counter: integer or DYNAMIC_PC */
70 target_ulong npc
; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
71 target_ulong jump_pc
[2]; /* used when JUMP_PC pc value is used */
75 bool address_mask_32bit
;
77 #ifndef CONFIG_USER_ONLY
84 uint32_t cc_op
; /* current CC operation */
85 struct TranslationBlock
*tb
;
104 // This function uses non-native bit order
105 #define GET_FIELD(X, FROM, TO) \
106 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
108 // This function uses the order in the manuals, i.e. bit 0 is 2^0
109 #define GET_FIELD_SP(X, FROM, TO) \
110 GET_FIELD(X, 31 - (TO), 31 - (FROM))
112 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
113 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
115 #ifdef TARGET_SPARC64
116 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
117 #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
119 #define DFPREG(r) (r & 0x1e)
120 #define QFPREG(r) (r & 0x1c)
123 #define UA2005_HTRAP_MASK 0xff
124 #define V8_TRAP_MASK 0x7f
126 static int sign_extend(int x
, int len
)
129 return (x
<< len
) >> len
;
132 #define IS_IMM (insn & (1<<13))
134 static inline TCGv_i32
get_temp_i32(DisasContext
*dc
)
137 assert(dc
->n_t32
< ARRAY_SIZE(dc
->t32
));
138 dc
->t32
[dc
->n_t32
++] = t
= tcg_temp_new_i32();
142 static inline TCGv
get_temp_tl(DisasContext
*dc
)
145 assert(dc
->n_ttl
< ARRAY_SIZE(dc
->ttl
));
146 dc
->ttl
[dc
->n_ttl
++] = t
= tcg_temp_new();
150 static inline void gen_update_fprs_dirty(DisasContext
*dc
, int rd
)
152 #if defined(TARGET_SPARC64)
153 int bit
= (rd
< 32) ? 1 : 2;
154 /* If we know we've already set this bit within the TB,
155 we can avoid setting it again. */
156 if (!(dc
->fprs_dirty
& bit
)) {
157 dc
->fprs_dirty
|= bit
;
158 tcg_gen_ori_i32(cpu_fprs
, cpu_fprs
, bit
);
163 /* floating point registers moves */
164 static TCGv_i32
gen_load_fpr_F(DisasContext
*dc
, unsigned int src
)
166 #if TCG_TARGET_REG_BITS == 32
168 return TCGV_LOW(cpu_fpr
[src
/ 2]);
170 return TCGV_HIGH(cpu_fpr
[src
/ 2]);
173 TCGv_i32 ret
= get_temp_i32(dc
);
175 tcg_gen_extrl_i64_i32(ret
, cpu_fpr
[src
/ 2]);
177 tcg_gen_extrh_i64_i32(ret
, cpu_fpr
[src
/ 2]);
183 static void gen_store_fpr_F(DisasContext
*dc
, unsigned int dst
, TCGv_i32 v
)
185 #if TCG_TARGET_REG_BITS == 32
187 tcg_gen_mov_i32(TCGV_LOW(cpu_fpr
[dst
/ 2]), v
);
189 tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr
[dst
/ 2]), v
);
192 TCGv_i64 t
= (TCGv_i64
)v
;
193 tcg_gen_deposit_i64(cpu_fpr
[dst
/ 2], cpu_fpr
[dst
/ 2], t
,
194 (dst
& 1 ? 0 : 32), 32);
196 gen_update_fprs_dirty(dc
, dst
);
199 static TCGv_i32
gen_dest_fpr_F(DisasContext
*dc
)
201 return get_temp_i32(dc
);
204 static TCGv_i64
gen_load_fpr_D(DisasContext
*dc
, unsigned int src
)
207 return cpu_fpr
[src
/ 2];
210 static void gen_store_fpr_D(DisasContext
*dc
, unsigned int dst
, TCGv_i64 v
)
213 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2], v
);
214 gen_update_fprs_dirty(dc
, dst
);
217 static TCGv_i64
gen_dest_fpr_D(DisasContext
*dc
, unsigned int dst
)
219 return cpu_fpr
[DFPREG(dst
) / 2];
222 static void gen_op_load_fpr_QT0(unsigned int src
)
224 tcg_gen_st_i64(cpu_fpr
[src
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
225 offsetof(CPU_QuadU
, ll
.upper
));
226 tcg_gen_st_i64(cpu_fpr
[src
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
227 offsetof(CPU_QuadU
, ll
.lower
));
230 static void gen_op_load_fpr_QT1(unsigned int src
)
232 tcg_gen_st_i64(cpu_fpr
[src
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt1
) +
233 offsetof(CPU_QuadU
, ll
.upper
));
234 tcg_gen_st_i64(cpu_fpr
[src
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt1
) +
235 offsetof(CPU_QuadU
, ll
.lower
));
238 static void gen_op_store_QT0_fpr(unsigned int dst
)
240 tcg_gen_ld_i64(cpu_fpr
[dst
/ 2], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
241 offsetof(CPU_QuadU
, ll
.upper
));
242 tcg_gen_ld_i64(cpu_fpr
[dst
/2 + 1], cpu_env
, offsetof(CPUSPARCState
, qt0
) +
243 offsetof(CPU_QuadU
, ll
.lower
));
246 static void gen_store_fpr_Q(DisasContext
*dc
, unsigned int dst
,
247 TCGv_i64 v1
, TCGv_i64 v2
)
251 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2], v1
);
252 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2 + 1], v2
);
253 gen_update_fprs_dirty(dc
, dst
);
256 #ifdef TARGET_SPARC64
257 static TCGv_i64
gen_load_fpr_Q0(DisasContext
*dc
, unsigned int src
)
260 return cpu_fpr
[src
/ 2];
263 static TCGv_i64
gen_load_fpr_Q1(DisasContext
*dc
, unsigned int src
)
266 return cpu_fpr
[src
/ 2 + 1];
269 static void gen_move_Q(DisasContext
*dc
, unsigned int rd
, unsigned int rs
)
274 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], cpu_fpr
[rs
/ 2]);
275 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2 + 1], cpu_fpr
[rs
/ 2 + 1]);
276 gen_update_fprs_dirty(dc
, rd
);
281 #ifdef CONFIG_USER_ONLY
282 #define supervisor(dc) 0
283 #ifdef TARGET_SPARC64
284 #define hypervisor(dc) 0
287 #ifdef TARGET_SPARC64
288 #define hypervisor(dc) (dc->hypervisor)
289 #define supervisor(dc) (dc->supervisor | dc->hypervisor)
291 #define supervisor(dc) (dc->supervisor)
295 #ifdef TARGET_SPARC64
297 #define AM_CHECK(dc) ((dc)->address_mask_32bit)
299 #define AM_CHECK(dc) (1)
303 static inline void gen_address_mask(DisasContext
*dc
, TCGv addr
)
305 #ifdef TARGET_SPARC64
307 tcg_gen_andi_tl(addr
, addr
, 0xffffffffULL
);
311 static inline TCGv
gen_load_gpr(DisasContext
*dc
, int reg
)
315 return cpu_regs
[reg
];
317 TCGv t
= get_temp_tl(dc
);
318 tcg_gen_movi_tl(t
, 0);
323 static inline void gen_store_gpr(DisasContext
*dc
, int reg
, TCGv v
)
327 tcg_gen_mov_tl(cpu_regs
[reg
], v
);
331 static inline TCGv
gen_dest_gpr(DisasContext
*dc
, int reg
)
335 return cpu_regs
[reg
];
337 return get_temp_tl(dc
);
341 static inline bool use_goto_tb(DisasContext
*s
, target_ulong pc
,
344 if (unlikely(s
->singlestep
)) {
348 #ifndef CONFIG_USER_ONLY
349 return (pc
& TARGET_PAGE_MASK
) == (s
->tb
->pc
& TARGET_PAGE_MASK
) &&
350 (npc
& TARGET_PAGE_MASK
) == (s
->tb
->pc
& TARGET_PAGE_MASK
);
356 static inline void gen_goto_tb(DisasContext
*s
, int tb_num
,
357 target_ulong pc
, target_ulong npc
)
359 if (use_goto_tb(s
, pc
, npc
)) {
360 /* jump to same page: we can use a direct jump */
361 tcg_gen_goto_tb(tb_num
);
362 tcg_gen_movi_tl(cpu_pc
, pc
);
363 tcg_gen_movi_tl(cpu_npc
, npc
);
364 tcg_gen_exit_tb((uintptr_t)s
->tb
+ tb_num
);
366 /* jump to another page: currently not optimized */
367 tcg_gen_movi_tl(cpu_pc
, pc
);
368 tcg_gen_movi_tl(cpu_npc
, npc
);
374 static inline void gen_mov_reg_N(TCGv reg
, TCGv_i32 src
)
376 tcg_gen_extu_i32_tl(reg
, src
);
377 tcg_gen_extract_tl(reg
, reg
, PSR_NEG_SHIFT
, 1);
380 static inline void gen_mov_reg_Z(TCGv reg
, TCGv_i32 src
)
382 tcg_gen_extu_i32_tl(reg
, src
);
383 tcg_gen_extract_tl(reg
, reg
, PSR_ZERO_SHIFT
, 1);
386 static inline void gen_mov_reg_V(TCGv reg
, TCGv_i32 src
)
388 tcg_gen_extu_i32_tl(reg
, src
);
389 tcg_gen_extract_tl(reg
, reg
, PSR_OVF_SHIFT
, 1);
392 static inline void gen_mov_reg_C(TCGv reg
, TCGv_i32 src
)
394 tcg_gen_extu_i32_tl(reg
, src
);
395 tcg_gen_extract_tl(reg
, reg
, PSR_CARRY_SHIFT
, 1);
398 static inline void gen_op_add_cc(TCGv dst
, TCGv src1
, TCGv src2
)
400 tcg_gen_mov_tl(cpu_cc_src
, src1
);
401 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
402 tcg_gen_add_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
403 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
406 static TCGv_i32
gen_add32_carry32(void)
408 TCGv_i32 carry_32
, cc_src1_32
, cc_src2_32
;
410 /* Carry is computed from a previous add: (dst < src) */
411 #if TARGET_LONG_BITS == 64
412 cc_src1_32
= tcg_temp_new_i32();
413 cc_src2_32
= tcg_temp_new_i32();
414 tcg_gen_extrl_i64_i32(cc_src1_32
, cpu_cc_dst
);
415 tcg_gen_extrl_i64_i32(cc_src2_32
, cpu_cc_src
);
417 cc_src1_32
= cpu_cc_dst
;
418 cc_src2_32
= cpu_cc_src
;
421 carry_32
= tcg_temp_new_i32();
422 tcg_gen_setcond_i32(TCG_COND_LTU
, carry_32
, cc_src1_32
, cc_src2_32
);
424 #if TARGET_LONG_BITS == 64
425 tcg_temp_free_i32(cc_src1_32
);
426 tcg_temp_free_i32(cc_src2_32
);
432 static TCGv_i32
gen_sub32_carry32(void)
434 TCGv_i32 carry_32
, cc_src1_32
, cc_src2_32
;
436 /* Carry is computed from a previous borrow: (src1 < src2) */
437 #if TARGET_LONG_BITS == 64
438 cc_src1_32
= tcg_temp_new_i32();
439 cc_src2_32
= tcg_temp_new_i32();
440 tcg_gen_extrl_i64_i32(cc_src1_32
, cpu_cc_src
);
441 tcg_gen_extrl_i64_i32(cc_src2_32
, cpu_cc_src2
);
443 cc_src1_32
= cpu_cc_src
;
444 cc_src2_32
= cpu_cc_src2
;
447 carry_32
= tcg_temp_new_i32();
448 tcg_gen_setcond_i32(TCG_COND_LTU
, carry_32
, cc_src1_32
, cc_src2_32
);
450 #if TARGET_LONG_BITS == 64
451 tcg_temp_free_i32(cc_src1_32
);
452 tcg_temp_free_i32(cc_src2_32
);
458 static void gen_op_addx_int(DisasContext
*dc
, TCGv dst
, TCGv src1
,
459 TCGv src2
, int update_cc
)
467 /* Carry is known to be zero. Fall back to plain ADD. */
469 gen_op_add_cc(dst
, src1
, src2
);
471 tcg_gen_add_tl(dst
, src1
, src2
);
478 if (TARGET_LONG_BITS
== 32) {
479 /* We can re-use the host's hardware carry generation by using
480 an ADD2 opcode. We discard the low part of the output.
481 Ideally we'd combine this operation with the add that
482 generated the carry in the first place. */
483 carry
= tcg_temp_new();
484 tcg_gen_add2_tl(carry
, dst
, cpu_cc_src
, src1
, cpu_cc_src2
, src2
);
485 tcg_temp_free(carry
);
488 carry_32
= gen_add32_carry32();
494 carry_32
= gen_sub32_carry32();
498 /* We need external help to produce the carry. */
499 carry_32
= tcg_temp_new_i32();
500 gen_helper_compute_C_icc(carry_32
, cpu_env
);
504 #if TARGET_LONG_BITS == 64
505 carry
= tcg_temp_new();
506 tcg_gen_extu_i32_i64(carry
, carry_32
);
511 tcg_gen_add_tl(dst
, src1
, src2
);
512 tcg_gen_add_tl(dst
, dst
, carry
);
514 tcg_temp_free_i32(carry_32
);
515 #if TARGET_LONG_BITS == 64
516 tcg_temp_free(carry
);
521 tcg_gen_mov_tl(cpu_cc_src
, src1
);
522 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
523 tcg_gen_mov_tl(cpu_cc_dst
, dst
);
524 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADDX
);
525 dc
->cc_op
= CC_OP_ADDX
;
529 static inline void gen_op_sub_cc(TCGv dst
, TCGv src1
, TCGv src2
)
531 tcg_gen_mov_tl(cpu_cc_src
, src1
);
532 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
533 tcg_gen_sub_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
534 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
537 static void gen_op_subx_int(DisasContext
*dc
, TCGv dst
, TCGv src1
,
538 TCGv src2
, int update_cc
)
546 /* Carry is known to be zero. Fall back to plain SUB. */
548 gen_op_sub_cc(dst
, src1
, src2
);
550 tcg_gen_sub_tl(dst
, src1
, src2
);
557 carry_32
= gen_add32_carry32();
563 if (TARGET_LONG_BITS
== 32) {
564 /* We can re-use the host's hardware carry generation by using
565 a SUB2 opcode. We discard the low part of the output.
566 Ideally we'd combine this operation with the add that
567 generated the carry in the first place. */
568 carry
= tcg_temp_new();
569 tcg_gen_sub2_tl(carry
, dst
, cpu_cc_src
, src1
, cpu_cc_src2
, src2
);
570 tcg_temp_free(carry
);
573 carry_32
= gen_sub32_carry32();
577 /* We need external help to produce the carry. */
578 carry_32
= tcg_temp_new_i32();
579 gen_helper_compute_C_icc(carry_32
, cpu_env
);
583 #if TARGET_LONG_BITS == 64
584 carry
= tcg_temp_new();
585 tcg_gen_extu_i32_i64(carry
, carry_32
);
590 tcg_gen_sub_tl(dst
, src1
, src2
);
591 tcg_gen_sub_tl(dst
, dst
, carry
);
593 tcg_temp_free_i32(carry_32
);
594 #if TARGET_LONG_BITS == 64
595 tcg_temp_free(carry
);
600 tcg_gen_mov_tl(cpu_cc_src
, src1
);
601 tcg_gen_mov_tl(cpu_cc_src2
, src2
);
602 tcg_gen_mov_tl(cpu_cc_dst
, dst
);
603 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUBX
);
604 dc
->cc_op
= CC_OP_SUBX
;
608 static inline void gen_op_mulscc(TCGv dst
, TCGv src1
, TCGv src2
)
610 TCGv r_temp
, zero
, t0
;
612 r_temp
= tcg_temp_new();
619 zero
= tcg_const_tl(0);
620 tcg_gen_andi_tl(cpu_cc_src
, src1
, 0xffffffff);
621 tcg_gen_andi_tl(r_temp
, cpu_y
, 0x1);
622 tcg_gen_andi_tl(cpu_cc_src2
, src2
, 0xffffffff);
623 tcg_gen_movcond_tl(TCG_COND_EQ
, cpu_cc_src2
, r_temp
, zero
,
628 // env->y = (b2 << 31) | (env->y >> 1);
629 tcg_gen_extract_tl(t0
, cpu_y
, 1, 31);
630 tcg_gen_deposit_tl(cpu_y
, t0
, cpu_cc_src
, 31, 1);
633 gen_mov_reg_N(t0
, cpu_psr
);
634 gen_mov_reg_V(r_temp
, cpu_psr
);
635 tcg_gen_xor_tl(t0
, t0
, r_temp
);
636 tcg_temp_free(r_temp
);
638 // T0 = (b1 << 31) | (T0 >> 1);
640 tcg_gen_shli_tl(t0
, t0
, 31);
641 tcg_gen_shri_tl(cpu_cc_src
, cpu_cc_src
, 1);
642 tcg_gen_or_tl(cpu_cc_src
, cpu_cc_src
, t0
);
645 tcg_gen_add_tl(cpu_cc_dst
, cpu_cc_src
, cpu_cc_src2
);
647 tcg_gen_mov_tl(dst
, cpu_cc_dst
);
650 static inline void gen_op_multiply(TCGv dst
, TCGv src1
, TCGv src2
, int sign_ext
)
652 #if TARGET_LONG_BITS == 32
654 tcg_gen_muls2_tl(dst
, cpu_y
, src1
, src2
);
656 tcg_gen_mulu2_tl(dst
, cpu_y
, src1
, src2
);
659 TCGv t0
= tcg_temp_new_i64();
660 TCGv t1
= tcg_temp_new_i64();
663 tcg_gen_ext32s_i64(t0
, src1
);
664 tcg_gen_ext32s_i64(t1
, src2
);
666 tcg_gen_ext32u_i64(t0
, src1
);
667 tcg_gen_ext32u_i64(t1
, src2
);
670 tcg_gen_mul_i64(dst
, t0
, t1
);
674 tcg_gen_shri_i64(cpu_y
, dst
, 32);
678 static inline void gen_op_umul(TCGv dst
, TCGv src1
, TCGv src2
)
680 /* zero-extend truncated operands before multiplication */
681 gen_op_multiply(dst
, src1
, src2
, 0);
684 static inline void gen_op_smul(TCGv dst
, TCGv src1
, TCGv src2
)
686 /* sign-extend truncated operands before multiplication */
687 gen_op_multiply(dst
, src1
, src2
, 1);
691 static inline void gen_op_eval_ba(TCGv dst
)
693 tcg_gen_movi_tl(dst
, 1);
697 static inline void gen_op_eval_be(TCGv dst
, TCGv_i32 src
)
699 gen_mov_reg_Z(dst
, src
);
703 static inline void gen_op_eval_ble(TCGv dst
, TCGv_i32 src
)
705 TCGv t0
= tcg_temp_new();
706 gen_mov_reg_N(t0
, src
);
707 gen_mov_reg_V(dst
, src
);
708 tcg_gen_xor_tl(dst
, dst
, t0
);
709 gen_mov_reg_Z(t0
, src
);
710 tcg_gen_or_tl(dst
, dst
, t0
);
715 static inline void gen_op_eval_bl(TCGv dst
, TCGv_i32 src
)
717 TCGv t0
= tcg_temp_new();
718 gen_mov_reg_V(t0
, src
);
719 gen_mov_reg_N(dst
, src
);
720 tcg_gen_xor_tl(dst
, dst
, t0
);
725 static inline void gen_op_eval_bleu(TCGv dst
, TCGv_i32 src
)
727 TCGv t0
= tcg_temp_new();
728 gen_mov_reg_Z(t0
, src
);
729 gen_mov_reg_C(dst
, src
);
730 tcg_gen_or_tl(dst
, dst
, t0
);
735 static inline void gen_op_eval_bcs(TCGv dst
, TCGv_i32 src
)
737 gen_mov_reg_C(dst
, src
);
741 static inline void gen_op_eval_bvs(TCGv dst
, TCGv_i32 src
)
743 gen_mov_reg_V(dst
, src
);
747 static inline void gen_op_eval_bn(TCGv dst
)
749 tcg_gen_movi_tl(dst
, 0);
753 static inline void gen_op_eval_bneg(TCGv dst
, TCGv_i32 src
)
755 gen_mov_reg_N(dst
, src
);
759 static inline void gen_op_eval_bne(TCGv dst
, TCGv_i32 src
)
761 gen_mov_reg_Z(dst
, src
);
762 tcg_gen_xori_tl(dst
, dst
, 0x1);
766 static inline void gen_op_eval_bg(TCGv dst
, TCGv_i32 src
)
768 gen_op_eval_ble(dst
, src
);
769 tcg_gen_xori_tl(dst
, dst
, 0x1);
773 static inline void gen_op_eval_bge(TCGv dst
, TCGv_i32 src
)
775 gen_op_eval_bl(dst
, src
);
776 tcg_gen_xori_tl(dst
, dst
, 0x1);
780 static inline void gen_op_eval_bgu(TCGv dst
, TCGv_i32 src
)
782 gen_op_eval_bleu(dst
, src
);
783 tcg_gen_xori_tl(dst
, dst
, 0x1);
787 static inline void gen_op_eval_bcc(TCGv dst
, TCGv_i32 src
)
789 gen_mov_reg_C(dst
, src
);
790 tcg_gen_xori_tl(dst
, dst
, 0x1);
794 static inline void gen_op_eval_bpos(TCGv dst
, TCGv_i32 src
)
796 gen_mov_reg_N(dst
, src
);
797 tcg_gen_xori_tl(dst
, dst
, 0x1);
801 static inline void gen_op_eval_bvc(TCGv dst
, TCGv_i32 src
)
803 gen_mov_reg_V(dst
, src
);
804 tcg_gen_xori_tl(dst
, dst
, 0x1);
808 FPSR bit field FCC1 | FCC0:
814 static inline void gen_mov_reg_FCC0(TCGv reg
, TCGv src
,
815 unsigned int fcc_offset
)
817 tcg_gen_shri_tl(reg
, src
, FSR_FCC0_SHIFT
+ fcc_offset
);
818 tcg_gen_andi_tl(reg
, reg
, 0x1);
821 static inline void gen_mov_reg_FCC1(TCGv reg
, TCGv src
,
822 unsigned int fcc_offset
)
824 tcg_gen_shri_tl(reg
, src
, FSR_FCC1_SHIFT
+ fcc_offset
);
825 tcg_gen_andi_tl(reg
, reg
, 0x1);
829 static inline void gen_op_eval_fbne(TCGv dst
, TCGv src
,
830 unsigned int fcc_offset
)
832 TCGv t0
= tcg_temp_new();
833 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
834 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
835 tcg_gen_or_tl(dst
, dst
, t0
);
839 // 1 or 2: FCC0 ^ FCC1
840 static inline void gen_op_eval_fblg(TCGv dst
, TCGv src
,
841 unsigned int fcc_offset
)
843 TCGv t0
= tcg_temp_new();
844 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
845 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
846 tcg_gen_xor_tl(dst
, dst
, t0
);
851 static inline void gen_op_eval_fbul(TCGv dst
, TCGv src
,
852 unsigned int fcc_offset
)
854 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
858 static inline void gen_op_eval_fbl(TCGv dst
, TCGv src
,
859 unsigned int fcc_offset
)
861 TCGv t0
= tcg_temp_new();
862 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
863 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
864 tcg_gen_andc_tl(dst
, dst
, t0
);
869 static inline void gen_op_eval_fbug(TCGv dst
, TCGv src
,
870 unsigned int fcc_offset
)
872 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
876 static inline void gen_op_eval_fbg(TCGv dst
, TCGv src
,
877 unsigned int fcc_offset
)
879 TCGv t0
= tcg_temp_new();
880 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
881 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
882 tcg_gen_andc_tl(dst
, t0
, dst
);
887 static inline void gen_op_eval_fbu(TCGv dst
, TCGv src
,
888 unsigned int fcc_offset
)
890 TCGv t0
= tcg_temp_new();
891 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
892 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
893 tcg_gen_and_tl(dst
, dst
, t0
);
898 static inline void gen_op_eval_fbe(TCGv dst
, TCGv src
,
899 unsigned int fcc_offset
)
901 TCGv t0
= tcg_temp_new();
902 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
903 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
904 tcg_gen_or_tl(dst
, dst
, t0
);
905 tcg_gen_xori_tl(dst
, dst
, 0x1);
909 // 0 or 3: !(FCC0 ^ FCC1)
910 static inline void gen_op_eval_fbue(TCGv dst
, TCGv src
,
911 unsigned int fcc_offset
)
913 TCGv t0
= tcg_temp_new();
914 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
915 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
916 tcg_gen_xor_tl(dst
, dst
, t0
);
917 tcg_gen_xori_tl(dst
, dst
, 0x1);
922 static inline void gen_op_eval_fbge(TCGv dst
, TCGv src
,
923 unsigned int fcc_offset
)
925 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
926 tcg_gen_xori_tl(dst
, dst
, 0x1);
929 // !1: !(FCC0 & !FCC1)
930 static inline void gen_op_eval_fbuge(TCGv dst
, TCGv src
,
931 unsigned int fcc_offset
)
933 TCGv t0
= tcg_temp_new();
934 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
935 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
936 tcg_gen_andc_tl(dst
, dst
, t0
);
937 tcg_gen_xori_tl(dst
, dst
, 0x1);
942 static inline void gen_op_eval_fble(TCGv dst
, TCGv src
,
943 unsigned int fcc_offset
)
945 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
946 tcg_gen_xori_tl(dst
, dst
, 0x1);
949 // !2: !(!FCC0 & FCC1)
950 static inline void gen_op_eval_fbule(TCGv dst
, TCGv src
,
951 unsigned int fcc_offset
)
953 TCGv t0
= tcg_temp_new();
954 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
955 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
956 tcg_gen_andc_tl(dst
, t0
, dst
);
957 tcg_gen_xori_tl(dst
, dst
, 0x1);
961 // !3: !(FCC0 & FCC1)
962 static inline void gen_op_eval_fbo(TCGv dst
, TCGv src
,
963 unsigned int fcc_offset
)
965 TCGv t0
= tcg_temp_new();
966 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
967 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
968 tcg_gen_and_tl(dst
, dst
, t0
);
969 tcg_gen_xori_tl(dst
, dst
, 0x1);
973 static inline void gen_branch2(DisasContext
*dc
, target_ulong pc1
,
974 target_ulong pc2
, TCGv r_cond
)
976 TCGLabel
*l1
= gen_new_label();
978 tcg_gen_brcondi_tl(TCG_COND_EQ
, r_cond
, 0, l1
);
980 gen_goto_tb(dc
, 0, pc1
, pc1
+ 4);
983 gen_goto_tb(dc
, 1, pc2
, pc2
+ 4);
986 static void gen_branch_a(DisasContext
*dc
, target_ulong pc1
)
988 TCGLabel
*l1
= gen_new_label();
989 target_ulong npc
= dc
->npc
;
991 tcg_gen_brcondi_tl(TCG_COND_EQ
, cpu_cond
, 0, l1
);
993 gen_goto_tb(dc
, 0, npc
, pc1
);
996 gen_goto_tb(dc
, 1, npc
+ 4, npc
+ 8);
1001 static void gen_branch_n(DisasContext
*dc
, target_ulong pc1
)
1003 target_ulong npc
= dc
->npc
;
1005 if (likely(npc
!= DYNAMIC_PC
)) {
1007 dc
->jump_pc
[0] = pc1
;
1008 dc
->jump_pc
[1] = npc
+ 4;
1013 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1015 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
1016 t
= tcg_const_tl(pc1
);
1017 z
= tcg_const_tl(0);
1018 tcg_gen_movcond_tl(TCG_COND_NE
, cpu_npc
, cpu_cond
, z
, t
, cpu_npc
);
1022 dc
->pc
= DYNAMIC_PC
;
1026 static inline void gen_generic_branch(DisasContext
*dc
)
1028 TCGv npc0
= tcg_const_tl(dc
->jump_pc
[0]);
1029 TCGv npc1
= tcg_const_tl(dc
->jump_pc
[1]);
1030 TCGv zero
= tcg_const_tl(0);
1032 tcg_gen_movcond_tl(TCG_COND_NE
, cpu_npc
, cpu_cond
, zero
, npc0
, npc1
);
1034 tcg_temp_free(npc0
);
1035 tcg_temp_free(npc1
);
1036 tcg_temp_free(zero
);
1039 /* call this function before using the condition register as it may
1040 have been set for a jump */
1041 static inline void flush_cond(DisasContext
*dc
)
1043 if (dc
->npc
== JUMP_PC
) {
1044 gen_generic_branch(dc
);
1045 dc
->npc
= DYNAMIC_PC
;
1049 static inline void save_npc(DisasContext
*dc
)
1051 if (dc
->npc
== JUMP_PC
) {
1052 gen_generic_branch(dc
);
1053 dc
->npc
= DYNAMIC_PC
;
1054 } else if (dc
->npc
!= DYNAMIC_PC
) {
1055 tcg_gen_movi_tl(cpu_npc
, dc
->npc
);
1059 static inline void update_psr(DisasContext
*dc
)
1061 if (dc
->cc_op
!= CC_OP_FLAGS
) {
1062 dc
->cc_op
= CC_OP_FLAGS
;
1063 gen_helper_compute_psr(cpu_env
);
1067 static inline void save_state(DisasContext
*dc
)
1069 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
1073 static void gen_exception(DisasContext
*dc
, int which
)
1078 t
= tcg_const_i32(which
);
1079 gen_helper_raise_exception(cpu_env
, t
);
1080 tcg_temp_free_i32(t
);
1084 static void gen_check_align(TCGv addr
, int mask
)
1086 TCGv_i32 r_mask
= tcg_const_i32(mask
);
1087 gen_helper_check_align(cpu_env
, addr
, r_mask
);
1088 tcg_temp_free_i32(r_mask
);
1091 static inline void gen_mov_pc_npc(DisasContext
*dc
)
1093 if (dc
->npc
== JUMP_PC
) {
1094 gen_generic_branch(dc
);
1095 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1096 dc
->pc
= DYNAMIC_PC
;
1097 } else if (dc
->npc
== DYNAMIC_PC
) {
1098 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1099 dc
->pc
= DYNAMIC_PC
;
1105 static inline void gen_op_next_insn(void)
1107 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1108 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
1111 static void free_compare(DisasCompare
*cmp
)
1114 tcg_temp_free(cmp
->c1
);
1117 tcg_temp_free(cmp
->c2
);
1121 static void gen_compare(DisasCompare
*cmp
, bool xcc
, unsigned int cond
,
1124 static int subcc_cond
[16] = {
1140 -1, /* no overflow */
1143 static int logic_cond
[16] = {
1145 TCG_COND_EQ
, /* eq: Z */
1146 TCG_COND_LE
, /* le: Z | (N ^ V) -> Z | N */
1147 TCG_COND_LT
, /* lt: N ^ V -> N */
1148 TCG_COND_EQ
, /* leu: C | Z -> Z */
1149 TCG_COND_NEVER
, /* ltu: C -> 0 */
1150 TCG_COND_LT
, /* neg: N */
1151 TCG_COND_NEVER
, /* vs: V -> 0 */
1153 TCG_COND_NE
, /* ne: !Z */
1154 TCG_COND_GT
, /* gt: !(Z | (N ^ V)) -> !(Z | N) */
1155 TCG_COND_GE
, /* ge: !(N ^ V) -> !N */
1156 TCG_COND_NE
, /* gtu: !(C | Z) -> !Z */
1157 TCG_COND_ALWAYS
, /* geu: !C -> 1 */
1158 TCG_COND_GE
, /* pos: !N */
1159 TCG_COND_ALWAYS
, /* vc: !V -> 1 */
1165 #ifdef TARGET_SPARC64
1175 switch (dc
->cc_op
) {
1177 cmp
->cond
= logic_cond
[cond
];
1179 cmp
->is_bool
= false;
1181 cmp
->c2
= tcg_const_tl(0);
1182 #ifdef TARGET_SPARC64
1185 cmp
->c1
= tcg_temp_new();
1186 tcg_gen_ext32s_tl(cmp
->c1
, cpu_cc_dst
);
1191 cmp
->c1
= cpu_cc_dst
;
1198 cmp
->cond
= (cond
== 6 ? TCG_COND_LT
: TCG_COND_GE
);
1199 goto do_compare_dst_0
;
1201 case 7: /* overflow */
1202 case 15: /* !overflow */
1206 cmp
->cond
= subcc_cond
[cond
];
1207 cmp
->is_bool
= false;
1208 #ifdef TARGET_SPARC64
1210 /* Note that sign-extension works for unsigned compares as
1211 long as both operands are sign-extended. */
1212 cmp
->g1
= cmp
->g2
= false;
1213 cmp
->c1
= tcg_temp_new();
1214 cmp
->c2
= tcg_temp_new();
1215 tcg_gen_ext32s_tl(cmp
->c1
, cpu_cc_src
);
1216 tcg_gen_ext32s_tl(cmp
->c2
, cpu_cc_src2
);
1220 cmp
->g1
= cmp
->g2
= true;
1221 cmp
->c1
= cpu_cc_src
;
1222 cmp
->c2
= cpu_cc_src2
;
1229 gen_helper_compute_psr(cpu_env
);
1230 dc
->cc_op
= CC_OP_FLAGS
;
1234 /* We're going to generate a boolean result. */
1235 cmp
->cond
= TCG_COND_NE
;
1236 cmp
->is_bool
= true;
1237 cmp
->g1
= cmp
->g2
= false;
1238 cmp
->c1
= r_dst
= tcg_temp_new();
1239 cmp
->c2
= tcg_const_tl(0);
1243 gen_op_eval_bn(r_dst
);
1246 gen_op_eval_be(r_dst
, r_src
);
1249 gen_op_eval_ble(r_dst
, r_src
);
1252 gen_op_eval_bl(r_dst
, r_src
);
1255 gen_op_eval_bleu(r_dst
, r_src
);
1258 gen_op_eval_bcs(r_dst
, r_src
);
1261 gen_op_eval_bneg(r_dst
, r_src
);
1264 gen_op_eval_bvs(r_dst
, r_src
);
1267 gen_op_eval_ba(r_dst
);
1270 gen_op_eval_bne(r_dst
, r_src
);
1273 gen_op_eval_bg(r_dst
, r_src
);
1276 gen_op_eval_bge(r_dst
, r_src
);
1279 gen_op_eval_bgu(r_dst
, r_src
);
1282 gen_op_eval_bcc(r_dst
, r_src
);
1285 gen_op_eval_bpos(r_dst
, r_src
);
1288 gen_op_eval_bvc(r_dst
, r_src
);
1295 static void gen_fcompare(DisasCompare
*cmp
, unsigned int cc
, unsigned int cond
)
1297 unsigned int offset
;
1300 /* For now we still generate a straight boolean result. */
1301 cmp
->cond
= TCG_COND_NE
;
1302 cmp
->is_bool
= true;
1303 cmp
->g1
= cmp
->g2
= false;
1304 cmp
->c1
= r_dst
= tcg_temp_new();
1305 cmp
->c2
= tcg_const_tl(0);
1325 gen_op_eval_bn(r_dst
);
1328 gen_op_eval_fbne(r_dst
, cpu_fsr
, offset
);
1331 gen_op_eval_fblg(r_dst
, cpu_fsr
, offset
);
1334 gen_op_eval_fbul(r_dst
, cpu_fsr
, offset
);
1337 gen_op_eval_fbl(r_dst
, cpu_fsr
, offset
);
1340 gen_op_eval_fbug(r_dst
, cpu_fsr
, offset
);
1343 gen_op_eval_fbg(r_dst
, cpu_fsr
, offset
);
1346 gen_op_eval_fbu(r_dst
, cpu_fsr
, offset
);
1349 gen_op_eval_ba(r_dst
);
1352 gen_op_eval_fbe(r_dst
, cpu_fsr
, offset
);
1355 gen_op_eval_fbue(r_dst
, cpu_fsr
, offset
);
1358 gen_op_eval_fbge(r_dst
, cpu_fsr
, offset
);
1361 gen_op_eval_fbuge(r_dst
, cpu_fsr
, offset
);
1364 gen_op_eval_fble(r_dst
, cpu_fsr
, offset
);
1367 gen_op_eval_fbule(r_dst
, cpu_fsr
, offset
);
1370 gen_op_eval_fbo(r_dst
, cpu_fsr
, offset
);
1375 static void gen_cond(TCGv r_dst
, unsigned int cc
, unsigned int cond
,
1379 gen_compare(&cmp
, cc
, cond
, dc
);
1381 /* The interface is to return a boolean in r_dst. */
1383 tcg_gen_mov_tl(r_dst
, cmp
.c1
);
1385 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1391 static void gen_fcond(TCGv r_dst
, unsigned int cc
, unsigned int cond
)
1394 gen_fcompare(&cmp
, cc
, cond
);
1396 /* The interface is to return a boolean in r_dst. */
1398 tcg_gen_mov_tl(r_dst
, cmp
.c1
);
1400 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1406 #ifdef TARGET_SPARC64
1408 static const int gen_tcg_cond_reg
[8] = {
1419 static void gen_compare_reg(DisasCompare
*cmp
, int cond
, TCGv r_src
)
1421 cmp
->cond
= tcg_invert_cond(gen_tcg_cond_reg
[cond
]);
1422 cmp
->is_bool
= false;
1426 cmp
->c2
= tcg_const_tl(0);
1429 static inline void gen_cond_reg(TCGv r_dst
, int cond
, TCGv r_src
)
1432 gen_compare_reg(&cmp
, cond
, r_src
);
1434 /* The interface is to return a boolean in r_dst. */
1435 tcg_gen_setcond_tl(cmp
.cond
, r_dst
, cmp
.c1
, cmp
.c2
);
1441 static void do_branch(DisasContext
*dc
, int32_t offset
, uint32_t insn
, int cc
)
1443 unsigned int cond
= GET_FIELD(insn
, 3, 6), a
= (insn
& (1 << 29));
1444 target_ulong target
= dc
->pc
+ offset
;
1446 #ifdef TARGET_SPARC64
1447 if (unlikely(AM_CHECK(dc
))) {
1448 target
&= 0xffffffffULL
;
1452 /* unconditional not taken */
1454 dc
->pc
= dc
->npc
+ 4;
1455 dc
->npc
= dc
->pc
+ 4;
1458 dc
->npc
= dc
->pc
+ 4;
1460 } else if (cond
== 0x8) {
1461 /* unconditional taken */
1464 dc
->npc
= dc
->pc
+ 4;
1468 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1472 gen_cond(cpu_cond
, cc
, cond
, dc
);
1474 gen_branch_a(dc
, target
);
1476 gen_branch_n(dc
, target
);
1481 static void do_fbranch(DisasContext
*dc
, int32_t offset
, uint32_t insn
, int cc
)
1483 unsigned int cond
= GET_FIELD(insn
, 3, 6), a
= (insn
& (1 << 29));
1484 target_ulong target
= dc
->pc
+ offset
;
1486 #ifdef TARGET_SPARC64
1487 if (unlikely(AM_CHECK(dc
))) {
1488 target
&= 0xffffffffULL
;
1492 /* unconditional not taken */
1494 dc
->pc
= dc
->npc
+ 4;
1495 dc
->npc
= dc
->pc
+ 4;
1498 dc
->npc
= dc
->pc
+ 4;
1500 } else if (cond
== 0x8) {
1501 /* unconditional taken */
1504 dc
->npc
= dc
->pc
+ 4;
1508 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
1512 gen_fcond(cpu_cond
, cc
, cond
);
1514 gen_branch_a(dc
, target
);
1516 gen_branch_n(dc
, target
);
1521 #ifdef TARGET_SPARC64
1522 static void do_branch_reg(DisasContext
*dc
, int32_t offset
, uint32_t insn
,
1525 unsigned int cond
= GET_FIELD_SP(insn
, 25, 27), a
= (insn
& (1 << 29));
1526 target_ulong target
= dc
->pc
+ offset
;
1528 if (unlikely(AM_CHECK(dc
))) {
1529 target
&= 0xffffffffULL
;
1532 gen_cond_reg(cpu_cond
, cond
, r_reg
);
1534 gen_branch_a(dc
, target
);
1536 gen_branch_n(dc
, target
);
1540 static inline void gen_op_fcmps(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1544 gen_helper_fcmps(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1547 gen_helper_fcmps_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1550 gen_helper_fcmps_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1553 gen_helper_fcmps_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1558 static inline void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1562 gen_helper_fcmpd(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1565 gen_helper_fcmpd_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1568 gen_helper_fcmpd_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1571 gen_helper_fcmpd_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1576 static inline void gen_op_fcmpq(int fccno
)
1580 gen_helper_fcmpq(cpu_fsr
, cpu_env
);
1583 gen_helper_fcmpq_fcc1(cpu_fsr
, cpu_env
);
1586 gen_helper_fcmpq_fcc2(cpu_fsr
, cpu_env
);
1589 gen_helper_fcmpq_fcc3(cpu_fsr
, cpu_env
);
1594 static inline void gen_op_fcmpes(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1598 gen_helper_fcmpes(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1601 gen_helper_fcmpes_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1604 gen_helper_fcmpes_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1607 gen_helper_fcmpes_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1612 static inline void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1616 gen_helper_fcmped(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1619 gen_helper_fcmped_fcc1(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1622 gen_helper_fcmped_fcc2(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1625 gen_helper_fcmped_fcc3(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1630 static inline void gen_op_fcmpeq(int fccno
)
1634 gen_helper_fcmpeq(cpu_fsr
, cpu_env
);
1637 gen_helper_fcmpeq_fcc1(cpu_fsr
, cpu_env
);
1640 gen_helper_fcmpeq_fcc2(cpu_fsr
, cpu_env
);
1643 gen_helper_fcmpeq_fcc3(cpu_fsr
, cpu_env
);
1650 static inline void gen_op_fcmps(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1652 gen_helper_fcmps(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1655 static inline void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1657 gen_helper_fcmpd(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1660 static inline void gen_op_fcmpq(int fccno
)
1662 gen_helper_fcmpq(cpu_fsr
, cpu_env
);
1665 static inline void gen_op_fcmpes(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1667 gen_helper_fcmpes(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1670 static inline void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1672 gen_helper_fcmped(cpu_fsr
, cpu_env
, r_rs1
, r_rs2
);
1675 static inline void gen_op_fcmpeq(int fccno
)
1677 gen_helper_fcmpeq(cpu_fsr
, cpu_env
);
1681 static void gen_op_fpexception_im(DisasContext
*dc
, int fsr_flags
)
1683 tcg_gen_andi_tl(cpu_fsr
, cpu_fsr
, FSR_FTT_NMASK
);
1684 tcg_gen_ori_tl(cpu_fsr
, cpu_fsr
, fsr_flags
);
1685 gen_exception(dc
, TT_FP_EXCP
);
1688 static int gen_trap_ifnofpu(DisasContext
*dc
)
1690 #if !defined(CONFIG_USER_ONLY)
1691 if (!dc
->fpu_enabled
) {
1692 gen_exception(dc
, TT_NFPU_INSN
);
1699 static inline void gen_op_clear_ieee_excp_and_FTT(void)
1701 tcg_gen_andi_tl(cpu_fsr
, cpu_fsr
, FSR_FTT_CEXC_NMASK
);
1704 static inline void gen_fop_FF(DisasContext
*dc
, int rd
, int rs
,
1705 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i32
))
1709 src
= gen_load_fpr_F(dc
, rs
);
1710 dst
= gen_dest_fpr_F(dc
);
1712 gen(dst
, cpu_env
, src
);
1713 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1715 gen_store_fpr_F(dc
, rd
, dst
);
1718 static inline void gen_ne_fop_FF(DisasContext
*dc
, int rd
, int rs
,
1719 void (*gen
)(TCGv_i32
, TCGv_i32
))
1723 src
= gen_load_fpr_F(dc
, rs
);
1724 dst
= gen_dest_fpr_F(dc
);
1728 gen_store_fpr_F(dc
, rd
, dst
);
1731 static inline void gen_fop_FFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1732 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i32
, TCGv_i32
))
1734 TCGv_i32 dst
, src1
, src2
;
1736 src1
= gen_load_fpr_F(dc
, rs1
);
1737 src2
= gen_load_fpr_F(dc
, rs2
);
1738 dst
= gen_dest_fpr_F(dc
);
1740 gen(dst
, cpu_env
, src1
, src2
);
1741 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1743 gen_store_fpr_F(dc
, rd
, dst
);
1746 #ifdef TARGET_SPARC64
1747 static inline void gen_ne_fop_FFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1748 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
1750 TCGv_i32 dst
, src1
, src2
;
1752 src1
= gen_load_fpr_F(dc
, rs1
);
1753 src2
= gen_load_fpr_F(dc
, rs2
);
1754 dst
= gen_dest_fpr_F(dc
);
1756 gen(dst
, src1
, src2
);
1758 gen_store_fpr_F(dc
, rd
, dst
);
1762 static inline void gen_fop_DD(DisasContext
*dc
, int rd
, int rs
,
1763 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i64
))
1767 src
= gen_load_fpr_D(dc
, rs
);
1768 dst
= gen_dest_fpr_D(dc
, rd
);
1770 gen(dst
, cpu_env
, src
);
1771 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1773 gen_store_fpr_D(dc
, rd
, dst
);
1776 #ifdef TARGET_SPARC64
1777 static inline void gen_ne_fop_DD(DisasContext
*dc
, int rd
, int rs
,
1778 void (*gen
)(TCGv_i64
, TCGv_i64
))
1782 src
= gen_load_fpr_D(dc
, rs
);
1783 dst
= gen_dest_fpr_D(dc
, rd
);
1787 gen_store_fpr_D(dc
, rd
, dst
);
1791 static inline void gen_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1792 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i64
, TCGv_i64
))
1794 TCGv_i64 dst
, src1
, src2
;
1796 src1
= gen_load_fpr_D(dc
, rs1
);
1797 src2
= gen_load_fpr_D(dc
, rs2
);
1798 dst
= gen_dest_fpr_D(dc
, rd
);
1800 gen(dst
, cpu_env
, src1
, src2
);
1801 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1803 gen_store_fpr_D(dc
, rd
, dst
);
1806 #ifdef TARGET_SPARC64
1807 static inline void gen_ne_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1808 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
))
1810 TCGv_i64 dst
, src1
, src2
;
1812 src1
= gen_load_fpr_D(dc
, rs1
);
1813 src2
= gen_load_fpr_D(dc
, rs2
);
1814 dst
= gen_dest_fpr_D(dc
, rd
);
1816 gen(dst
, src1
, src2
);
1818 gen_store_fpr_D(dc
, rd
, dst
);
1821 static inline void gen_gsr_fop_DDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1822 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_i64
))
1824 TCGv_i64 dst
, src1
, src2
;
1826 src1
= gen_load_fpr_D(dc
, rs1
);
1827 src2
= gen_load_fpr_D(dc
, rs2
);
1828 dst
= gen_dest_fpr_D(dc
, rd
);
1830 gen(dst
, cpu_gsr
, src1
, src2
);
1832 gen_store_fpr_D(dc
, rd
, dst
);
1835 static inline void gen_ne_fop_DDDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1836 void (*gen
)(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_i64
))
1838 TCGv_i64 dst
, src0
, src1
, src2
;
1840 src1
= gen_load_fpr_D(dc
, rs1
);
1841 src2
= gen_load_fpr_D(dc
, rs2
);
1842 src0
= gen_load_fpr_D(dc
, rd
);
1843 dst
= gen_dest_fpr_D(dc
, rd
);
1845 gen(dst
, src0
, src1
, src2
);
1847 gen_store_fpr_D(dc
, rd
, dst
);
1851 static inline void gen_fop_QQ(DisasContext
*dc
, int rd
, int rs
,
1852 void (*gen
)(TCGv_ptr
))
1854 gen_op_load_fpr_QT1(QFPREG(rs
));
1857 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1859 gen_op_store_QT0_fpr(QFPREG(rd
));
1860 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1863 #ifdef TARGET_SPARC64
1864 static inline void gen_ne_fop_QQ(DisasContext
*dc
, int rd
, int rs
,
1865 void (*gen
)(TCGv_ptr
))
1867 gen_op_load_fpr_QT1(QFPREG(rs
));
1871 gen_op_store_QT0_fpr(QFPREG(rd
));
1872 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1876 static inline void gen_fop_QQQ(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1877 void (*gen
)(TCGv_ptr
))
1879 gen_op_load_fpr_QT0(QFPREG(rs1
));
1880 gen_op_load_fpr_QT1(QFPREG(rs2
));
1883 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1885 gen_op_store_QT0_fpr(QFPREG(rd
));
1886 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1889 static inline void gen_fop_DFF(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1890 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
, TCGv_i32
))
1893 TCGv_i32 src1
, src2
;
1895 src1
= gen_load_fpr_F(dc
, rs1
);
1896 src2
= gen_load_fpr_F(dc
, rs2
);
1897 dst
= gen_dest_fpr_D(dc
, rd
);
1899 gen(dst
, cpu_env
, src1
, src2
);
1900 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1902 gen_store_fpr_D(dc
, rd
, dst
);
1905 static inline void gen_fop_QDD(DisasContext
*dc
, int rd
, int rs1
, int rs2
,
1906 void (*gen
)(TCGv_ptr
, TCGv_i64
, TCGv_i64
))
1908 TCGv_i64 src1
, src2
;
1910 src1
= gen_load_fpr_D(dc
, rs1
);
1911 src2
= gen_load_fpr_D(dc
, rs2
);
1913 gen(cpu_env
, src1
, src2
);
1914 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1916 gen_op_store_QT0_fpr(QFPREG(rd
));
1917 gen_update_fprs_dirty(dc
, QFPREG(rd
));
1920 #ifdef TARGET_SPARC64
1921 static inline void gen_fop_DF(DisasContext
*dc
, int rd
, int rs
,
1922 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
))
1927 src
= gen_load_fpr_F(dc
, rs
);
1928 dst
= gen_dest_fpr_D(dc
, rd
);
1930 gen(dst
, cpu_env
, src
);
1931 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1933 gen_store_fpr_D(dc
, rd
, dst
);
1937 static inline void gen_ne_fop_DF(DisasContext
*dc
, int rd
, int rs
,
1938 void (*gen
)(TCGv_i64
, TCGv_ptr
, TCGv_i32
))
1943 src
= gen_load_fpr_F(dc
, rs
);
1944 dst
= gen_dest_fpr_D(dc
, rd
);
1946 gen(dst
, cpu_env
, src
);
1948 gen_store_fpr_D(dc
, rd
, dst
);
1951 static inline void gen_fop_FD(DisasContext
*dc
, int rd
, int rs
,
1952 void (*gen
)(TCGv_i32
, TCGv_ptr
, TCGv_i64
))
1957 src
= gen_load_fpr_D(dc
, rs
);
1958 dst
= gen_dest_fpr_F(dc
);
1960 gen(dst
, cpu_env
, src
);
1961 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1963 gen_store_fpr_F(dc
, rd
, dst
);
1966 static inline void gen_fop_FQ(DisasContext
*dc
, int rd
, int rs
,
1967 void (*gen
)(TCGv_i32
, TCGv_ptr
))
1971 gen_op_load_fpr_QT1(QFPREG(rs
));
1972 dst
= gen_dest_fpr_F(dc
);
1975 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1977 gen_store_fpr_F(dc
, rd
, dst
);
1980 static inline void gen_fop_DQ(DisasContext
*dc
, int rd
, int rs
,
1981 void (*gen
)(TCGv_i64
, TCGv_ptr
))
1985 gen_op_load_fpr_QT1(QFPREG(rs
));
1986 dst
= gen_dest_fpr_D(dc
, rd
);
1989 gen_helper_check_ieee_exceptions(cpu_fsr
, cpu_env
);
1991 gen_store_fpr_D(dc
, rd
, dst
);
1994 static inline void gen_ne_fop_QF(DisasContext
*dc
, int rd
, int rs
,
1995 void (*gen
)(TCGv_ptr
, TCGv_i32
))
1999 src
= gen_load_fpr_F(dc
, rs
);
2003 gen_op_store_QT0_fpr(QFPREG(rd
));
2004 gen_update_fprs_dirty(dc
, QFPREG(rd
));
2007 static inline void gen_ne_fop_QD(DisasContext
*dc
, int rd
, int rs
,
2008 void (*gen
)(TCGv_ptr
, TCGv_i64
))
2012 src
= gen_load_fpr_D(dc
, rs
);
2016 gen_op_store_QT0_fpr(QFPREG(rd
));
2017 gen_update_fprs_dirty(dc
, QFPREG(rd
));
2020 static void gen_swap(DisasContext
*dc
, TCGv dst
, TCGv src
,
2021 TCGv addr
, int mmu_idx
, TCGMemOp memop
)
2023 gen_address_mask(dc
, addr
);
2024 tcg_gen_atomic_xchg_tl(dst
, addr
, src
, mmu_idx
, memop
);
2027 static void gen_ldstub(DisasContext
*dc
, TCGv dst
, TCGv addr
, int mmu_idx
)
2029 TCGv m1
= tcg_const_tl(0xff);
2030 gen_address_mask(dc
, addr
);
2031 tcg_gen_atomic_xchg_tl(dst
, addr
, m1
, mmu_idx
, MO_UB
);
2036 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2055 static DisasASI
get_asi(DisasContext
*dc
, int insn
, TCGMemOp memop
)
2057 int asi
= GET_FIELD(insn
, 19, 26);
2058 ASIType type
= GET_ASI_HELPER
;
2059 int mem_idx
= dc
->mem_idx
;
2061 #ifndef TARGET_SPARC64
2062 /* Before v9, all asis are immediate and privileged. */
2064 gen_exception(dc
, TT_ILL_INSN
);
2065 type
= GET_ASI_EXCP
;
2066 } else if (supervisor(dc
)
2067 /* Note that LEON accepts ASI_USERDATA in user mode, for
2068 use with CASA. Also note that previous versions of
2069 QEMU allowed (and old versions of gcc emitted) ASI_P
2070 for LEON, which is incorrect. */
2071 || (asi
== ASI_USERDATA
2072 && (dc
->def
->features
& CPU_FEATURE_CASA
))) {
2074 case ASI_USERDATA
: /* User data access */
2075 mem_idx
= MMU_USER_IDX
;
2076 type
= GET_ASI_DIRECT
;
2078 case ASI_KERNELDATA
: /* Supervisor data access */
2079 mem_idx
= MMU_KERNEL_IDX
;
2080 type
= GET_ASI_DIRECT
;
2082 case ASI_M_BYPASS
: /* MMU passthrough */
2083 case ASI_LEON_BYPASS
: /* LEON MMU passthrough */
2084 mem_idx
= MMU_PHYS_IDX
;
2085 type
= GET_ASI_DIRECT
;
2087 case ASI_M_BCOPY
: /* Block copy, sta access */
2088 mem_idx
= MMU_KERNEL_IDX
;
2089 type
= GET_ASI_BCOPY
;
2091 case ASI_M_BFILL
: /* Block fill, stda access */
2092 mem_idx
= MMU_KERNEL_IDX
;
2093 type
= GET_ASI_BFILL
;
2097 gen_exception(dc
, TT_PRIV_INSN
);
2098 type
= GET_ASI_EXCP
;
2104 /* With v9, all asis below 0x80 are privileged. */
2105 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
2106 down that bit into DisasContext. For the moment that's ok,
2107 since the direct implementations below doesn't have any ASIs
2108 in the restricted [0x30, 0x7f] range, and the check will be
2109 done properly in the helper. */
2110 if (!supervisor(dc
) && asi
< 0x80) {
2111 gen_exception(dc
, TT_PRIV_ACT
);
2112 type
= GET_ASI_EXCP
;
2115 case ASI_REAL
: /* Bypass */
2116 case ASI_REAL_IO
: /* Bypass, non-cacheable */
2117 case ASI_REAL_L
: /* Bypass LE */
2118 case ASI_REAL_IO_L
: /* Bypass, non-cacheable LE */
2119 case ASI_TWINX_REAL
: /* Real address, twinx */
2120 case ASI_TWINX_REAL_L
: /* Real address, twinx, LE */
2121 case ASI_QUAD_LDD_PHYS
:
2122 case ASI_QUAD_LDD_PHYS_L
:
2123 mem_idx
= MMU_PHYS_IDX
;
2125 case ASI_N
: /* Nucleus */
2126 case ASI_NL
: /* Nucleus LE */
2129 case ASI_NUCLEUS_QUAD_LDD
:
2130 case ASI_NUCLEUS_QUAD_LDD_L
:
2131 if (hypervisor(dc
)) {
2132 mem_idx
= MMU_PHYS_IDX
;
2134 mem_idx
= MMU_NUCLEUS_IDX
;
2137 case ASI_AIUP
: /* As if user primary */
2138 case ASI_AIUPL
: /* As if user primary LE */
2139 case ASI_TWINX_AIUP
:
2140 case ASI_TWINX_AIUP_L
:
2141 case ASI_BLK_AIUP_4V
:
2142 case ASI_BLK_AIUP_L_4V
:
2145 mem_idx
= MMU_USER_IDX
;
2147 case ASI_AIUS
: /* As if user secondary */
2148 case ASI_AIUSL
: /* As if user secondary LE */
2149 case ASI_TWINX_AIUS
:
2150 case ASI_TWINX_AIUS_L
:
2151 case ASI_BLK_AIUS_4V
:
2152 case ASI_BLK_AIUS_L_4V
:
2155 mem_idx
= MMU_USER_SECONDARY_IDX
;
2157 case ASI_S
: /* Secondary */
2158 case ASI_SL
: /* Secondary LE */
2161 case ASI_BLK_COMMIT_S
:
2168 if (mem_idx
== MMU_USER_IDX
) {
2169 mem_idx
= MMU_USER_SECONDARY_IDX
;
2170 } else if (mem_idx
== MMU_KERNEL_IDX
) {
2171 mem_idx
= MMU_KERNEL_SECONDARY_IDX
;
2174 case ASI_P
: /* Primary */
2175 case ASI_PL
: /* Primary LE */
2178 case ASI_BLK_COMMIT_P
:
2202 type
= GET_ASI_DIRECT
;
2204 case ASI_TWINX_REAL
:
2205 case ASI_TWINX_REAL_L
:
2208 case ASI_TWINX_AIUP
:
2209 case ASI_TWINX_AIUP_L
:
2210 case ASI_TWINX_AIUS
:
2211 case ASI_TWINX_AIUS_L
:
2216 case ASI_QUAD_LDD_PHYS
:
2217 case ASI_QUAD_LDD_PHYS_L
:
2218 case ASI_NUCLEUS_QUAD_LDD
:
2219 case ASI_NUCLEUS_QUAD_LDD_L
:
2220 type
= GET_ASI_DTWINX
;
2222 case ASI_BLK_COMMIT_P
:
2223 case ASI_BLK_COMMIT_S
:
2224 case ASI_BLK_AIUP_4V
:
2225 case ASI_BLK_AIUP_L_4V
:
2228 case ASI_BLK_AIUS_4V
:
2229 case ASI_BLK_AIUS_L_4V
:
2236 type
= GET_ASI_BLOCK
;
2243 type
= GET_ASI_SHORT
;
2250 type
= GET_ASI_SHORT
;
2253 /* The little-endian asis all have bit 3 set. */
2260 return (DisasASI
){ type
, asi
, mem_idx
, memop
};
2263 static void gen_ld_asi(DisasContext
*dc
, TCGv dst
, TCGv addr
,
2264 int insn
, TCGMemOp memop
)
2266 DisasASI da
= get_asi(dc
, insn
, memop
);
2271 case GET_ASI_DTWINX
: /* Reserved for ldda. */
2272 gen_exception(dc
, TT_ILL_INSN
);
2274 case GET_ASI_DIRECT
:
2275 gen_address_mask(dc
, addr
);
2276 tcg_gen_qemu_ld_tl(dst
, addr
, da
.mem_idx
, da
.memop
);
2280 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2281 TCGv_i32 r_mop
= tcg_const_i32(memop
);
2284 #ifdef TARGET_SPARC64
2285 gen_helper_ld_asi(dst
, cpu_env
, addr
, r_asi
, r_mop
);
2288 TCGv_i64 t64
= tcg_temp_new_i64();
2289 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2290 tcg_gen_trunc_i64_tl(dst
, t64
);
2291 tcg_temp_free_i64(t64
);
2294 tcg_temp_free_i32(r_mop
);
2295 tcg_temp_free_i32(r_asi
);
2301 static void gen_st_asi(DisasContext
*dc
, TCGv src
, TCGv addr
,
2302 int insn
, TCGMemOp memop
)
2304 DisasASI da
= get_asi(dc
, insn
, memop
);
2309 case GET_ASI_DTWINX
: /* Reserved for stda. */
2310 #ifndef TARGET_SPARC64
2311 gen_exception(dc
, TT_ILL_INSN
);
2314 if (!(dc
->def
->features
& CPU_FEATURE_HYPV
)) {
2315 /* Pre OpenSPARC CPUs don't have these */
2316 gen_exception(dc
, TT_ILL_INSN
);
2319 /* in OpenSPARC T1+ CPUs TWINX ASIs in store instructions
2320 * are ST_BLKINIT_ ASIs */
2323 case GET_ASI_DIRECT
:
2324 gen_address_mask(dc
, addr
);
2325 tcg_gen_qemu_st_tl(src
, addr
, da
.mem_idx
, da
.memop
);
2327 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
2329 /* Copy 32 bytes from the address in SRC to ADDR. */
2330 /* ??? The original qemu code suggests 4-byte alignment, dropping
2331 the low bits, but the only place I can see this used is in the
2332 Linux kernel with 32 byte alignment, which would make more sense
2333 as a cacheline-style operation. */
2335 TCGv saddr
= tcg_temp_new();
2336 TCGv daddr
= tcg_temp_new();
2337 TCGv four
= tcg_const_tl(4);
2338 TCGv_i32 tmp
= tcg_temp_new_i32();
2341 tcg_gen_andi_tl(saddr
, src
, -4);
2342 tcg_gen_andi_tl(daddr
, addr
, -4);
2343 for (i
= 0; i
< 32; i
+= 4) {
2344 /* Since the loads and stores are paired, allow the
2345 copy to happen in the host endianness. */
2346 tcg_gen_qemu_ld_i32(tmp
, saddr
, da
.mem_idx
, MO_UL
);
2347 tcg_gen_qemu_st_i32(tmp
, daddr
, da
.mem_idx
, MO_UL
);
2348 tcg_gen_add_tl(saddr
, saddr
, four
);
2349 tcg_gen_add_tl(daddr
, daddr
, four
);
2352 tcg_temp_free(saddr
);
2353 tcg_temp_free(daddr
);
2354 tcg_temp_free(four
);
2355 tcg_temp_free_i32(tmp
);
2361 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2362 TCGv_i32 r_mop
= tcg_const_i32(memop
& MO_SIZE
);
2365 #ifdef TARGET_SPARC64
2366 gen_helper_st_asi(cpu_env
, addr
, src
, r_asi
, r_mop
);
2369 TCGv_i64 t64
= tcg_temp_new_i64();
2370 tcg_gen_extu_tl_i64(t64
, src
);
2371 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2372 tcg_temp_free_i64(t64
);
2375 tcg_temp_free_i32(r_mop
);
2376 tcg_temp_free_i32(r_asi
);
2378 /* A write to a TLB register may alter page maps. End the TB. */
2379 dc
->npc
= DYNAMIC_PC
;
2385 static void gen_swap_asi(DisasContext
*dc
, TCGv dst
, TCGv src
,
2386 TCGv addr
, int insn
)
2388 DisasASI da
= get_asi(dc
, insn
, MO_TEUL
);
2393 case GET_ASI_DIRECT
:
2394 gen_swap(dc
, dst
, src
, addr
, da
.mem_idx
, da
.memop
);
2397 /* ??? Should be DAE_invalid_asi. */
2398 gen_exception(dc
, TT_DATA_ACCESS
);
2403 static void gen_cas_asi(DisasContext
*dc
, TCGv addr
, TCGv cmpv
,
2406 DisasASI da
= get_asi(dc
, insn
, MO_TEUL
);
2412 case GET_ASI_DIRECT
:
2413 oldv
= tcg_temp_new();
2414 tcg_gen_atomic_cmpxchg_tl(oldv
, addr
, cmpv
, gen_load_gpr(dc
, rd
),
2415 da
.mem_idx
, da
.memop
);
2416 gen_store_gpr(dc
, rd
, oldv
);
2417 tcg_temp_free(oldv
);
2420 /* ??? Should be DAE_invalid_asi. */
2421 gen_exception(dc
, TT_DATA_ACCESS
);
2426 static void gen_ldstub_asi(DisasContext
*dc
, TCGv dst
, TCGv addr
, int insn
)
2428 DisasASI da
= get_asi(dc
, insn
, MO_UB
);
2433 case GET_ASI_DIRECT
:
2434 gen_ldstub(dc
, dst
, addr
, da
.mem_idx
);
2437 /* ??? In theory, this should be raise DAE_invalid_asi.
2438 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
2439 if (tb_cflags(dc
->tb
) & CF_PARALLEL
) {
2440 gen_helper_exit_atomic(cpu_env
);
2442 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2443 TCGv_i32 r_mop
= tcg_const_i32(MO_UB
);
2447 t64
= tcg_temp_new_i64();
2448 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2450 s64
= tcg_const_i64(0xff);
2451 gen_helper_st_asi(cpu_env
, addr
, s64
, r_asi
, r_mop
);
2452 tcg_temp_free_i64(s64
);
2453 tcg_temp_free_i32(r_mop
);
2454 tcg_temp_free_i32(r_asi
);
2456 tcg_gen_trunc_i64_tl(dst
, t64
);
2457 tcg_temp_free_i64(t64
);
2460 dc
->npc
= DYNAMIC_PC
;
2467 #ifdef TARGET_SPARC64
2468 static void gen_ldf_asi(DisasContext
*dc
, TCGv addr
,
2469 int insn
, int size
, int rd
)
2471 DisasASI da
= get_asi(dc
, insn
, (size
== 4 ? MO_TEUL
: MO_TEQ
));
2479 case GET_ASI_DIRECT
:
2480 gen_address_mask(dc
, addr
);
2483 d32
= gen_dest_fpr_F(dc
);
2484 tcg_gen_qemu_ld_i32(d32
, addr
, da
.mem_idx
, da
.memop
);
2485 gen_store_fpr_F(dc
, rd
, d32
);
2488 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2489 da
.memop
| MO_ALIGN_4
);
2492 d64
= tcg_temp_new_i64();
2493 tcg_gen_qemu_ld_i64(d64
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_4
);
2494 tcg_gen_addi_tl(addr
, addr
, 8);
2495 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/2+1], addr
, da
.mem_idx
,
2496 da
.memop
| MO_ALIGN_4
);
2497 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
2498 tcg_temp_free_i64(d64
);
2501 g_assert_not_reached();
2506 /* Valid for lddfa on aligned registers only. */
2507 if (size
== 8 && (rd
& 7) == 0) {
2512 gen_address_mask(dc
, addr
);
2514 /* The first operation checks required alignment. */
2515 memop
= da
.memop
| MO_ALIGN_64
;
2516 eight
= tcg_const_tl(8);
2517 for (i
= 0; ; ++i
) {
2518 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2 + i
], addr
,
2523 tcg_gen_add_tl(addr
, addr
, eight
);
2526 tcg_temp_free(eight
);
2528 gen_exception(dc
, TT_ILL_INSN
);
2533 /* Valid for lddfa only. */
2535 gen_address_mask(dc
, addr
);
2536 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
, da
.memop
);
2538 gen_exception(dc
, TT_ILL_INSN
);
2544 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2545 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2548 /* According to the table in the UA2011 manual, the only
2549 other asis that are valid for ldfa/lddfa/ldqfa are
2550 the NO_FAULT asis. We still need a helper for these,
2551 but we can just use the integer asi helper for them. */
2554 d64
= tcg_temp_new_i64();
2555 gen_helper_ld_asi(d64
, cpu_env
, addr
, r_asi
, r_mop
);
2556 d32
= gen_dest_fpr_F(dc
);
2557 tcg_gen_extrl_i64_i32(d32
, d64
);
2558 tcg_temp_free_i64(d64
);
2559 gen_store_fpr_F(dc
, rd
, d32
);
2562 gen_helper_ld_asi(cpu_fpr
[rd
/ 2], cpu_env
, addr
, r_asi
, r_mop
);
2565 d64
= tcg_temp_new_i64();
2566 gen_helper_ld_asi(d64
, cpu_env
, addr
, r_asi
, r_mop
);
2567 tcg_gen_addi_tl(addr
, addr
, 8);
2568 gen_helper_ld_asi(cpu_fpr
[rd
/2+1], cpu_env
, addr
, r_asi
, r_mop
);
2569 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
2570 tcg_temp_free_i64(d64
);
2573 g_assert_not_reached();
2575 tcg_temp_free_i32(r_mop
);
2576 tcg_temp_free_i32(r_asi
);
2582 static void gen_stf_asi(DisasContext
*dc
, TCGv addr
,
2583 int insn
, int size
, int rd
)
2585 DisasASI da
= get_asi(dc
, insn
, (size
== 4 ? MO_TEUL
: MO_TEQ
));
2592 case GET_ASI_DIRECT
:
2593 gen_address_mask(dc
, addr
);
2596 d32
= gen_load_fpr_F(dc
, rd
);
2597 tcg_gen_qemu_st_i32(d32
, addr
, da
.mem_idx
, da
.memop
);
2600 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2601 da
.memop
| MO_ALIGN_4
);
2604 /* Only 4-byte alignment required. However, it is legal for the
2605 cpu to signal the alignment fault, and the OS trap handler is
2606 required to fix it up. Requiring 16-byte alignment here avoids
2607 having to probe the second page before performing the first
2609 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
,
2610 da
.memop
| MO_ALIGN_16
);
2611 tcg_gen_addi_tl(addr
, addr
, 8);
2612 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/2+1], addr
, da
.mem_idx
, da
.memop
);
2615 g_assert_not_reached();
2620 /* Valid for stdfa on aligned registers only. */
2621 if (size
== 8 && (rd
& 7) == 0) {
2626 gen_address_mask(dc
, addr
);
2628 /* The first operation checks required alignment. */
2629 memop
= da
.memop
| MO_ALIGN_64
;
2630 eight
= tcg_const_tl(8);
2631 for (i
= 0; ; ++i
) {
2632 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2 + i
], addr
,
2637 tcg_gen_add_tl(addr
, addr
, eight
);
2640 tcg_temp_free(eight
);
2642 gen_exception(dc
, TT_ILL_INSN
);
2647 /* Valid for stdfa only. */
2649 gen_address_mask(dc
, addr
);
2650 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
.mem_idx
, da
.memop
);
2652 gen_exception(dc
, TT_ILL_INSN
);
2657 /* According to the table in the UA2011 manual, the only
2658 other asis that are valid for ldfa/lddfa/ldqfa are
2659 the PST* asis, which aren't currently handled. */
2660 gen_exception(dc
, TT_ILL_INSN
);
2665 static void gen_ldda_asi(DisasContext
*dc
, TCGv addr
, int insn
, int rd
)
2667 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2668 TCGv_i64 hi
= gen_dest_gpr(dc
, rd
);
2669 TCGv_i64 lo
= gen_dest_gpr(dc
, rd
+ 1);
2675 case GET_ASI_DTWINX
:
2676 gen_address_mask(dc
, addr
);
2677 tcg_gen_qemu_ld_i64(hi
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_16
);
2678 tcg_gen_addi_tl(addr
, addr
, 8);
2679 tcg_gen_qemu_ld_i64(lo
, addr
, da
.mem_idx
, da
.memop
);
2682 case GET_ASI_DIRECT
:
2684 TCGv_i64 tmp
= tcg_temp_new_i64();
2686 gen_address_mask(dc
, addr
);
2687 tcg_gen_qemu_ld_i64(tmp
, addr
, da
.mem_idx
, da
.memop
);
2689 /* Note that LE ldda acts as if each 32-bit register
2690 result is byte swapped. Having just performed one
2691 64-bit bswap, we need now to swap the writebacks. */
2692 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2693 tcg_gen_extr32_i64(lo
, hi
, tmp
);
2695 tcg_gen_extr32_i64(hi
, lo
, tmp
);
2697 tcg_temp_free_i64(tmp
);
2702 /* ??? In theory we've handled all of the ASIs that are valid
2703 for ldda, and this should raise DAE_invalid_asi. However,
2704 real hardware allows others. This can be seen with e.g.
2705 FreeBSD 10.3 wrt ASI_IC_TAG. */
2707 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2708 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2709 TCGv_i64 tmp
= tcg_temp_new_i64();
2712 gen_helper_ld_asi(tmp
, cpu_env
, addr
, r_asi
, r_mop
);
2713 tcg_temp_free_i32(r_asi
);
2714 tcg_temp_free_i32(r_mop
);
2717 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2718 tcg_gen_extr32_i64(lo
, hi
, tmp
);
2720 tcg_gen_extr32_i64(hi
, lo
, tmp
);
2722 tcg_temp_free_i64(tmp
);
2727 gen_store_gpr(dc
, rd
, hi
);
2728 gen_store_gpr(dc
, rd
+ 1, lo
);
2731 static void gen_stda_asi(DisasContext
*dc
, TCGv hi
, TCGv addr
,
2734 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2735 TCGv lo
= gen_load_gpr(dc
, rd
+ 1);
2741 case GET_ASI_DTWINX
:
2742 gen_address_mask(dc
, addr
);
2743 tcg_gen_qemu_st_i64(hi
, addr
, da
.mem_idx
, da
.memop
| MO_ALIGN_16
);
2744 tcg_gen_addi_tl(addr
, addr
, 8);
2745 tcg_gen_qemu_st_i64(lo
, addr
, da
.mem_idx
, da
.memop
);
2748 case GET_ASI_DIRECT
:
2750 TCGv_i64 t64
= tcg_temp_new_i64();
2752 /* Note that LE stda acts as if each 32-bit register result is
2753 byte swapped. We will perform one 64-bit LE store, so now
2754 we must swap the order of the construction. */
2755 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2756 tcg_gen_concat32_i64(t64
, lo
, hi
);
2758 tcg_gen_concat32_i64(t64
, hi
, lo
);
2760 gen_address_mask(dc
, addr
);
2761 tcg_gen_qemu_st_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2762 tcg_temp_free_i64(t64
);
2767 /* ??? In theory we've handled all of the ASIs that are valid
2768 for stda, and this should raise DAE_invalid_asi. */
2770 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2771 TCGv_i32 r_mop
= tcg_const_i32(da
.memop
);
2772 TCGv_i64 t64
= tcg_temp_new_i64();
2775 if ((da
.memop
& MO_BSWAP
) == MO_TE
) {
2776 tcg_gen_concat32_i64(t64
, lo
, hi
);
2778 tcg_gen_concat32_i64(t64
, hi
, lo
);
2782 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2783 tcg_temp_free_i32(r_mop
);
2784 tcg_temp_free_i32(r_asi
);
2785 tcg_temp_free_i64(t64
);
2791 static void gen_casx_asi(DisasContext
*dc
, TCGv addr
, TCGv cmpv
,
2794 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2800 case GET_ASI_DIRECT
:
2801 oldv
= tcg_temp_new();
2802 tcg_gen_atomic_cmpxchg_tl(oldv
, addr
, cmpv
, gen_load_gpr(dc
, rd
),
2803 da
.mem_idx
, da
.memop
);
2804 gen_store_gpr(dc
, rd
, oldv
);
2805 tcg_temp_free(oldv
);
2808 /* ??? Should be DAE_invalid_asi. */
2809 gen_exception(dc
, TT_DATA_ACCESS
);
2814 #elif !defined(CONFIG_USER_ONLY)
2815 static void gen_ldda_asi(DisasContext
*dc
, TCGv addr
, int insn
, int rd
)
2817 /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
2818 whereby "rd + 1" elicits "error: array subscript is above array".
2819 Since we have already asserted that rd is even, the semantics
2821 TCGv lo
= gen_dest_gpr(dc
, rd
| 1);
2822 TCGv hi
= gen_dest_gpr(dc
, rd
);
2823 TCGv_i64 t64
= tcg_temp_new_i64();
2824 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2828 tcg_temp_free_i64(t64
);
2830 case GET_ASI_DIRECT
:
2831 gen_address_mask(dc
, addr
);
2832 tcg_gen_qemu_ld_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2836 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2837 TCGv_i32 r_mop
= tcg_const_i32(MO_Q
);
2840 gen_helper_ld_asi(t64
, cpu_env
, addr
, r_asi
, r_mop
);
2841 tcg_temp_free_i32(r_mop
);
2842 tcg_temp_free_i32(r_asi
);
2847 tcg_gen_extr_i64_i32(lo
, hi
, t64
);
2848 tcg_temp_free_i64(t64
);
2849 gen_store_gpr(dc
, rd
| 1, lo
);
2850 gen_store_gpr(dc
, rd
, hi
);
2853 static void gen_stda_asi(DisasContext
*dc
, TCGv hi
, TCGv addr
,
2856 DisasASI da
= get_asi(dc
, insn
, MO_TEQ
);
2857 TCGv lo
= gen_load_gpr(dc
, rd
+ 1);
2858 TCGv_i64 t64
= tcg_temp_new_i64();
2860 tcg_gen_concat_tl_i64(t64
, lo
, hi
);
2865 case GET_ASI_DIRECT
:
2866 gen_address_mask(dc
, addr
);
2867 tcg_gen_qemu_st_i64(t64
, addr
, da
.mem_idx
, da
.memop
);
2870 /* Store 32 bytes of T64 to ADDR. */
2871 /* ??? The original qemu code suggests 8-byte alignment, dropping
2872 the low bits, but the only place I can see this used is in the
2873 Linux kernel with 32 byte alignment, which would make more sense
2874 as a cacheline-style operation. */
2876 TCGv d_addr
= tcg_temp_new();
2877 TCGv eight
= tcg_const_tl(8);
2880 tcg_gen_andi_tl(d_addr
, addr
, -8);
2881 for (i
= 0; i
< 32; i
+= 8) {
2882 tcg_gen_qemu_st_i64(t64
, d_addr
, da
.mem_idx
, da
.memop
);
2883 tcg_gen_add_tl(d_addr
, d_addr
, eight
);
2886 tcg_temp_free(d_addr
);
2887 tcg_temp_free(eight
);
2892 TCGv_i32 r_asi
= tcg_const_i32(da
.asi
);
2893 TCGv_i32 r_mop
= tcg_const_i32(MO_Q
);
2896 gen_helper_st_asi(cpu_env
, addr
, t64
, r_asi
, r_mop
);
2897 tcg_temp_free_i32(r_mop
);
2898 tcg_temp_free_i32(r_asi
);
2903 tcg_temp_free_i64(t64
);
2907 static TCGv
get_src1(DisasContext
*dc
, unsigned int insn
)
2909 unsigned int rs1
= GET_FIELD(insn
, 13, 17);
2910 return gen_load_gpr(dc
, rs1
);
2913 static TCGv
get_src2(DisasContext
*dc
, unsigned int insn
)
2915 if (IS_IMM
) { /* immediate */
2916 target_long simm
= GET_FIELDs(insn
, 19, 31);
2917 TCGv t
= get_temp_tl(dc
);
2918 tcg_gen_movi_tl(t
, simm
);
2920 } else { /* register */
2921 unsigned int rs2
= GET_FIELD(insn
, 27, 31);
2922 return gen_load_gpr(dc
, rs2
);
2926 #ifdef TARGET_SPARC64
2927 static void gen_fmovs(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2929 TCGv_i32 c32
, zero
, dst
, s1
, s2
;
2931 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2932 or fold the comparison down to 32 bits and use movcond_i32. Choose
2934 c32
= tcg_temp_new_i32();
2936 tcg_gen_extrl_i64_i32(c32
, cmp
->c1
);
2938 TCGv_i64 c64
= tcg_temp_new_i64();
2939 tcg_gen_setcond_i64(cmp
->cond
, c64
, cmp
->c1
, cmp
->c2
);
2940 tcg_gen_extrl_i64_i32(c32
, c64
);
2941 tcg_temp_free_i64(c64
);
2944 s1
= gen_load_fpr_F(dc
, rs
);
2945 s2
= gen_load_fpr_F(dc
, rd
);
2946 dst
= gen_dest_fpr_F(dc
);
2947 zero
= tcg_const_i32(0);
2949 tcg_gen_movcond_i32(TCG_COND_NE
, dst
, c32
, zero
, s1
, s2
);
2951 tcg_temp_free_i32(c32
);
2952 tcg_temp_free_i32(zero
);
2953 gen_store_fpr_F(dc
, rd
, dst
);
2956 static void gen_fmovd(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2958 TCGv_i64 dst
= gen_dest_fpr_D(dc
, rd
);
2959 tcg_gen_movcond_i64(cmp
->cond
, dst
, cmp
->c1
, cmp
->c2
,
2960 gen_load_fpr_D(dc
, rs
),
2961 gen_load_fpr_D(dc
, rd
));
2962 gen_store_fpr_D(dc
, rd
, dst
);
2965 static void gen_fmovq(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2967 int qd
= QFPREG(rd
);
2968 int qs
= QFPREG(rs
);
2970 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2], cmp
->c1
, cmp
->c2
,
2971 cpu_fpr
[qs
/ 2], cpu_fpr
[qd
/ 2]);
2972 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2 + 1], cmp
->c1
, cmp
->c2
,
2973 cpu_fpr
[qs
/ 2 + 1], cpu_fpr
[qd
/ 2 + 1]);
2975 gen_update_fprs_dirty(dc
, qd
);
2978 #ifndef CONFIG_USER_ONLY
2979 static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr
, TCGv_env cpu_env
)
2981 TCGv_i32 r_tl
= tcg_temp_new_i32();
2983 /* load env->tl into r_tl */
2984 tcg_gen_ld_i32(r_tl
, cpu_env
, offsetof(CPUSPARCState
, tl
));
2986 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2987 tcg_gen_andi_i32(r_tl
, r_tl
, MAXTL_MASK
);
2989 /* calculate offset to current trap state from env->ts, reuse r_tl */
2990 tcg_gen_muli_i32(r_tl
, r_tl
, sizeof (trap_state
));
2991 tcg_gen_addi_ptr(r_tsptr
, cpu_env
, offsetof(CPUSPARCState
, ts
));
2993 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2995 TCGv_ptr r_tl_tmp
= tcg_temp_new_ptr();
2996 tcg_gen_ext_i32_ptr(r_tl_tmp
, r_tl
);
2997 tcg_gen_add_ptr(r_tsptr
, r_tsptr
, r_tl_tmp
);
2998 tcg_temp_free_ptr(r_tl_tmp
);
3001 tcg_temp_free_i32(r_tl
);
3005 static void gen_edge(DisasContext
*dc
, TCGv dst
, TCGv s1
, TCGv s2
,
3006 int width
, bool cc
, bool left
)
3008 TCGv lo1
, lo2
, t1
, t2
;
3009 uint64_t amask
, tabl
, tabr
;
3010 int shift
, imask
, omask
;
3013 tcg_gen_mov_tl(cpu_cc_src
, s1
);
3014 tcg_gen_mov_tl(cpu_cc_src2
, s2
);
3015 tcg_gen_sub_tl(cpu_cc_dst
, s1
, s2
);
3016 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUB
);
3017 dc
->cc_op
= CC_OP_SUB
;
3020 /* Theory of operation: there are two tables, left and right (not to
3021 be confused with the left and right versions of the opcode). These
3022 are indexed by the low 3 bits of the inputs. To make things "easy",
3023 these tables are loaded into two constants, TABL and TABR below.
3024 The operation index = (input & imask) << shift calculates the index
3025 into the constant, while val = (table >> index) & omask calculates
3026 the value we're looking for. */
3033 tabl
= 0x80c0e0f0f8fcfeffULL
;
3034 tabr
= 0xff7f3f1f0f070301ULL
;
3036 tabl
= 0x0103070f1f3f7fffULL
;
3037 tabr
= 0xfffefcf8f0e0c080ULL
;
3057 tabl
= (2 << 2) | 3;
3058 tabr
= (3 << 2) | 1;
3060 tabl
= (1 << 2) | 3;
3061 tabr
= (3 << 2) | 2;
3068 lo1
= tcg_temp_new();
3069 lo2
= tcg_temp_new();
3070 tcg_gen_andi_tl(lo1
, s1
, imask
);
3071 tcg_gen_andi_tl(lo2
, s2
, imask
);
3072 tcg_gen_shli_tl(lo1
, lo1
, shift
);
3073 tcg_gen_shli_tl(lo2
, lo2
, shift
);
3075 t1
= tcg_const_tl(tabl
);
3076 t2
= tcg_const_tl(tabr
);
3077 tcg_gen_shr_tl(lo1
, t1
, lo1
);
3078 tcg_gen_shr_tl(lo2
, t2
, lo2
);
3079 tcg_gen_andi_tl(dst
, lo1
, omask
);
3080 tcg_gen_andi_tl(lo2
, lo2
, omask
);
3084 amask
&= 0xffffffffULL
;
3086 tcg_gen_andi_tl(s1
, s1
, amask
);
3087 tcg_gen_andi_tl(s2
, s2
, amask
);
3089 /* We want to compute
3090 dst = (s1 == s2 ? lo1 : lo1 & lo2).
3091 We've already done dst = lo1, so this reduces to
3092 dst &= (s1 == s2 ? -1 : lo2)
3097 tcg_gen_setcond_tl(TCG_COND_EQ
, t1
, s1
, s2
);
3098 tcg_gen_neg_tl(t1
, t1
);
3099 tcg_gen_or_tl(lo2
, lo2
, t1
);
3100 tcg_gen_and_tl(dst
, dst
, lo2
);
3108 static void gen_alignaddr(TCGv dst
, TCGv s1
, TCGv s2
, bool left
)
3110 TCGv tmp
= tcg_temp_new();
3112 tcg_gen_add_tl(tmp
, s1
, s2
);
3113 tcg_gen_andi_tl(dst
, tmp
, -8);
3115 tcg_gen_neg_tl(tmp
, tmp
);
3117 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, tmp
, 0, 3);
3122 static void gen_faligndata(TCGv dst
, TCGv gsr
, TCGv s1
, TCGv s2
)
3126 t1
= tcg_temp_new();
3127 t2
= tcg_temp_new();
3128 shift
= tcg_temp_new();
3130 tcg_gen_andi_tl(shift
, gsr
, 7);
3131 tcg_gen_shli_tl(shift
, shift
, 3);
3132 tcg_gen_shl_tl(t1
, s1
, shift
);
3134 /* A shift of 64 does not produce 0 in TCG. Divide this into a
3135 shift of (up to 63) followed by a constant shift of 1. */
3136 tcg_gen_xori_tl(shift
, shift
, 63);
3137 tcg_gen_shr_tl(t2
, s2
, shift
);
3138 tcg_gen_shri_tl(t2
, t2
, 1);
3140 tcg_gen_or_tl(dst
, t1
, t2
);
3144 tcg_temp_free(shift
);
3148 #define CHECK_IU_FEATURE(dc, FEATURE) \
3149 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3151 #define CHECK_FPU_FEATURE(dc, FEATURE) \
3152 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3155 /* before an instruction, dc->pc must be static */
3156 static void disas_sparc_insn(DisasContext
* dc
, unsigned int insn
)
3158 unsigned int opc
, rs1
, rs2
, rd
;
3159 TCGv cpu_src1
, cpu_src2
;
3160 TCGv_i32 cpu_src1_32
, cpu_src2_32
, cpu_dst_32
;
3161 TCGv_i64 cpu_src1_64
, cpu_src2_64
, cpu_dst_64
;
3164 opc
= GET_FIELD(insn
, 0, 1);
3165 rd
= GET_FIELD(insn
, 2, 6);
3168 case 0: /* branches/sethi */
3170 unsigned int xop
= GET_FIELD(insn
, 7, 9);
3173 #ifdef TARGET_SPARC64
3174 case 0x1: /* V9 BPcc */
3178 target
= GET_FIELD_SP(insn
, 0, 18);
3179 target
= sign_extend(target
, 19);
3181 cc
= GET_FIELD_SP(insn
, 20, 21);
3183 do_branch(dc
, target
, insn
, 0);
3185 do_branch(dc
, target
, insn
, 1);
3190 case 0x3: /* V9 BPr */
3192 target
= GET_FIELD_SP(insn
, 0, 13) |
3193 (GET_FIELD_SP(insn
, 20, 21) << 14);
3194 target
= sign_extend(target
, 16);
3196 cpu_src1
= get_src1(dc
, insn
);
3197 do_branch_reg(dc
, target
, insn
, cpu_src1
);
3200 case 0x5: /* V9 FBPcc */
3202 int cc
= GET_FIELD_SP(insn
, 20, 21);
3203 if (gen_trap_ifnofpu(dc
)) {
3206 target
= GET_FIELD_SP(insn
, 0, 18);
3207 target
= sign_extend(target
, 19);
3209 do_fbranch(dc
, target
, insn
, cc
);
3213 case 0x7: /* CBN+x */
3218 case 0x2: /* BN+x */
3220 target
= GET_FIELD(insn
, 10, 31);
3221 target
= sign_extend(target
, 22);
3223 do_branch(dc
, target
, insn
, 0);
3226 case 0x6: /* FBN+x */
3228 if (gen_trap_ifnofpu(dc
)) {
3231 target
= GET_FIELD(insn
, 10, 31);
3232 target
= sign_extend(target
, 22);
3234 do_fbranch(dc
, target
, insn
, 0);
3237 case 0x4: /* SETHI */
3238 /* Special-case %g0 because that's the canonical nop. */
3240 uint32_t value
= GET_FIELD(insn
, 10, 31);
3241 TCGv t
= gen_dest_gpr(dc
, rd
);
3242 tcg_gen_movi_tl(t
, value
<< 10);
3243 gen_store_gpr(dc
, rd
, t
);
3246 case 0x0: /* UNIMPL */
3255 target_long target
= GET_FIELDs(insn
, 2, 31) << 2;
3256 TCGv o7
= gen_dest_gpr(dc
, 15);
3258 tcg_gen_movi_tl(o7
, dc
->pc
);
3259 gen_store_gpr(dc
, 15, o7
);
3262 #ifdef TARGET_SPARC64
3263 if (unlikely(AM_CHECK(dc
))) {
3264 target
&= 0xffffffffULL
;
3270 case 2: /* FPU & Logical Operations */
3272 unsigned int xop
= GET_FIELD(insn
, 7, 12);
3273 TCGv cpu_dst
= get_temp_tl(dc
);
3276 if (xop
== 0x3a) { /* generate trap */
3277 int cond
= GET_FIELD(insn
, 3, 6);
3279 TCGLabel
*l1
= NULL
;
3290 /* Conditional trap. */
3292 #ifdef TARGET_SPARC64
3294 int cc
= GET_FIELD_SP(insn
, 11, 12);
3296 gen_compare(&cmp
, 0, cond
, dc
);
3297 } else if (cc
== 2) {
3298 gen_compare(&cmp
, 1, cond
, dc
);
3303 gen_compare(&cmp
, 0, cond
, dc
);
3305 l1
= gen_new_label();
3306 tcg_gen_brcond_tl(tcg_invert_cond(cmp
.cond
),
3307 cmp
.c1
, cmp
.c2
, l1
);
3311 mask
= ((dc
->def
->features
& CPU_FEATURE_HYPV
) && supervisor(dc
)
3312 ? UA2005_HTRAP_MASK
: V8_TRAP_MASK
);
3314 /* Don't use the normal temporaries, as they may well have
3315 gone out of scope with the branch above. While we're
3316 doing that we might as well pre-truncate to 32-bit. */
3317 trap
= tcg_temp_new_i32();
3319 rs1
= GET_FIELD_SP(insn
, 14, 18);
3321 rs2
= GET_FIELD_SP(insn
, 0, 7);
3323 tcg_gen_movi_i32(trap
, (rs2
& mask
) + TT_TRAP
);
3324 /* Signal that the trap value is fully constant. */
3327 TCGv t1
= gen_load_gpr(dc
, rs1
);
3328 tcg_gen_trunc_tl_i32(trap
, t1
);
3329 tcg_gen_addi_i32(trap
, trap
, rs2
);
3333 rs2
= GET_FIELD_SP(insn
, 0, 4);
3334 t1
= gen_load_gpr(dc
, rs1
);
3335 t2
= gen_load_gpr(dc
, rs2
);
3336 tcg_gen_add_tl(t1
, t1
, t2
);
3337 tcg_gen_trunc_tl_i32(trap
, t1
);
3340 tcg_gen_andi_i32(trap
, trap
, mask
);
3341 tcg_gen_addi_i32(trap
, trap
, TT_TRAP
);
3344 gen_helper_raise_exception(cpu_env
, trap
);
3345 tcg_temp_free_i32(trap
);
3348 /* An unconditional trap ends the TB. */
3352 /* A conditional trap falls through to the next insn. */
3356 } else if (xop
== 0x28) {
3357 rs1
= GET_FIELD(insn
, 13, 17);
3360 #ifndef TARGET_SPARC64
3361 case 0x01 ... 0x0e: /* undefined in the SPARCv8
3362 manual, rdy on the microSPARC
3364 case 0x0f: /* stbar in the SPARCv8 manual,
3365 rdy on the microSPARC II */
3366 case 0x10 ... 0x1f: /* implementation-dependent in the
3367 SPARCv8 manual, rdy on the
3370 if (rs1
== 0x11 && dc
->def
->features
& CPU_FEATURE_ASR17
) {
3371 TCGv t
= gen_dest_gpr(dc
, rd
);
3372 /* Read Asr17 for a Leon3 monoprocessor */
3373 tcg_gen_movi_tl(t
, (1 << 8) | (dc
->def
->nwindows
- 1));
3374 gen_store_gpr(dc
, rd
, t
);
3378 gen_store_gpr(dc
, rd
, cpu_y
);
3380 #ifdef TARGET_SPARC64
3381 case 0x2: /* V9 rdccr */
3383 gen_helper_rdccr(cpu_dst
, cpu_env
);
3384 gen_store_gpr(dc
, rd
, cpu_dst
);
3386 case 0x3: /* V9 rdasi */
3387 tcg_gen_movi_tl(cpu_dst
, dc
->asi
);
3388 gen_store_gpr(dc
, rd
, cpu_dst
);
3390 case 0x4: /* V9 rdtick */
3395 r_tickptr
= tcg_temp_new_ptr();
3396 r_const
= tcg_const_i32(dc
->mem_idx
);
3397 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3398 offsetof(CPUSPARCState
, tick
));
3399 gen_helper_tick_get_count(cpu_dst
, cpu_env
, r_tickptr
,
3401 tcg_temp_free_ptr(r_tickptr
);
3402 tcg_temp_free_i32(r_const
);
3403 gen_store_gpr(dc
, rd
, cpu_dst
);
3406 case 0x5: /* V9 rdpc */
3408 TCGv t
= gen_dest_gpr(dc
, rd
);
3409 if (unlikely(AM_CHECK(dc
))) {
3410 tcg_gen_movi_tl(t
, dc
->pc
& 0xffffffffULL
);
3412 tcg_gen_movi_tl(t
, dc
->pc
);
3414 gen_store_gpr(dc
, rd
, t
);
3417 case 0x6: /* V9 rdfprs */
3418 tcg_gen_ext_i32_tl(cpu_dst
, cpu_fprs
);
3419 gen_store_gpr(dc
, rd
, cpu_dst
);
3421 case 0xf: /* V9 membar */
3422 break; /* no effect */
3423 case 0x13: /* Graphics Status */
3424 if (gen_trap_ifnofpu(dc
)) {
3427 gen_store_gpr(dc
, rd
, cpu_gsr
);
3429 case 0x16: /* Softint */
3430 tcg_gen_ld32s_tl(cpu_dst
, cpu_env
,
3431 offsetof(CPUSPARCState
, softint
));
3432 gen_store_gpr(dc
, rd
, cpu_dst
);
3434 case 0x17: /* Tick compare */
3435 gen_store_gpr(dc
, rd
, cpu_tick_cmpr
);
3437 case 0x18: /* System tick */
3442 r_tickptr
= tcg_temp_new_ptr();
3443 r_const
= tcg_const_i32(dc
->mem_idx
);
3444 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3445 offsetof(CPUSPARCState
, stick
));
3446 gen_helper_tick_get_count(cpu_dst
, cpu_env
, r_tickptr
,
3448 tcg_temp_free_ptr(r_tickptr
);
3449 tcg_temp_free_i32(r_const
);
3450 gen_store_gpr(dc
, rd
, cpu_dst
);
3453 case 0x19: /* System tick compare */
3454 gen_store_gpr(dc
, rd
, cpu_stick_cmpr
);
3456 case 0x1a: /* UltraSPARC-T1 Strand status */
3457 /* XXX HYPV check maybe not enough, UA2005 & UA2007 describe
3458 * this ASR as impl. dep
3460 CHECK_IU_FEATURE(dc
, HYPV
);
3462 TCGv t
= gen_dest_gpr(dc
, rd
);
3463 tcg_gen_movi_tl(t
, 1UL);
3464 gen_store_gpr(dc
, rd
, t
);
3467 case 0x10: /* Performance Control */
3468 case 0x11: /* Performance Instrumentation Counter */
3469 case 0x12: /* Dispatch Control */
3470 case 0x14: /* Softint set, WO */
3471 case 0x15: /* Softint clear, WO */
3476 #if !defined(CONFIG_USER_ONLY)
3477 } else if (xop
== 0x29) { /* rdpsr / UA2005 rdhpr */
3478 #ifndef TARGET_SPARC64
3479 if (!supervisor(dc
)) {
3483 gen_helper_rdpsr(cpu_dst
, cpu_env
);
3485 CHECK_IU_FEATURE(dc
, HYPV
);
3486 if (!hypervisor(dc
))
3488 rs1
= GET_FIELD(insn
, 13, 17);
3491 tcg_gen_ld_i64(cpu_dst
, cpu_env
,
3492 offsetof(CPUSPARCState
, hpstate
));
3495 // gen_op_rdhtstate();
3498 tcg_gen_mov_tl(cpu_dst
, cpu_hintp
);
3501 tcg_gen_mov_tl(cpu_dst
, cpu_htba
);
3504 tcg_gen_mov_tl(cpu_dst
, cpu_hver
);
3506 case 31: // hstick_cmpr
3507 tcg_gen_mov_tl(cpu_dst
, cpu_hstick_cmpr
);
3513 gen_store_gpr(dc
, rd
, cpu_dst
);
3515 } else if (xop
== 0x2a) { /* rdwim / V9 rdpr */
3516 if (!supervisor(dc
)) {
3519 cpu_tmp0
= get_temp_tl(dc
);
3520 #ifdef TARGET_SPARC64
3521 rs1
= GET_FIELD(insn
, 13, 17);
3527 r_tsptr
= tcg_temp_new_ptr();
3528 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3529 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3530 offsetof(trap_state
, tpc
));
3531 tcg_temp_free_ptr(r_tsptr
);
3538 r_tsptr
= tcg_temp_new_ptr();
3539 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3540 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3541 offsetof(trap_state
, tnpc
));
3542 tcg_temp_free_ptr(r_tsptr
);
3549 r_tsptr
= tcg_temp_new_ptr();
3550 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3551 tcg_gen_ld_tl(cpu_tmp0
, r_tsptr
,
3552 offsetof(trap_state
, tstate
));
3553 tcg_temp_free_ptr(r_tsptr
);
3558 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3560 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
3561 tcg_gen_ld32s_tl(cpu_tmp0
, r_tsptr
,
3562 offsetof(trap_state
, tt
));
3563 tcg_temp_free_ptr(r_tsptr
);
3571 r_tickptr
= tcg_temp_new_ptr();
3572 r_const
= tcg_const_i32(dc
->mem_idx
);
3573 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
3574 offsetof(CPUSPARCState
, tick
));
3575 gen_helper_tick_get_count(cpu_tmp0
, cpu_env
,
3576 r_tickptr
, r_const
);
3577 tcg_temp_free_ptr(r_tickptr
);
3578 tcg_temp_free_i32(r_const
);
3582 tcg_gen_mov_tl(cpu_tmp0
, cpu_tbr
);
3585 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3586 offsetof(CPUSPARCState
, pstate
));
3589 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3590 offsetof(CPUSPARCState
, tl
));
3593 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3594 offsetof(CPUSPARCState
, psrpil
));
3597 gen_helper_rdcwp(cpu_tmp0
, cpu_env
);
3600 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3601 offsetof(CPUSPARCState
, cansave
));
3603 case 11: // canrestore
3604 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3605 offsetof(CPUSPARCState
, canrestore
));
3607 case 12: // cleanwin
3608 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3609 offsetof(CPUSPARCState
, cleanwin
));
3611 case 13: // otherwin
3612 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3613 offsetof(CPUSPARCState
, otherwin
));
3616 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3617 offsetof(CPUSPARCState
, wstate
));
3619 case 16: // UA2005 gl
3620 CHECK_IU_FEATURE(dc
, GL
);
3621 tcg_gen_ld32s_tl(cpu_tmp0
, cpu_env
,
3622 offsetof(CPUSPARCState
, gl
));
3624 case 26: // UA2005 strand status
3625 CHECK_IU_FEATURE(dc
, HYPV
);
3626 if (!hypervisor(dc
))
3628 tcg_gen_mov_tl(cpu_tmp0
, cpu_ssr
);
3631 tcg_gen_mov_tl(cpu_tmp0
, cpu_ver
);
3638 tcg_gen_ext_i32_tl(cpu_tmp0
, cpu_wim
);
3640 gen_store_gpr(dc
, rd
, cpu_tmp0
);
3642 } else if (xop
== 0x2b) { /* rdtbr / V9 flushw */
3643 #ifdef TARGET_SPARC64
3644 gen_helper_flushw(cpu_env
);
3646 if (!supervisor(dc
))
3648 gen_store_gpr(dc
, rd
, cpu_tbr
);
3652 } else if (xop
== 0x34) { /* FPU Operations */
3653 if (gen_trap_ifnofpu(dc
)) {
3656 gen_op_clear_ieee_excp_and_FTT();
3657 rs1
= GET_FIELD(insn
, 13, 17);
3658 rs2
= GET_FIELD(insn
, 27, 31);
3659 xop
= GET_FIELD(insn
, 18, 26);
3662 case 0x1: /* fmovs */
3663 cpu_src1_32
= gen_load_fpr_F(dc
, rs2
);
3664 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
3666 case 0x5: /* fnegs */
3667 gen_ne_fop_FF(dc
, rd
, rs2
, gen_helper_fnegs
);
3669 case 0x9: /* fabss */
3670 gen_ne_fop_FF(dc
, rd
, rs2
, gen_helper_fabss
);
3672 case 0x29: /* fsqrts */
3673 CHECK_FPU_FEATURE(dc
, FSQRT
);
3674 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fsqrts
);
3676 case 0x2a: /* fsqrtd */
3677 CHECK_FPU_FEATURE(dc
, FSQRT
);
3678 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fsqrtd
);
3680 case 0x2b: /* fsqrtq */
3681 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3682 gen_fop_QQ(dc
, rd
, rs2
, gen_helper_fsqrtq
);
3684 case 0x41: /* fadds */
3685 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fadds
);
3687 case 0x42: /* faddd */
3688 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_faddd
);
3690 case 0x43: /* faddq */
3691 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3692 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_faddq
);
3694 case 0x45: /* fsubs */
3695 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fsubs
);
3697 case 0x46: /* fsubd */
3698 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fsubd
);
3700 case 0x47: /* fsubq */
3701 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3702 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fsubq
);
3704 case 0x49: /* fmuls */
3705 CHECK_FPU_FEATURE(dc
, FMUL
);
3706 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fmuls
);
3708 case 0x4a: /* fmuld */
3709 CHECK_FPU_FEATURE(dc
, FMUL
);
3710 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld
);
3712 case 0x4b: /* fmulq */
3713 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3714 CHECK_FPU_FEATURE(dc
, FMUL
);
3715 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fmulq
);
3717 case 0x4d: /* fdivs */
3718 gen_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fdivs
);
3720 case 0x4e: /* fdivd */
3721 gen_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fdivd
);
3723 case 0x4f: /* fdivq */
3724 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3725 gen_fop_QQQ(dc
, rd
, rs1
, rs2
, gen_helper_fdivq
);
3727 case 0x69: /* fsmuld */
3728 CHECK_FPU_FEATURE(dc
, FSMULD
);
3729 gen_fop_DFF(dc
, rd
, rs1
, rs2
, gen_helper_fsmuld
);
3731 case 0x6e: /* fdmulq */
3732 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3733 gen_fop_QDD(dc
, rd
, rs1
, rs2
, gen_helper_fdmulq
);
3735 case 0xc4: /* fitos */
3736 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fitos
);
3738 case 0xc6: /* fdtos */
3739 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fdtos
);
3741 case 0xc7: /* fqtos */
3742 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3743 gen_fop_FQ(dc
, rd
, rs2
, gen_helper_fqtos
);
3745 case 0xc8: /* fitod */
3746 gen_ne_fop_DF(dc
, rd
, rs2
, gen_helper_fitod
);
3748 case 0xc9: /* fstod */
3749 gen_ne_fop_DF(dc
, rd
, rs2
, gen_helper_fstod
);
3751 case 0xcb: /* fqtod */
3752 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3753 gen_fop_DQ(dc
, rd
, rs2
, gen_helper_fqtod
);
3755 case 0xcc: /* fitoq */
3756 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3757 gen_ne_fop_QF(dc
, rd
, rs2
, gen_helper_fitoq
);
3759 case 0xcd: /* fstoq */
3760 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3761 gen_ne_fop_QF(dc
, rd
, rs2
, gen_helper_fstoq
);
3763 case 0xce: /* fdtoq */
3764 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3765 gen_ne_fop_QD(dc
, rd
, rs2
, gen_helper_fdtoq
);
3767 case 0xd1: /* fstoi */
3768 gen_fop_FF(dc
, rd
, rs2
, gen_helper_fstoi
);
3770 case 0xd2: /* fdtoi */
3771 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fdtoi
);
3773 case 0xd3: /* fqtoi */
3774 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3775 gen_fop_FQ(dc
, rd
, rs2
, gen_helper_fqtoi
);
3777 #ifdef TARGET_SPARC64
3778 case 0x2: /* V9 fmovd */
3779 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
3780 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
3782 case 0x3: /* V9 fmovq */
3783 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3784 gen_move_Q(dc
, rd
, rs2
);
3786 case 0x6: /* V9 fnegd */
3787 gen_ne_fop_DD(dc
, rd
, rs2
, gen_helper_fnegd
);
3789 case 0x7: /* V9 fnegq */
3790 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3791 gen_ne_fop_QQ(dc
, rd
, rs2
, gen_helper_fnegq
);
3793 case 0xa: /* V9 fabsd */
3794 gen_ne_fop_DD(dc
, rd
, rs2
, gen_helper_fabsd
);
3796 case 0xb: /* V9 fabsq */
3797 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3798 gen_ne_fop_QQ(dc
, rd
, rs2
, gen_helper_fabsq
);
3800 case 0x81: /* V9 fstox */
3801 gen_fop_DF(dc
, rd
, rs2
, gen_helper_fstox
);
3803 case 0x82: /* V9 fdtox */
3804 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fdtox
);
3806 case 0x83: /* V9 fqtox */
3807 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3808 gen_fop_DQ(dc
, rd
, rs2
, gen_helper_fqtox
);
3810 case 0x84: /* V9 fxtos */
3811 gen_fop_FD(dc
, rd
, rs2
, gen_helper_fxtos
);
3813 case 0x88: /* V9 fxtod */
3814 gen_fop_DD(dc
, rd
, rs2
, gen_helper_fxtod
);
3816 case 0x8c: /* V9 fxtoq */
3817 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3818 gen_ne_fop_QD(dc
, rd
, rs2
, gen_helper_fxtoq
);
3824 } else if (xop
== 0x35) { /* FPU Operations */
3825 #ifdef TARGET_SPARC64
3828 if (gen_trap_ifnofpu(dc
)) {
3831 gen_op_clear_ieee_excp_and_FTT();
3832 rs1
= GET_FIELD(insn
, 13, 17);
3833 rs2
= GET_FIELD(insn
, 27, 31);
3834 xop
= GET_FIELD(insn
, 18, 26);
3836 #ifdef TARGET_SPARC64
3840 cond = GET_FIELD_SP(insn, 10, 12); \
3841 cpu_src1 = get_src1(dc, insn); \
3842 gen_compare_reg(&cmp, cond, cpu_src1); \
3843 gen_fmov##sz(dc, &cmp, rd, rs2); \
3844 free_compare(&cmp); \
3847 if ((xop
& 0x11f) == 0x005) { /* V9 fmovsr */
3850 } else if ((xop
& 0x11f) == 0x006) { // V9 fmovdr
3853 } else if ((xop
& 0x11f) == 0x007) { // V9 fmovqr
3854 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3861 #ifdef TARGET_SPARC64
3862 #define FMOVCC(fcc, sz) \
3865 cond = GET_FIELD_SP(insn, 14, 17); \
3866 gen_fcompare(&cmp, fcc, cond); \
3867 gen_fmov##sz(dc, &cmp, rd, rs2); \
3868 free_compare(&cmp); \
3871 case 0x001: /* V9 fmovscc %fcc0 */
3874 case 0x002: /* V9 fmovdcc %fcc0 */
3877 case 0x003: /* V9 fmovqcc %fcc0 */
3878 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3881 case 0x041: /* V9 fmovscc %fcc1 */
3884 case 0x042: /* V9 fmovdcc %fcc1 */
3887 case 0x043: /* V9 fmovqcc %fcc1 */
3888 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3891 case 0x081: /* V9 fmovscc %fcc2 */
3894 case 0x082: /* V9 fmovdcc %fcc2 */
3897 case 0x083: /* V9 fmovqcc %fcc2 */
3898 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3901 case 0x0c1: /* V9 fmovscc %fcc3 */
3904 case 0x0c2: /* V9 fmovdcc %fcc3 */
3907 case 0x0c3: /* V9 fmovqcc %fcc3 */
3908 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3912 #define FMOVCC(xcc, sz) \
3915 cond = GET_FIELD_SP(insn, 14, 17); \
3916 gen_compare(&cmp, xcc, cond, dc); \
3917 gen_fmov##sz(dc, &cmp, rd, rs2); \
3918 free_compare(&cmp); \
3921 case 0x101: /* V9 fmovscc %icc */
3924 case 0x102: /* V9 fmovdcc %icc */
3927 case 0x103: /* V9 fmovqcc %icc */
3928 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3931 case 0x181: /* V9 fmovscc %xcc */
3934 case 0x182: /* V9 fmovdcc %xcc */
3937 case 0x183: /* V9 fmovqcc %xcc */
3938 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3943 case 0x51: /* fcmps, V9 %fcc */
3944 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
3945 cpu_src2_32
= gen_load_fpr_F(dc
, rs2
);
3946 gen_op_fcmps(rd
& 3, cpu_src1_32
, cpu_src2_32
);
3948 case 0x52: /* fcmpd, V9 %fcc */
3949 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
3950 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
3951 gen_op_fcmpd(rd
& 3, cpu_src1_64
, cpu_src2_64
);
3953 case 0x53: /* fcmpq, V9 %fcc */
3954 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3955 gen_op_load_fpr_QT0(QFPREG(rs1
));
3956 gen_op_load_fpr_QT1(QFPREG(rs2
));
3957 gen_op_fcmpq(rd
& 3);
3959 case 0x55: /* fcmpes, V9 %fcc */
3960 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
3961 cpu_src2_32
= gen_load_fpr_F(dc
, rs2
);
3962 gen_op_fcmpes(rd
& 3, cpu_src1_32
, cpu_src2_32
);
3964 case 0x56: /* fcmped, V9 %fcc */
3965 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
3966 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
3967 gen_op_fcmped(rd
& 3, cpu_src1_64
, cpu_src2_64
);
3969 case 0x57: /* fcmpeq, V9 %fcc */
3970 CHECK_FPU_FEATURE(dc
, FLOAT128
);
3971 gen_op_load_fpr_QT0(QFPREG(rs1
));
3972 gen_op_load_fpr_QT1(QFPREG(rs2
));
3973 gen_op_fcmpeq(rd
& 3);
3978 } else if (xop
== 0x2) {
3979 TCGv dst
= gen_dest_gpr(dc
, rd
);
3980 rs1
= GET_FIELD(insn
, 13, 17);
3982 /* clr/mov shortcut : or %g0, x, y -> mov x, y */
3983 if (IS_IMM
) { /* immediate */
3984 simm
= GET_FIELDs(insn
, 19, 31);
3985 tcg_gen_movi_tl(dst
, simm
);
3986 gen_store_gpr(dc
, rd
, dst
);
3987 } else { /* register */
3988 rs2
= GET_FIELD(insn
, 27, 31);
3990 tcg_gen_movi_tl(dst
, 0);
3991 gen_store_gpr(dc
, rd
, dst
);
3993 cpu_src2
= gen_load_gpr(dc
, rs2
);
3994 gen_store_gpr(dc
, rd
, cpu_src2
);
3998 cpu_src1
= get_src1(dc
, insn
);
3999 if (IS_IMM
) { /* immediate */
4000 simm
= GET_FIELDs(insn
, 19, 31);
4001 tcg_gen_ori_tl(dst
, cpu_src1
, simm
);
4002 gen_store_gpr(dc
, rd
, dst
);
4003 } else { /* register */
4004 rs2
= GET_FIELD(insn
, 27, 31);
4006 /* mov shortcut: or x, %g0, y -> mov x, y */
4007 gen_store_gpr(dc
, rd
, cpu_src1
);
4009 cpu_src2
= gen_load_gpr(dc
, rs2
);
4010 tcg_gen_or_tl(dst
, cpu_src1
, cpu_src2
);
4011 gen_store_gpr(dc
, rd
, dst
);
4015 #ifdef TARGET_SPARC64
4016 } else if (xop
== 0x25) { /* sll, V9 sllx */
4017 cpu_src1
= get_src1(dc
, insn
);
4018 if (IS_IMM
) { /* immediate */
4019 simm
= GET_FIELDs(insn
, 20, 31);
4020 if (insn
& (1 << 12)) {
4021 tcg_gen_shli_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4023 tcg_gen_shli_i64(cpu_dst
, cpu_src1
, simm
& 0x1f);
4025 } else { /* register */
4026 rs2
= GET_FIELD(insn
, 27, 31);
4027 cpu_src2
= gen_load_gpr(dc
, rs2
);
4028 cpu_tmp0
= get_temp_tl(dc
);
4029 if (insn
& (1 << 12)) {
4030 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4032 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4034 tcg_gen_shl_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4036 gen_store_gpr(dc
, rd
, cpu_dst
);
4037 } else if (xop
== 0x26) { /* srl, V9 srlx */
4038 cpu_src1
= get_src1(dc
, insn
);
4039 if (IS_IMM
) { /* immediate */
4040 simm
= GET_FIELDs(insn
, 20, 31);
4041 if (insn
& (1 << 12)) {
4042 tcg_gen_shri_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4044 tcg_gen_andi_i64(cpu_dst
, cpu_src1
, 0xffffffffULL
);
4045 tcg_gen_shri_i64(cpu_dst
, cpu_dst
, simm
& 0x1f);
4047 } else { /* register */
4048 rs2
= GET_FIELD(insn
, 27, 31);
4049 cpu_src2
= gen_load_gpr(dc
, rs2
);
4050 cpu_tmp0
= get_temp_tl(dc
);
4051 if (insn
& (1 << 12)) {
4052 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4053 tcg_gen_shr_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4055 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4056 tcg_gen_andi_i64(cpu_dst
, cpu_src1
, 0xffffffffULL
);
4057 tcg_gen_shr_i64(cpu_dst
, cpu_dst
, cpu_tmp0
);
4060 gen_store_gpr(dc
, rd
, cpu_dst
);
4061 } else if (xop
== 0x27) { /* sra, V9 srax */
4062 cpu_src1
= get_src1(dc
, insn
);
4063 if (IS_IMM
) { /* immediate */
4064 simm
= GET_FIELDs(insn
, 20, 31);
4065 if (insn
& (1 << 12)) {
4066 tcg_gen_sari_i64(cpu_dst
, cpu_src1
, simm
& 0x3f);
4068 tcg_gen_ext32s_i64(cpu_dst
, cpu_src1
);
4069 tcg_gen_sari_i64(cpu_dst
, cpu_dst
, simm
& 0x1f);
4071 } else { /* register */
4072 rs2
= GET_FIELD(insn
, 27, 31);
4073 cpu_src2
= gen_load_gpr(dc
, rs2
);
4074 cpu_tmp0
= get_temp_tl(dc
);
4075 if (insn
& (1 << 12)) {
4076 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x3f);
4077 tcg_gen_sar_i64(cpu_dst
, cpu_src1
, cpu_tmp0
);
4079 tcg_gen_andi_i64(cpu_tmp0
, cpu_src2
, 0x1f);
4080 tcg_gen_ext32s_i64(cpu_dst
, cpu_src1
);
4081 tcg_gen_sar_i64(cpu_dst
, cpu_dst
, cpu_tmp0
);
4084 gen_store_gpr(dc
, rd
, cpu_dst
);
4086 } else if (xop
< 0x36) {
4088 cpu_src1
= get_src1(dc
, insn
);
4089 cpu_src2
= get_src2(dc
, insn
);
4090 switch (xop
& ~0x10) {
4093 gen_op_add_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4094 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADD
);
4095 dc
->cc_op
= CC_OP_ADD
;
4097 tcg_gen_add_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4101 tcg_gen_and_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4103 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4104 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4105 dc
->cc_op
= CC_OP_LOGIC
;
4109 tcg_gen_or_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4111 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4112 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4113 dc
->cc_op
= CC_OP_LOGIC
;
4117 tcg_gen_xor_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4119 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4120 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4121 dc
->cc_op
= CC_OP_LOGIC
;
4126 gen_op_sub_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4127 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_SUB
);
4128 dc
->cc_op
= CC_OP_SUB
;
4130 tcg_gen_sub_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4133 case 0x5: /* andn */
4134 tcg_gen_andc_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4136 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4137 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4138 dc
->cc_op
= CC_OP_LOGIC
;
4142 tcg_gen_orc_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4144 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4145 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4146 dc
->cc_op
= CC_OP_LOGIC
;
4149 case 0x7: /* xorn */
4150 tcg_gen_eqv_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4152 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4153 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4154 dc
->cc_op
= CC_OP_LOGIC
;
4157 case 0x8: /* addx, V9 addc */
4158 gen_op_addx_int(dc
, cpu_dst
, cpu_src1
, cpu_src2
,
4161 #ifdef TARGET_SPARC64
4162 case 0x9: /* V9 mulx */
4163 tcg_gen_mul_i64(cpu_dst
, cpu_src1
, cpu_src2
);
4166 case 0xa: /* umul */
4167 CHECK_IU_FEATURE(dc
, MUL
);
4168 gen_op_umul(cpu_dst
, cpu_src1
, cpu_src2
);
4170 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4171 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4172 dc
->cc_op
= CC_OP_LOGIC
;
4175 case 0xb: /* smul */
4176 CHECK_IU_FEATURE(dc
, MUL
);
4177 gen_op_smul(cpu_dst
, cpu_src1
, cpu_src2
);
4179 tcg_gen_mov_tl(cpu_cc_dst
, cpu_dst
);
4180 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_LOGIC
);
4181 dc
->cc_op
= CC_OP_LOGIC
;
4184 case 0xc: /* subx, V9 subc */
4185 gen_op_subx_int(dc
, cpu_dst
, cpu_src1
, cpu_src2
,
4188 #ifdef TARGET_SPARC64
4189 case 0xd: /* V9 udivx */
4190 gen_helper_udivx(cpu_dst
, cpu_env
, cpu_src1
, cpu_src2
);
4193 case 0xe: /* udiv */
4194 CHECK_IU_FEATURE(dc
, DIV
);
4196 gen_helper_udiv_cc(cpu_dst
, cpu_env
, cpu_src1
,
4198 dc
->cc_op
= CC_OP_DIV
;
4200 gen_helper_udiv(cpu_dst
, cpu_env
, cpu_src1
,
4204 case 0xf: /* sdiv */
4205 CHECK_IU_FEATURE(dc
, DIV
);
4207 gen_helper_sdiv_cc(cpu_dst
, cpu_env
, cpu_src1
,
4209 dc
->cc_op
= CC_OP_DIV
;
4211 gen_helper_sdiv(cpu_dst
, cpu_env
, cpu_src1
,
4218 gen_store_gpr(dc
, rd
, cpu_dst
);
4220 cpu_src1
= get_src1(dc
, insn
);
4221 cpu_src2
= get_src2(dc
, insn
);
4223 case 0x20: /* taddcc */
4224 gen_op_add_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4225 gen_store_gpr(dc
, rd
, cpu_dst
);
4226 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_TADD
);
4227 dc
->cc_op
= CC_OP_TADD
;
4229 case 0x21: /* tsubcc */
4230 gen_op_sub_cc(cpu_dst
, cpu_src1
, cpu_src2
);
4231 gen_store_gpr(dc
, rd
, cpu_dst
);
4232 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_TSUB
);
4233 dc
->cc_op
= CC_OP_TSUB
;
4235 case 0x22: /* taddcctv */
4236 gen_helper_taddcctv(cpu_dst
, cpu_env
,
4237 cpu_src1
, cpu_src2
);
4238 gen_store_gpr(dc
, rd
, cpu_dst
);
4239 dc
->cc_op
= CC_OP_TADDTV
;
4241 case 0x23: /* tsubcctv */
4242 gen_helper_tsubcctv(cpu_dst
, cpu_env
,
4243 cpu_src1
, cpu_src2
);
4244 gen_store_gpr(dc
, rd
, cpu_dst
);
4245 dc
->cc_op
= CC_OP_TSUBTV
;
4247 case 0x24: /* mulscc */
4249 gen_op_mulscc(cpu_dst
, cpu_src1
, cpu_src2
);
4250 gen_store_gpr(dc
, rd
, cpu_dst
);
4251 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_ADD
);
4252 dc
->cc_op
= CC_OP_ADD
;
4254 #ifndef TARGET_SPARC64
4255 case 0x25: /* sll */
4256 if (IS_IMM
) { /* immediate */
4257 simm
= GET_FIELDs(insn
, 20, 31);
4258 tcg_gen_shli_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4259 } else { /* register */
4260 cpu_tmp0
= get_temp_tl(dc
);
4261 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4262 tcg_gen_shl_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4264 gen_store_gpr(dc
, rd
, cpu_dst
);
4266 case 0x26: /* srl */
4267 if (IS_IMM
) { /* immediate */
4268 simm
= GET_FIELDs(insn
, 20, 31);
4269 tcg_gen_shri_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4270 } else { /* register */
4271 cpu_tmp0
= get_temp_tl(dc
);
4272 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4273 tcg_gen_shr_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4275 gen_store_gpr(dc
, rd
, cpu_dst
);
4277 case 0x27: /* sra */
4278 if (IS_IMM
) { /* immediate */
4279 simm
= GET_FIELDs(insn
, 20, 31);
4280 tcg_gen_sari_tl(cpu_dst
, cpu_src1
, simm
& 0x1f);
4281 } else { /* register */
4282 cpu_tmp0
= get_temp_tl(dc
);
4283 tcg_gen_andi_tl(cpu_tmp0
, cpu_src2
, 0x1f);
4284 tcg_gen_sar_tl(cpu_dst
, cpu_src1
, cpu_tmp0
);
4286 gen_store_gpr(dc
, rd
, cpu_dst
);
4291 cpu_tmp0
= get_temp_tl(dc
);
4294 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4295 tcg_gen_andi_tl(cpu_y
, cpu_tmp0
, 0xffffffff);
4297 #ifndef TARGET_SPARC64
4298 case 0x01 ... 0x0f: /* undefined in the
4302 case 0x10 ... 0x1f: /* implementation-dependent
4306 if ((rd
== 0x13) && (dc
->def
->features
&
4307 CPU_FEATURE_POWERDOWN
)) {
4308 /* LEON3 power-down */
4310 gen_helper_power_down(cpu_env
);
4314 case 0x2: /* V9 wrccr */
4315 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4316 gen_helper_wrccr(cpu_env
, cpu_tmp0
);
4317 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_FLAGS
);
4318 dc
->cc_op
= CC_OP_FLAGS
;
4320 case 0x3: /* V9 wrasi */
4321 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4322 tcg_gen_andi_tl(cpu_tmp0
, cpu_tmp0
, 0xff);
4323 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4324 offsetof(CPUSPARCState
, asi
));
4325 /* End TB to notice changed ASI. */
4331 case 0x6: /* V9 wrfprs */
4332 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4333 tcg_gen_trunc_tl_i32(cpu_fprs
, cpu_tmp0
);
4340 case 0xf: /* V9 sir, nop if user */
4341 #if !defined(CONFIG_USER_ONLY)
4342 if (supervisor(dc
)) {
4347 case 0x13: /* Graphics Status */
4348 if (gen_trap_ifnofpu(dc
)) {
4351 tcg_gen_xor_tl(cpu_gsr
, cpu_src1
, cpu_src2
);
4353 case 0x14: /* Softint set */
4354 if (!supervisor(dc
))
4356 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4357 gen_helper_set_softint(cpu_env
, cpu_tmp0
);
4359 case 0x15: /* Softint clear */
4360 if (!supervisor(dc
))
4362 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4363 gen_helper_clear_softint(cpu_env
, cpu_tmp0
);
4365 case 0x16: /* Softint write */
4366 if (!supervisor(dc
))
4368 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4369 gen_helper_write_softint(cpu_env
, cpu_tmp0
);
4371 case 0x17: /* Tick compare */
4372 #if !defined(CONFIG_USER_ONLY)
4373 if (!supervisor(dc
))
4379 tcg_gen_xor_tl(cpu_tick_cmpr
, cpu_src1
,
4381 r_tickptr
= tcg_temp_new_ptr();
4382 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4383 offsetof(CPUSPARCState
, tick
));
4384 gen_helper_tick_set_limit(r_tickptr
,
4386 tcg_temp_free_ptr(r_tickptr
);
4389 case 0x18: /* System tick */
4390 #if !defined(CONFIG_USER_ONLY)
4391 if (!supervisor(dc
))
4397 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
,
4399 r_tickptr
= tcg_temp_new_ptr();
4400 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4401 offsetof(CPUSPARCState
, stick
));
4402 gen_helper_tick_set_count(r_tickptr
,
4404 tcg_temp_free_ptr(r_tickptr
);
4407 case 0x19: /* System tick compare */
4408 #if !defined(CONFIG_USER_ONLY)
4409 if (!supervisor(dc
))
4415 tcg_gen_xor_tl(cpu_stick_cmpr
, cpu_src1
,
4417 r_tickptr
= tcg_temp_new_ptr();
4418 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4419 offsetof(CPUSPARCState
, stick
));
4420 gen_helper_tick_set_limit(r_tickptr
,
4422 tcg_temp_free_ptr(r_tickptr
);
4426 case 0x10: /* Performance Control */
4427 case 0x11: /* Performance Instrumentation
4429 case 0x12: /* Dispatch Control */
4436 #if !defined(CONFIG_USER_ONLY)
4437 case 0x31: /* wrpsr, V9 saved, restored */
4439 if (!supervisor(dc
))
4441 #ifdef TARGET_SPARC64
4444 gen_helper_saved(cpu_env
);
4447 gen_helper_restored(cpu_env
);
4449 case 2: /* UA2005 allclean */
4450 case 3: /* UA2005 otherw */
4451 case 4: /* UA2005 normalw */
4452 case 5: /* UA2005 invalw */
4458 cpu_tmp0
= get_temp_tl(dc
);
4459 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4460 gen_helper_wrpsr(cpu_env
, cpu_tmp0
);
4461 tcg_gen_movi_i32(cpu_cc_op
, CC_OP_FLAGS
);
4462 dc
->cc_op
= CC_OP_FLAGS
;
4470 case 0x32: /* wrwim, V9 wrpr */
4472 if (!supervisor(dc
))
4474 cpu_tmp0
= get_temp_tl(dc
);
4475 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4476 #ifdef TARGET_SPARC64
4482 r_tsptr
= tcg_temp_new_ptr();
4483 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4484 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4485 offsetof(trap_state
, tpc
));
4486 tcg_temp_free_ptr(r_tsptr
);
4493 r_tsptr
= tcg_temp_new_ptr();
4494 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4495 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4496 offsetof(trap_state
, tnpc
));
4497 tcg_temp_free_ptr(r_tsptr
);
4504 r_tsptr
= tcg_temp_new_ptr();
4505 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4506 tcg_gen_st_tl(cpu_tmp0
, r_tsptr
,
4507 offsetof(trap_state
,
4509 tcg_temp_free_ptr(r_tsptr
);
4516 r_tsptr
= tcg_temp_new_ptr();
4517 gen_load_trap_state_at_tl(r_tsptr
, cpu_env
);
4518 tcg_gen_st32_tl(cpu_tmp0
, r_tsptr
,
4519 offsetof(trap_state
, tt
));
4520 tcg_temp_free_ptr(r_tsptr
);
4527 r_tickptr
= tcg_temp_new_ptr();
4528 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4529 offsetof(CPUSPARCState
, tick
));
4530 gen_helper_tick_set_count(r_tickptr
,
4532 tcg_temp_free_ptr(r_tickptr
);
4536 tcg_gen_mov_tl(cpu_tbr
, cpu_tmp0
);
4540 gen_helper_wrpstate(cpu_env
, cpu_tmp0
);
4541 dc
->npc
= DYNAMIC_PC
;
4545 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4546 offsetof(CPUSPARCState
, tl
));
4547 dc
->npc
= DYNAMIC_PC
;
4550 gen_helper_wrpil(cpu_env
, cpu_tmp0
);
4553 gen_helper_wrcwp(cpu_env
, cpu_tmp0
);
4556 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4557 offsetof(CPUSPARCState
,
4560 case 11: // canrestore
4561 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4562 offsetof(CPUSPARCState
,
4565 case 12: // cleanwin
4566 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4567 offsetof(CPUSPARCState
,
4570 case 13: // otherwin
4571 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4572 offsetof(CPUSPARCState
,
4576 tcg_gen_st32_tl(cpu_tmp0
, cpu_env
,
4577 offsetof(CPUSPARCState
,
4580 case 16: // UA2005 gl
4581 CHECK_IU_FEATURE(dc
, GL
);
4582 gen_helper_wrgl(cpu_env
, cpu_tmp0
);
4584 case 26: // UA2005 strand status
4585 CHECK_IU_FEATURE(dc
, HYPV
);
4586 if (!hypervisor(dc
))
4588 tcg_gen_mov_tl(cpu_ssr
, cpu_tmp0
);
4594 tcg_gen_trunc_tl_i32(cpu_wim
, cpu_tmp0
);
4595 if (dc
->def
->nwindows
!= 32) {
4596 tcg_gen_andi_tl(cpu_wim
, cpu_wim
,
4597 (1 << dc
->def
->nwindows
) - 1);
4602 case 0x33: /* wrtbr, UA2005 wrhpr */
4604 #ifndef TARGET_SPARC64
4605 if (!supervisor(dc
))
4607 tcg_gen_xor_tl(cpu_tbr
, cpu_src1
, cpu_src2
);
4609 CHECK_IU_FEATURE(dc
, HYPV
);
4610 if (!hypervisor(dc
))
4612 cpu_tmp0
= get_temp_tl(dc
);
4613 tcg_gen_xor_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
4616 tcg_gen_st_i64(cpu_tmp0
, cpu_env
,
4617 offsetof(CPUSPARCState
,
4625 // XXX gen_op_wrhtstate();
4628 tcg_gen_mov_tl(cpu_hintp
, cpu_tmp0
);
4631 tcg_gen_mov_tl(cpu_htba
, cpu_tmp0
);
4633 case 31: // hstick_cmpr
4637 tcg_gen_mov_tl(cpu_hstick_cmpr
, cpu_tmp0
);
4638 r_tickptr
= tcg_temp_new_ptr();
4639 tcg_gen_ld_ptr(r_tickptr
, cpu_env
,
4640 offsetof(CPUSPARCState
, hstick
));
4641 gen_helper_tick_set_limit(r_tickptr
,
4643 tcg_temp_free_ptr(r_tickptr
);
4646 case 6: // hver readonly
4654 #ifdef TARGET_SPARC64
4655 case 0x2c: /* V9 movcc */
4657 int cc
= GET_FIELD_SP(insn
, 11, 12);
4658 int cond
= GET_FIELD_SP(insn
, 14, 17);
4662 if (insn
& (1 << 18)) {
4664 gen_compare(&cmp
, 0, cond
, dc
);
4665 } else if (cc
== 2) {
4666 gen_compare(&cmp
, 1, cond
, dc
);
4671 gen_fcompare(&cmp
, cc
, cond
);
4674 /* The get_src2 above loaded the normal 13-bit
4675 immediate field, not the 11-bit field we have
4676 in movcc. But it did handle the reg case. */
4678 simm
= GET_FIELD_SPs(insn
, 0, 10);
4679 tcg_gen_movi_tl(cpu_src2
, simm
);
4682 dst
= gen_load_gpr(dc
, rd
);
4683 tcg_gen_movcond_tl(cmp
.cond
, dst
,
4687 gen_store_gpr(dc
, rd
, dst
);
4690 case 0x2d: /* V9 sdivx */
4691 gen_helper_sdivx(cpu_dst
, cpu_env
, cpu_src1
, cpu_src2
);
4692 gen_store_gpr(dc
, rd
, cpu_dst
);
4694 case 0x2e: /* V9 popc */
4695 tcg_gen_ctpop_tl(cpu_dst
, cpu_src2
);
4696 gen_store_gpr(dc
, rd
, cpu_dst
);
4698 case 0x2f: /* V9 movr */
4700 int cond
= GET_FIELD_SP(insn
, 10, 12);
4704 gen_compare_reg(&cmp
, cond
, cpu_src1
);
4706 /* The get_src2 above loaded the normal 13-bit
4707 immediate field, not the 10-bit field we have
4708 in movr. But it did handle the reg case. */
4710 simm
= GET_FIELD_SPs(insn
, 0, 9);
4711 tcg_gen_movi_tl(cpu_src2
, simm
);
4714 dst
= gen_load_gpr(dc
, rd
);
4715 tcg_gen_movcond_tl(cmp
.cond
, dst
,
4719 gen_store_gpr(dc
, rd
, dst
);
4727 } else if (xop
== 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4728 #ifdef TARGET_SPARC64
4729 int opf
= GET_FIELD_SP(insn
, 5, 13);
4730 rs1
= GET_FIELD(insn
, 13, 17);
4731 rs2
= GET_FIELD(insn
, 27, 31);
4732 if (gen_trap_ifnofpu(dc
)) {
4737 case 0x000: /* VIS I edge8cc */
4738 CHECK_FPU_FEATURE(dc
, VIS1
);
4739 cpu_src1
= gen_load_gpr(dc
, rs1
);
4740 cpu_src2
= gen_load_gpr(dc
, rs2
);
4741 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 1, 0);
4742 gen_store_gpr(dc
, rd
, cpu_dst
);
4744 case 0x001: /* VIS II edge8n */
4745 CHECK_FPU_FEATURE(dc
, VIS2
);
4746 cpu_src1
= gen_load_gpr(dc
, rs1
);
4747 cpu_src2
= gen_load_gpr(dc
, rs2
);
4748 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 0, 0);
4749 gen_store_gpr(dc
, rd
, cpu_dst
);
4751 case 0x002: /* VIS I edge8lcc */
4752 CHECK_FPU_FEATURE(dc
, VIS1
);
4753 cpu_src1
= gen_load_gpr(dc
, rs1
);
4754 cpu_src2
= gen_load_gpr(dc
, rs2
);
4755 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 1, 1);
4756 gen_store_gpr(dc
, rd
, cpu_dst
);
4758 case 0x003: /* VIS II edge8ln */
4759 CHECK_FPU_FEATURE(dc
, VIS2
);
4760 cpu_src1
= gen_load_gpr(dc
, rs1
);
4761 cpu_src2
= gen_load_gpr(dc
, rs2
);
4762 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 8, 0, 1);
4763 gen_store_gpr(dc
, rd
, cpu_dst
);
4765 case 0x004: /* VIS I edge16cc */
4766 CHECK_FPU_FEATURE(dc
, VIS1
);
4767 cpu_src1
= gen_load_gpr(dc
, rs1
);
4768 cpu_src2
= gen_load_gpr(dc
, rs2
);
4769 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 1, 0);
4770 gen_store_gpr(dc
, rd
, cpu_dst
);
4772 case 0x005: /* VIS II edge16n */
4773 CHECK_FPU_FEATURE(dc
, VIS2
);
4774 cpu_src1
= gen_load_gpr(dc
, rs1
);
4775 cpu_src2
= gen_load_gpr(dc
, rs2
);
4776 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 0, 0);
4777 gen_store_gpr(dc
, rd
, cpu_dst
);
4779 case 0x006: /* VIS I edge16lcc */
4780 CHECK_FPU_FEATURE(dc
, VIS1
);
4781 cpu_src1
= gen_load_gpr(dc
, rs1
);
4782 cpu_src2
= gen_load_gpr(dc
, rs2
);
4783 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 1, 1);
4784 gen_store_gpr(dc
, rd
, cpu_dst
);
4786 case 0x007: /* VIS II edge16ln */
4787 CHECK_FPU_FEATURE(dc
, VIS2
);
4788 cpu_src1
= gen_load_gpr(dc
, rs1
);
4789 cpu_src2
= gen_load_gpr(dc
, rs2
);
4790 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 16, 0, 1);
4791 gen_store_gpr(dc
, rd
, cpu_dst
);
4793 case 0x008: /* VIS I edge32cc */
4794 CHECK_FPU_FEATURE(dc
, VIS1
);
4795 cpu_src1
= gen_load_gpr(dc
, rs1
);
4796 cpu_src2
= gen_load_gpr(dc
, rs2
);
4797 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 1, 0);
4798 gen_store_gpr(dc
, rd
, cpu_dst
);
4800 case 0x009: /* VIS II edge32n */
4801 CHECK_FPU_FEATURE(dc
, VIS2
);
4802 cpu_src1
= gen_load_gpr(dc
, rs1
);
4803 cpu_src2
= gen_load_gpr(dc
, rs2
);
4804 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 0, 0);
4805 gen_store_gpr(dc
, rd
, cpu_dst
);
4807 case 0x00a: /* VIS I edge32lcc */
4808 CHECK_FPU_FEATURE(dc
, VIS1
);
4809 cpu_src1
= gen_load_gpr(dc
, rs1
);
4810 cpu_src2
= gen_load_gpr(dc
, rs2
);
4811 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 1, 1);
4812 gen_store_gpr(dc
, rd
, cpu_dst
);
4814 case 0x00b: /* VIS II edge32ln */
4815 CHECK_FPU_FEATURE(dc
, VIS2
);
4816 cpu_src1
= gen_load_gpr(dc
, rs1
);
4817 cpu_src2
= gen_load_gpr(dc
, rs2
);
4818 gen_edge(dc
, cpu_dst
, cpu_src1
, cpu_src2
, 32, 0, 1);
4819 gen_store_gpr(dc
, rd
, cpu_dst
);
4821 case 0x010: /* VIS I array8 */
4822 CHECK_FPU_FEATURE(dc
, VIS1
);
4823 cpu_src1
= gen_load_gpr(dc
, rs1
);
4824 cpu_src2
= gen_load_gpr(dc
, rs2
);
4825 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4826 gen_store_gpr(dc
, rd
, cpu_dst
);
4828 case 0x012: /* VIS I array16 */
4829 CHECK_FPU_FEATURE(dc
, VIS1
);
4830 cpu_src1
= gen_load_gpr(dc
, rs1
);
4831 cpu_src2
= gen_load_gpr(dc
, rs2
);
4832 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4833 tcg_gen_shli_i64(cpu_dst
, cpu_dst
, 1);
4834 gen_store_gpr(dc
, rd
, cpu_dst
);
4836 case 0x014: /* VIS I array32 */
4837 CHECK_FPU_FEATURE(dc
, VIS1
);
4838 cpu_src1
= gen_load_gpr(dc
, rs1
);
4839 cpu_src2
= gen_load_gpr(dc
, rs2
);
4840 gen_helper_array8(cpu_dst
, cpu_src1
, cpu_src2
);
4841 tcg_gen_shli_i64(cpu_dst
, cpu_dst
, 2);
4842 gen_store_gpr(dc
, rd
, cpu_dst
);
4844 case 0x018: /* VIS I alignaddr */
4845 CHECK_FPU_FEATURE(dc
, VIS1
);
4846 cpu_src1
= gen_load_gpr(dc
, rs1
);
4847 cpu_src2
= gen_load_gpr(dc
, rs2
);
4848 gen_alignaddr(cpu_dst
, cpu_src1
, cpu_src2
, 0);
4849 gen_store_gpr(dc
, rd
, cpu_dst
);
4851 case 0x01a: /* VIS I alignaddrl */
4852 CHECK_FPU_FEATURE(dc
, VIS1
);
4853 cpu_src1
= gen_load_gpr(dc
, rs1
);
4854 cpu_src2
= gen_load_gpr(dc
, rs2
);
4855 gen_alignaddr(cpu_dst
, cpu_src1
, cpu_src2
, 1);
4856 gen_store_gpr(dc
, rd
, cpu_dst
);
4858 case 0x019: /* VIS II bmask */
4859 CHECK_FPU_FEATURE(dc
, VIS2
);
4860 cpu_src1
= gen_load_gpr(dc
, rs1
);
4861 cpu_src2
= gen_load_gpr(dc
, rs2
);
4862 tcg_gen_add_tl(cpu_dst
, cpu_src1
, cpu_src2
);
4863 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, cpu_dst
, 32, 32);
4864 gen_store_gpr(dc
, rd
, cpu_dst
);
4866 case 0x020: /* VIS I fcmple16 */
4867 CHECK_FPU_FEATURE(dc
, VIS1
);
4868 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4869 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4870 gen_helper_fcmple16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4871 gen_store_gpr(dc
, rd
, cpu_dst
);
4873 case 0x022: /* VIS I fcmpne16 */
4874 CHECK_FPU_FEATURE(dc
, VIS1
);
4875 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4876 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4877 gen_helper_fcmpne16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4878 gen_store_gpr(dc
, rd
, cpu_dst
);
4880 case 0x024: /* VIS I fcmple32 */
4881 CHECK_FPU_FEATURE(dc
, VIS1
);
4882 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4883 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4884 gen_helper_fcmple32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4885 gen_store_gpr(dc
, rd
, cpu_dst
);
4887 case 0x026: /* VIS I fcmpne32 */
4888 CHECK_FPU_FEATURE(dc
, VIS1
);
4889 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4890 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4891 gen_helper_fcmpne32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4892 gen_store_gpr(dc
, rd
, cpu_dst
);
4894 case 0x028: /* VIS I fcmpgt16 */
4895 CHECK_FPU_FEATURE(dc
, VIS1
);
4896 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4897 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4898 gen_helper_fcmpgt16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4899 gen_store_gpr(dc
, rd
, cpu_dst
);
4901 case 0x02a: /* VIS I fcmpeq16 */
4902 CHECK_FPU_FEATURE(dc
, VIS1
);
4903 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4904 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4905 gen_helper_fcmpeq16(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4906 gen_store_gpr(dc
, rd
, cpu_dst
);
4908 case 0x02c: /* VIS I fcmpgt32 */
4909 CHECK_FPU_FEATURE(dc
, VIS1
);
4910 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4911 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4912 gen_helper_fcmpgt32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4913 gen_store_gpr(dc
, rd
, cpu_dst
);
4915 case 0x02e: /* VIS I fcmpeq32 */
4916 CHECK_FPU_FEATURE(dc
, VIS1
);
4917 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
4918 cpu_src2_64
= gen_load_fpr_D(dc
, rs2
);
4919 gen_helper_fcmpeq32(cpu_dst
, cpu_src1_64
, cpu_src2_64
);
4920 gen_store_gpr(dc
, rd
, cpu_dst
);
4922 case 0x031: /* VIS I fmul8x16 */
4923 CHECK_FPU_FEATURE(dc
, VIS1
);
4924 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16
);
4926 case 0x033: /* VIS I fmul8x16au */
4927 CHECK_FPU_FEATURE(dc
, VIS1
);
4928 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16au
);
4930 case 0x035: /* VIS I fmul8x16al */
4931 CHECK_FPU_FEATURE(dc
, VIS1
);
4932 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8x16al
);
4934 case 0x036: /* VIS I fmul8sux16 */
4935 CHECK_FPU_FEATURE(dc
, VIS1
);
4936 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8sux16
);
4938 case 0x037: /* VIS I fmul8ulx16 */
4939 CHECK_FPU_FEATURE(dc
, VIS1
);
4940 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmul8ulx16
);
4942 case 0x038: /* VIS I fmuld8sux16 */
4943 CHECK_FPU_FEATURE(dc
, VIS1
);
4944 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld8sux16
);
4946 case 0x039: /* VIS I fmuld8ulx16 */
4947 CHECK_FPU_FEATURE(dc
, VIS1
);
4948 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fmuld8ulx16
);
4950 case 0x03a: /* VIS I fpack32 */
4951 CHECK_FPU_FEATURE(dc
, VIS1
);
4952 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpack32
);
4954 case 0x03b: /* VIS I fpack16 */
4955 CHECK_FPU_FEATURE(dc
, VIS1
);
4956 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
4957 cpu_dst_32
= gen_dest_fpr_F(dc
);
4958 gen_helper_fpack16(cpu_dst_32
, cpu_gsr
, cpu_src1_64
);
4959 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
4961 case 0x03d: /* VIS I fpackfix */
4962 CHECK_FPU_FEATURE(dc
, VIS1
);
4963 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
4964 cpu_dst_32
= gen_dest_fpr_F(dc
);
4965 gen_helper_fpackfix(cpu_dst_32
, cpu_gsr
, cpu_src1_64
);
4966 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
4968 case 0x03e: /* VIS I pdist */
4969 CHECK_FPU_FEATURE(dc
, VIS1
);
4970 gen_ne_fop_DDDD(dc
, rd
, rs1
, rs2
, gen_helper_pdist
);
4972 case 0x048: /* VIS I faligndata */
4973 CHECK_FPU_FEATURE(dc
, VIS1
);
4974 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_faligndata
);
4976 case 0x04b: /* VIS I fpmerge */
4977 CHECK_FPU_FEATURE(dc
, VIS1
);
4978 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpmerge
);
4980 case 0x04c: /* VIS II bshuffle */
4981 CHECK_FPU_FEATURE(dc
, VIS2
);
4982 gen_gsr_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_bshuffle
);
4984 case 0x04d: /* VIS I fexpand */
4985 CHECK_FPU_FEATURE(dc
, VIS1
);
4986 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fexpand
);
4988 case 0x050: /* VIS I fpadd16 */
4989 CHECK_FPU_FEATURE(dc
, VIS1
);
4990 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpadd16
);
4992 case 0x051: /* VIS I fpadd16s */
4993 CHECK_FPU_FEATURE(dc
, VIS1
);
4994 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fpadd16s
);
4996 case 0x052: /* VIS I fpadd32 */
4997 CHECK_FPU_FEATURE(dc
, VIS1
);
4998 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpadd32
);
5000 case 0x053: /* VIS I fpadd32s */
5001 CHECK_FPU_FEATURE(dc
, VIS1
);
5002 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_add_i32
);
5004 case 0x054: /* VIS I fpsub16 */
5005 CHECK_FPU_FEATURE(dc
, VIS1
);
5006 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpsub16
);
5008 case 0x055: /* VIS I fpsub16s */
5009 CHECK_FPU_FEATURE(dc
, VIS1
);
5010 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, gen_helper_fpsub16s
);
5012 case 0x056: /* VIS I fpsub32 */
5013 CHECK_FPU_FEATURE(dc
, VIS1
);
5014 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, gen_helper_fpsub32
);
5016 case 0x057: /* VIS I fpsub32s */
5017 CHECK_FPU_FEATURE(dc
, VIS1
);
5018 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_sub_i32
);
5020 case 0x060: /* VIS I fzero */
5021 CHECK_FPU_FEATURE(dc
, VIS1
);
5022 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5023 tcg_gen_movi_i64(cpu_dst_64
, 0);
5024 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5026 case 0x061: /* VIS I fzeros */
5027 CHECK_FPU_FEATURE(dc
, VIS1
);
5028 cpu_dst_32
= gen_dest_fpr_F(dc
);
5029 tcg_gen_movi_i32(cpu_dst_32
, 0);
5030 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5032 case 0x062: /* VIS I fnor */
5033 CHECK_FPU_FEATURE(dc
, VIS1
);
5034 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_nor_i64
);
5036 case 0x063: /* VIS I fnors */
5037 CHECK_FPU_FEATURE(dc
, VIS1
);
5038 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_nor_i32
);
5040 case 0x064: /* VIS I fandnot2 */
5041 CHECK_FPU_FEATURE(dc
, VIS1
);
5042 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_andc_i64
);
5044 case 0x065: /* VIS I fandnot2s */
5045 CHECK_FPU_FEATURE(dc
, VIS1
);
5046 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_andc_i32
);
5048 case 0x066: /* VIS I fnot2 */
5049 CHECK_FPU_FEATURE(dc
, VIS1
);
5050 gen_ne_fop_DD(dc
, rd
, rs2
, tcg_gen_not_i64
);
5052 case 0x067: /* VIS I fnot2s */
5053 CHECK_FPU_FEATURE(dc
, VIS1
);
5054 gen_ne_fop_FF(dc
, rd
, rs2
, tcg_gen_not_i32
);
5056 case 0x068: /* VIS I fandnot1 */
5057 CHECK_FPU_FEATURE(dc
, VIS1
);
5058 gen_ne_fop_DDD(dc
, rd
, rs2
, rs1
, tcg_gen_andc_i64
);
5060 case 0x069: /* VIS I fandnot1s */
5061 CHECK_FPU_FEATURE(dc
, VIS1
);
5062 gen_ne_fop_FFF(dc
, rd
, rs2
, rs1
, tcg_gen_andc_i32
);
5064 case 0x06a: /* VIS I fnot1 */
5065 CHECK_FPU_FEATURE(dc
, VIS1
);
5066 gen_ne_fop_DD(dc
, rd
, rs1
, tcg_gen_not_i64
);
5068 case 0x06b: /* VIS I fnot1s */
5069 CHECK_FPU_FEATURE(dc
, VIS1
);
5070 gen_ne_fop_FF(dc
, rd
, rs1
, tcg_gen_not_i32
);
5072 case 0x06c: /* VIS I fxor */
5073 CHECK_FPU_FEATURE(dc
, VIS1
);
5074 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_xor_i64
);
5076 case 0x06d: /* VIS I fxors */
5077 CHECK_FPU_FEATURE(dc
, VIS1
);
5078 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_xor_i32
);
5080 case 0x06e: /* VIS I fnand */
5081 CHECK_FPU_FEATURE(dc
, VIS1
);
5082 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_nand_i64
);
5084 case 0x06f: /* VIS I fnands */
5085 CHECK_FPU_FEATURE(dc
, VIS1
);
5086 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_nand_i32
);
5088 case 0x070: /* VIS I fand */
5089 CHECK_FPU_FEATURE(dc
, VIS1
);
5090 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_and_i64
);
5092 case 0x071: /* VIS I fands */
5093 CHECK_FPU_FEATURE(dc
, VIS1
);
5094 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_and_i32
);
5096 case 0x072: /* VIS I fxnor */
5097 CHECK_FPU_FEATURE(dc
, VIS1
);
5098 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_eqv_i64
);
5100 case 0x073: /* VIS I fxnors */
5101 CHECK_FPU_FEATURE(dc
, VIS1
);
5102 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_eqv_i32
);
5104 case 0x074: /* VIS I fsrc1 */
5105 CHECK_FPU_FEATURE(dc
, VIS1
);
5106 cpu_src1_64
= gen_load_fpr_D(dc
, rs1
);
5107 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
5109 case 0x075: /* VIS I fsrc1s */
5110 CHECK_FPU_FEATURE(dc
, VIS1
);
5111 cpu_src1_32
= gen_load_fpr_F(dc
, rs1
);
5112 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
5114 case 0x076: /* VIS I fornot2 */
5115 CHECK_FPU_FEATURE(dc
, VIS1
);
5116 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_orc_i64
);
5118 case 0x077: /* VIS I fornot2s */
5119 CHECK_FPU_FEATURE(dc
, VIS1
);
5120 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_orc_i32
);
5122 case 0x078: /* VIS I fsrc2 */
5123 CHECK_FPU_FEATURE(dc
, VIS1
);
5124 cpu_src1_64
= gen_load_fpr_D(dc
, rs2
);
5125 gen_store_fpr_D(dc
, rd
, cpu_src1_64
);
5127 case 0x079: /* VIS I fsrc2s */
5128 CHECK_FPU_FEATURE(dc
, VIS1
);
5129 cpu_src1_32
= gen_load_fpr_F(dc
, rs2
);
5130 gen_store_fpr_F(dc
, rd
, cpu_src1_32
);
5132 case 0x07a: /* VIS I fornot1 */
5133 CHECK_FPU_FEATURE(dc
, VIS1
);
5134 gen_ne_fop_DDD(dc
, rd
, rs2
, rs1
, tcg_gen_orc_i64
);
5136 case 0x07b: /* VIS I fornot1s */
5137 CHECK_FPU_FEATURE(dc
, VIS1
);
5138 gen_ne_fop_FFF(dc
, rd
, rs2
, rs1
, tcg_gen_orc_i32
);
5140 case 0x07c: /* VIS I for */
5141 CHECK_FPU_FEATURE(dc
, VIS1
);
5142 gen_ne_fop_DDD(dc
, rd
, rs1
, rs2
, tcg_gen_or_i64
);
5144 case 0x07d: /* VIS I fors */
5145 CHECK_FPU_FEATURE(dc
, VIS1
);
5146 gen_ne_fop_FFF(dc
, rd
, rs1
, rs2
, tcg_gen_or_i32
);
5148 case 0x07e: /* VIS I fone */
5149 CHECK_FPU_FEATURE(dc
, VIS1
);
5150 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5151 tcg_gen_movi_i64(cpu_dst_64
, -1);
5152 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5154 case 0x07f: /* VIS I fones */
5155 CHECK_FPU_FEATURE(dc
, VIS1
);
5156 cpu_dst_32
= gen_dest_fpr_F(dc
);
5157 tcg_gen_movi_i32(cpu_dst_32
, -1);
5158 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5160 case 0x080: /* VIS I shutdown */
5161 case 0x081: /* VIS II siam */
5170 } else if (xop
== 0x37) { /* V8 CPop2, V9 impdep2 */
5171 #ifdef TARGET_SPARC64
5176 #ifdef TARGET_SPARC64
5177 } else if (xop
== 0x39) { /* V9 return */
5179 cpu_src1
= get_src1(dc
, insn
);
5180 cpu_tmp0
= get_temp_tl(dc
);
5181 if (IS_IMM
) { /* immediate */
5182 simm
= GET_FIELDs(insn
, 19, 31);
5183 tcg_gen_addi_tl(cpu_tmp0
, cpu_src1
, simm
);
5184 } else { /* register */
5185 rs2
= GET_FIELD(insn
, 27, 31);
5187 cpu_src2
= gen_load_gpr(dc
, rs2
);
5188 tcg_gen_add_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
5190 tcg_gen_mov_tl(cpu_tmp0
, cpu_src1
);
5193 gen_helper_restore(cpu_env
);
5195 gen_check_align(cpu_tmp0
, 3);
5196 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5197 dc
->npc
= DYNAMIC_PC
;
5201 cpu_src1
= get_src1(dc
, insn
);
5202 cpu_tmp0
= get_temp_tl(dc
);
5203 if (IS_IMM
) { /* immediate */
5204 simm
= GET_FIELDs(insn
, 19, 31);
5205 tcg_gen_addi_tl(cpu_tmp0
, cpu_src1
, simm
);
5206 } else { /* register */
5207 rs2
= GET_FIELD(insn
, 27, 31);
5209 cpu_src2
= gen_load_gpr(dc
, rs2
);
5210 tcg_gen_add_tl(cpu_tmp0
, cpu_src1
, cpu_src2
);
5212 tcg_gen_mov_tl(cpu_tmp0
, cpu_src1
);
5216 case 0x38: /* jmpl */
5218 TCGv t
= gen_dest_gpr(dc
, rd
);
5219 tcg_gen_movi_tl(t
, dc
->pc
);
5220 gen_store_gpr(dc
, rd
, t
);
5223 gen_check_align(cpu_tmp0
, 3);
5224 gen_address_mask(dc
, cpu_tmp0
);
5225 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5226 dc
->npc
= DYNAMIC_PC
;
5229 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5230 case 0x39: /* rett, V9 return */
5232 if (!supervisor(dc
))
5235 gen_check_align(cpu_tmp0
, 3);
5236 tcg_gen_mov_tl(cpu_npc
, cpu_tmp0
);
5237 dc
->npc
= DYNAMIC_PC
;
5238 gen_helper_rett(cpu_env
);
5242 case 0x3b: /* flush */
5243 if (!((dc
)->def
->features
& CPU_FEATURE_FLUSH
))
5247 case 0x3c: /* save */
5248 gen_helper_save(cpu_env
);
5249 gen_store_gpr(dc
, rd
, cpu_tmp0
);
5251 case 0x3d: /* restore */
5252 gen_helper_restore(cpu_env
);
5253 gen_store_gpr(dc
, rd
, cpu_tmp0
);
5255 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
5256 case 0x3e: /* V9 done/retry */
5260 if (!supervisor(dc
))
5262 dc
->npc
= DYNAMIC_PC
;
5263 dc
->pc
= DYNAMIC_PC
;
5264 gen_helper_done(cpu_env
);
5267 if (!supervisor(dc
))
5269 dc
->npc
= DYNAMIC_PC
;
5270 dc
->pc
= DYNAMIC_PC
;
5271 gen_helper_retry(cpu_env
);
5286 case 3: /* load/store instructions */
5288 unsigned int xop
= GET_FIELD(insn
, 7, 12);
5289 /* ??? gen_address_mask prevents us from using a source
5290 register directly. Always generate a temporary. */
5291 TCGv cpu_addr
= get_temp_tl(dc
);
5293 tcg_gen_mov_tl(cpu_addr
, get_src1(dc
, insn
));
5294 if (xop
== 0x3c || xop
== 0x3e) {
5295 /* V9 casa/casxa : no offset */
5296 } else if (IS_IMM
) { /* immediate */
5297 simm
= GET_FIELDs(insn
, 19, 31);
5299 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, simm
);
5301 } else { /* register */
5302 rs2
= GET_FIELD(insn
, 27, 31);
5304 tcg_gen_add_tl(cpu_addr
, cpu_addr
, gen_load_gpr(dc
, rs2
));
5307 if (xop
< 4 || (xop
> 7 && xop
< 0x14 && xop
!= 0x0e) ||
5308 (xop
> 0x17 && xop
<= 0x1d ) ||
5309 (xop
> 0x2c && xop
<= 0x33) || xop
== 0x1f || xop
== 0x3d) {
5310 TCGv cpu_val
= gen_dest_gpr(dc
, rd
);
5313 case 0x0: /* ld, V9 lduw, load unsigned word */
5314 gen_address_mask(dc
, cpu_addr
);
5315 tcg_gen_qemu_ld32u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5317 case 0x1: /* ldub, load unsigned byte */
5318 gen_address_mask(dc
, cpu_addr
);
5319 tcg_gen_qemu_ld8u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5321 case 0x2: /* lduh, load unsigned halfword */
5322 gen_address_mask(dc
, cpu_addr
);
5323 tcg_gen_qemu_ld16u(cpu_val
, cpu_addr
, dc
->mem_idx
);
5325 case 0x3: /* ldd, load double word */
5331 gen_address_mask(dc
, cpu_addr
);
5332 t64
= tcg_temp_new_i64();
5333 tcg_gen_qemu_ld64(t64
, cpu_addr
, dc
->mem_idx
);
5334 tcg_gen_trunc_i64_tl(cpu_val
, t64
);
5335 tcg_gen_ext32u_tl(cpu_val
, cpu_val
);
5336 gen_store_gpr(dc
, rd
+ 1, cpu_val
);
5337 tcg_gen_shri_i64(t64
, t64
, 32);
5338 tcg_gen_trunc_i64_tl(cpu_val
, t64
);
5339 tcg_temp_free_i64(t64
);
5340 tcg_gen_ext32u_tl(cpu_val
, cpu_val
);
5343 case 0x9: /* ldsb, load signed byte */
5344 gen_address_mask(dc
, cpu_addr
);
5345 tcg_gen_qemu_ld8s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5347 case 0xa: /* ldsh, load signed halfword */
5348 gen_address_mask(dc
, cpu_addr
);
5349 tcg_gen_qemu_ld16s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5351 case 0xd: /* ldstub */
5352 gen_ldstub(dc
, cpu_val
, cpu_addr
, dc
->mem_idx
);
5355 /* swap, swap register with memory. Also atomically */
5356 CHECK_IU_FEATURE(dc
, SWAP
);
5357 cpu_src1
= gen_load_gpr(dc
, rd
);
5358 gen_swap(dc
, cpu_val
, cpu_src1
, cpu_addr
,
5359 dc
->mem_idx
, MO_TEUL
);
5361 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5362 case 0x10: /* lda, V9 lduwa, load word alternate */
5363 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUL
);
5365 case 0x11: /* lduba, load unsigned byte alternate */
5366 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_UB
);
5368 case 0x12: /* lduha, load unsigned halfword alternate */
5369 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUW
);
5371 case 0x13: /* ldda, load double word alternate */
5375 gen_ldda_asi(dc
, cpu_addr
, insn
, rd
);
5377 case 0x19: /* ldsba, load signed byte alternate */
5378 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_SB
);
5380 case 0x1a: /* ldsha, load signed halfword alternate */
5381 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TESW
);
5383 case 0x1d: /* ldstuba -- XXX: should be atomically */
5384 gen_ldstub_asi(dc
, cpu_val
, cpu_addr
, insn
);
5386 case 0x1f: /* swapa, swap reg with alt. memory. Also
5388 CHECK_IU_FEATURE(dc
, SWAP
);
5389 cpu_src1
= gen_load_gpr(dc
, rd
);
5390 gen_swap_asi(dc
, cpu_val
, cpu_src1
, cpu_addr
, insn
);
5393 #ifndef TARGET_SPARC64
5394 case 0x30: /* ldc */
5395 case 0x31: /* ldcsr */
5396 case 0x33: /* lddc */
5400 #ifdef TARGET_SPARC64
5401 case 0x08: /* V9 ldsw */
5402 gen_address_mask(dc
, cpu_addr
);
5403 tcg_gen_qemu_ld32s(cpu_val
, cpu_addr
, dc
->mem_idx
);
5405 case 0x0b: /* V9 ldx */
5406 gen_address_mask(dc
, cpu_addr
);
5407 tcg_gen_qemu_ld64(cpu_val
, cpu_addr
, dc
->mem_idx
);
5409 case 0x18: /* V9 ldswa */
5410 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TESL
);
5412 case 0x1b: /* V9 ldxa */
5413 gen_ld_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEQ
);
5415 case 0x2d: /* V9 prefetch, no effect */
5417 case 0x30: /* V9 ldfa */
5418 if (gen_trap_ifnofpu(dc
)) {
5421 gen_ldf_asi(dc
, cpu_addr
, insn
, 4, rd
);
5422 gen_update_fprs_dirty(dc
, rd
);
5424 case 0x33: /* V9 lddfa */
5425 if (gen_trap_ifnofpu(dc
)) {
5428 gen_ldf_asi(dc
, cpu_addr
, insn
, 8, DFPREG(rd
));
5429 gen_update_fprs_dirty(dc
, DFPREG(rd
));
5431 case 0x3d: /* V9 prefetcha, no effect */
5433 case 0x32: /* V9 ldqfa */
5434 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5435 if (gen_trap_ifnofpu(dc
)) {
5438 gen_ldf_asi(dc
, cpu_addr
, insn
, 16, QFPREG(rd
));
5439 gen_update_fprs_dirty(dc
, QFPREG(rd
));
5445 gen_store_gpr(dc
, rd
, cpu_val
);
5446 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5449 } else if (xop
>= 0x20 && xop
< 0x24) {
5450 if (gen_trap_ifnofpu(dc
)) {
5454 case 0x20: /* ldf, load fpreg */
5455 gen_address_mask(dc
, cpu_addr
);
5456 cpu_dst_32
= gen_dest_fpr_F(dc
);
5457 tcg_gen_qemu_ld_i32(cpu_dst_32
, cpu_addr
,
5458 dc
->mem_idx
, MO_TEUL
);
5459 gen_store_fpr_F(dc
, rd
, cpu_dst_32
);
5461 case 0x21: /* ldfsr, V9 ldxfsr */
5462 #ifdef TARGET_SPARC64
5463 gen_address_mask(dc
, cpu_addr
);
5465 TCGv_i64 t64
= tcg_temp_new_i64();
5466 tcg_gen_qemu_ld_i64(t64
, cpu_addr
,
5467 dc
->mem_idx
, MO_TEQ
);
5468 gen_helper_ldxfsr(cpu_fsr
, cpu_env
, cpu_fsr
, t64
);
5469 tcg_temp_free_i64(t64
);
5473 cpu_dst_32
= get_temp_i32(dc
);
5474 tcg_gen_qemu_ld_i32(cpu_dst_32
, cpu_addr
,
5475 dc
->mem_idx
, MO_TEUL
);
5476 gen_helper_ldfsr(cpu_fsr
, cpu_env
, cpu_fsr
, cpu_dst_32
);
5478 case 0x22: /* ldqf, load quad fpreg */
5479 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5480 gen_address_mask(dc
, cpu_addr
);
5481 cpu_src1_64
= tcg_temp_new_i64();
5482 tcg_gen_qemu_ld_i64(cpu_src1_64
, cpu_addr
, dc
->mem_idx
,
5483 MO_TEQ
| MO_ALIGN_4
);
5484 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, 8);
5485 cpu_src2_64
= tcg_temp_new_i64();
5486 tcg_gen_qemu_ld_i64(cpu_src2_64
, cpu_addr
, dc
->mem_idx
,
5487 MO_TEQ
| MO_ALIGN_4
);
5488 gen_store_fpr_Q(dc
, rd
, cpu_src1_64
, cpu_src2_64
);
5489 tcg_temp_free_i64(cpu_src1_64
);
5490 tcg_temp_free_i64(cpu_src2_64
);
5492 case 0x23: /* lddf, load double fpreg */
5493 gen_address_mask(dc
, cpu_addr
);
5494 cpu_dst_64
= gen_dest_fpr_D(dc
, rd
);
5495 tcg_gen_qemu_ld_i64(cpu_dst_64
, cpu_addr
, dc
->mem_idx
,
5496 MO_TEQ
| MO_ALIGN_4
);
5497 gen_store_fpr_D(dc
, rd
, cpu_dst_64
);
5502 } else if (xop
< 8 || (xop
>= 0x14 && xop
< 0x18) ||
5503 xop
== 0xe || xop
== 0x1e) {
5504 TCGv cpu_val
= gen_load_gpr(dc
, rd
);
5507 case 0x4: /* st, store word */
5508 gen_address_mask(dc
, cpu_addr
);
5509 tcg_gen_qemu_st32(cpu_val
, cpu_addr
, dc
->mem_idx
);
5511 case 0x5: /* stb, store byte */
5512 gen_address_mask(dc
, cpu_addr
);
5513 tcg_gen_qemu_st8(cpu_val
, cpu_addr
, dc
->mem_idx
);
5515 case 0x6: /* sth, store halfword */
5516 gen_address_mask(dc
, cpu_addr
);
5517 tcg_gen_qemu_st16(cpu_val
, cpu_addr
, dc
->mem_idx
);
5519 case 0x7: /* std, store double word */
5526 gen_address_mask(dc
, cpu_addr
);
5527 lo
= gen_load_gpr(dc
, rd
+ 1);
5528 t64
= tcg_temp_new_i64();
5529 tcg_gen_concat_tl_i64(t64
, lo
, cpu_val
);
5530 tcg_gen_qemu_st64(t64
, cpu_addr
, dc
->mem_idx
);
5531 tcg_temp_free_i64(t64
);
5534 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5535 case 0x14: /* sta, V9 stwa, store word alternate */
5536 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUL
);
5538 case 0x15: /* stba, store byte alternate */
5539 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_UB
);
5541 case 0x16: /* stha, store halfword alternate */
5542 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEUW
);
5544 case 0x17: /* stda, store double word alternate */
5548 gen_stda_asi(dc
, cpu_val
, cpu_addr
, insn
, rd
);
5551 #ifdef TARGET_SPARC64
5552 case 0x0e: /* V9 stx */
5553 gen_address_mask(dc
, cpu_addr
);
5554 tcg_gen_qemu_st64(cpu_val
, cpu_addr
, dc
->mem_idx
);
5556 case 0x1e: /* V9 stxa */
5557 gen_st_asi(dc
, cpu_val
, cpu_addr
, insn
, MO_TEQ
);
5563 } else if (xop
> 0x23 && xop
< 0x28) {
5564 if (gen_trap_ifnofpu(dc
)) {
5568 case 0x24: /* stf, store fpreg */
5569 gen_address_mask(dc
, cpu_addr
);
5570 cpu_src1_32
= gen_load_fpr_F(dc
, rd
);
5571 tcg_gen_qemu_st_i32(cpu_src1_32
, cpu_addr
,
5572 dc
->mem_idx
, MO_TEUL
);
5574 case 0x25: /* stfsr, V9 stxfsr */
5576 #ifdef TARGET_SPARC64
5577 gen_address_mask(dc
, cpu_addr
);
5579 tcg_gen_qemu_st64(cpu_fsr
, cpu_addr
, dc
->mem_idx
);
5583 tcg_gen_qemu_st32(cpu_fsr
, cpu_addr
, dc
->mem_idx
);
5587 #ifdef TARGET_SPARC64
5588 /* V9 stqf, store quad fpreg */
5589 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5590 gen_address_mask(dc
, cpu_addr
);
5591 /* ??? While stqf only requires 4-byte alignment, it is
5592 legal for the cpu to signal the unaligned exception.
5593 The OS trap handler is then required to fix it up.
5594 For qemu, this avoids having to probe the second page
5595 before performing the first write. */
5596 cpu_src1_64
= gen_load_fpr_Q0(dc
, rd
);
5597 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
,
5598 dc
->mem_idx
, MO_TEQ
| MO_ALIGN_16
);
5599 tcg_gen_addi_tl(cpu_addr
, cpu_addr
, 8);
5600 cpu_src2_64
= gen_load_fpr_Q1(dc
, rd
);
5601 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
,
5602 dc
->mem_idx
, MO_TEQ
);
5604 #else /* !TARGET_SPARC64 */
5605 /* stdfq, store floating point queue */
5606 #if defined(CONFIG_USER_ONLY)
5609 if (!supervisor(dc
))
5611 if (gen_trap_ifnofpu(dc
)) {
5617 case 0x27: /* stdf, store double fpreg */
5618 gen_address_mask(dc
, cpu_addr
);
5619 cpu_src1_64
= gen_load_fpr_D(dc
, rd
);
5620 tcg_gen_qemu_st_i64(cpu_src1_64
, cpu_addr
, dc
->mem_idx
,
5621 MO_TEQ
| MO_ALIGN_4
);
5626 } else if (xop
> 0x33 && xop
< 0x3f) {
5628 #ifdef TARGET_SPARC64
5629 case 0x34: /* V9 stfa */
5630 if (gen_trap_ifnofpu(dc
)) {
5633 gen_stf_asi(dc
, cpu_addr
, insn
, 4, rd
);
5635 case 0x36: /* V9 stqfa */
5637 CHECK_FPU_FEATURE(dc
, FLOAT128
);
5638 if (gen_trap_ifnofpu(dc
)) {
5641 gen_stf_asi(dc
, cpu_addr
, insn
, 16, QFPREG(rd
));
5644 case 0x37: /* V9 stdfa */
5645 if (gen_trap_ifnofpu(dc
)) {
5648 gen_stf_asi(dc
, cpu_addr
, insn
, 8, DFPREG(rd
));
5650 case 0x3e: /* V9 casxa */
5651 rs2
= GET_FIELD(insn
, 27, 31);
5652 cpu_src2
= gen_load_gpr(dc
, rs2
);
5653 gen_casx_asi(dc
, cpu_addr
, cpu_src2
, insn
, rd
);
5656 case 0x34: /* stc */
5657 case 0x35: /* stcsr */
5658 case 0x36: /* stdcq */
5659 case 0x37: /* stdc */
5662 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5663 case 0x3c: /* V9 or LEON3 casa */
5664 #ifndef TARGET_SPARC64
5665 CHECK_IU_FEATURE(dc
, CASA
);
5667 rs2
= GET_FIELD(insn
, 27, 31);
5668 cpu_src2
= gen_load_gpr(dc
, rs2
);
5669 gen_cas_asi(dc
, cpu_addr
, cpu_src2
, insn
, rd
);
5681 /* default case for non jump instructions */
5682 if (dc
->npc
== DYNAMIC_PC
) {
5683 dc
->pc
= DYNAMIC_PC
;
5685 } else if (dc
->npc
== JUMP_PC
) {
5686 /* we can do a static jump */
5687 gen_branch2(dc
, dc
->jump_pc
[0], dc
->jump_pc
[1], cpu_cond
);
5691 dc
->npc
= dc
->npc
+ 4;
5696 gen_exception(dc
, TT_ILL_INSN
);
5699 gen_exception(dc
, TT_UNIMP_FLUSH
);
5701 #if !defined(CONFIG_USER_ONLY)
5703 gen_exception(dc
, TT_PRIV_INSN
);
5707 gen_op_fpexception_im(dc
, FSR_FTT_UNIMPFPOP
);
5709 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5711 gen_op_fpexception_im(dc
, FSR_FTT_SEQ_ERROR
);
5714 #ifndef TARGET_SPARC64
5716 gen_exception(dc
, TT_NCP_INSN
);
5720 if (dc
->n_t32
!= 0) {
5722 for (i
= dc
->n_t32
- 1; i
>= 0; --i
) {
5723 tcg_temp_free_i32(dc
->t32
[i
]);
5727 if (dc
->n_ttl
!= 0) {
5729 for (i
= dc
->n_ttl
- 1; i
>= 0; --i
) {
5730 tcg_temp_free(dc
->ttl
[i
]);
5736 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
* tb
)
5738 CPUSPARCState
*env
= cs
->env_ptr
;
5739 target_ulong pc_start
, last_pc
;
5740 DisasContext dc1
, *dc
= &dc1
;
5745 memset(dc
, 0, sizeof(DisasContext
));
5750 dc
->npc
= (target_ulong
) tb
->cs_base
;
5751 dc
->cc_op
= CC_OP_DYNAMIC
;
5752 dc
->mem_idx
= tb
->flags
& TB_FLAG_MMU_MASK
;
5753 dc
->def
= &env
->def
;
5754 dc
->fpu_enabled
= tb_fpu_enabled(tb
->flags
);
5755 dc
->address_mask_32bit
= tb_am_enabled(tb
->flags
);
5756 dc
->singlestep
= (cs
->singlestep_enabled
|| singlestep
);
5757 #ifndef CONFIG_USER_ONLY
5758 dc
->supervisor
= (tb
->flags
& TB_FLAG_SUPER
) != 0;
5760 #ifdef TARGET_SPARC64
5762 dc
->asi
= (tb
->flags
>> TB_FLAG_ASI_SHIFT
) & 0xff;
5763 #ifndef CONFIG_USER_ONLY
5764 dc
->hypervisor
= (tb
->flags
& TB_FLAG_HYPER
) != 0;
5769 max_insns
= tb_cflags(tb
) & CF_COUNT_MASK
;
5770 if (max_insns
== 0) {
5771 max_insns
= CF_COUNT_MASK
;
5773 if (max_insns
> TCG_MAX_INSNS
) {
5774 max_insns
= TCG_MAX_INSNS
;
5779 if (dc
->npc
& JUMP_PC
) {
5780 assert(dc
->jump_pc
[1] == dc
->pc
+ 4);
5781 tcg_gen_insn_start(dc
->pc
, dc
->jump_pc
[0] | JUMP_PC
);
5783 tcg_gen_insn_start(dc
->pc
, dc
->npc
);
5788 if (unlikely(cpu_breakpoint_test(cs
, dc
->pc
, BP_ANY
))) {
5789 if (dc
->pc
!= pc_start
) {
5792 gen_helper_debug(cpu_env
);
5798 if (num_insns
== max_insns
&& (tb_cflags(tb
) & CF_LAST_IO
)) {
5802 insn
= cpu_ldl_code(env
, dc
->pc
);
5804 disas_sparc_insn(dc
, insn
);
5808 /* if the next PC is different, we abort now */
5809 if (dc
->pc
!= (last_pc
+ 4))
5811 /* if we reach a page boundary, we stop generation so that the
5812 PC of a TT_TFAULT exception is always in the right page */
5813 if ((dc
->pc
& (TARGET_PAGE_SIZE
- 1)) == 0)
5815 /* if single step mode, we generate only one instruction and
5816 generate an exception */
5817 if (dc
->singlestep
) {
5820 } while (!tcg_op_buf_full() &&
5821 (dc
->pc
- pc_start
) < (TARGET_PAGE_SIZE
- 32) &&
5822 num_insns
< max_insns
);
5825 if (tb_cflags(tb
) & CF_LAST_IO
) {
5829 if (dc
->pc
!= DYNAMIC_PC
&&
5830 (dc
->npc
!= DYNAMIC_PC
&& dc
->npc
!= JUMP_PC
)) {
5831 /* static PC and NPC: we can use direct chaining */
5832 gen_goto_tb(dc
, 0, dc
->pc
, dc
->npc
);
5834 if (dc
->pc
!= DYNAMIC_PC
) {
5835 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
5841 gen_tb_end(tb
, num_insns
);
5843 tb
->size
= last_pc
+ 4 - pc_start
;
5844 tb
->icount
= num_insns
;
5847 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)
5848 && qemu_log_in_addr_range(pc_start
)) {
5850 qemu_log("--------------\n");
5851 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
5852 log_target_disas(cs
, pc_start
, last_pc
+ 4 - pc_start
);
5859 void sparc_tcg_init(void)
5861 static const char gregnames
[32][4] = {
5862 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5863 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5864 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5865 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5867 static const char fregnames
[32][4] = {
5868 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5869 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5870 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5871 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5874 static const struct { TCGv_i32
*ptr
; int off
; const char *name
; } r32
[] = {
5875 #ifdef TARGET_SPARC64
5876 { &cpu_xcc
, offsetof(CPUSPARCState
, xcc
), "xcc" },
5877 { &cpu_fprs
, offsetof(CPUSPARCState
, fprs
), "fprs" },
5879 { &cpu_wim
, offsetof(CPUSPARCState
, wim
), "wim" },
5881 { &cpu_cc_op
, offsetof(CPUSPARCState
, cc_op
), "cc_op" },
5882 { &cpu_psr
, offsetof(CPUSPARCState
, psr
), "psr" },
5885 static const struct { TCGv
*ptr
; int off
; const char *name
; } rtl
[] = {
5886 #ifdef TARGET_SPARC64
5887 { &cpu_gsr
, offsetof(CPUSPARCState
, gsr
), "gsr" },
5888 { &cpu_tick_cmpr
, offsetof(CPUSPARCState
, tick_cmpr
), "tick_cmpr" },
5889 { &cpu_stick_cmpr
, offsetof(CPUSPARCState
, stick_cmpr
), "stick_cmpr" },
5890 { &cpu_hstick_cmpr
, offsetof(CPUSPARCState
, hstick_cmpr
),
5892 { &cpu_hintp
, offsetof(CPUSPARCState
, hintp
), "hintp" },
5893 { &cpu_htba
, offsetof(CPUSPARCState
, htba
), "htba" },
5894 { &cpu_hver
, offsetof(CPUSPARCState
, hver
), "hver" },
5895 { &cpu_ssr
, offsetof(CPUSPARCState
, ssr
), "ssr" },
5896 { &cpu_ver
, offsetof(CPUSPARCState
, version
), "ver" },
5898 { &cpu_cond
, offsetof(CPUSPARCState
, cond
), "cond" },
5899 { &cpu_cc_src
, offsetof(CPUSPARCState
, cc_src
), "cc_src" },
5900 { &cpu_cc_src2
, offsetof(CPUSPARCState
, cc_src2
), "cc_src2" },
5901 { &cpu_cc_dst
, offsetof(CPUSPARCState
, cc_dst
), "cc_dst" },
5902 { &cpu_fsr
, offsetof(CPUSPARCState
, fsr
), "fsr" },
5903 { &cpu_pc
, offsetof(CPUSPARCState
, pc
), "pc" },
5904 { &cpu_npc
, offsetof(CPUSPARCState
, npc
), "npc" },
5905 { &cpu_y
, offsetof(CPUSPARCState
, y
), "y" },
5906 #ifndef CONFIG_USER_ONLY
5907 { &cpu_tbr
, offsetof(CPUSPARCState
, tbr
), "tbr" },
5913 cpu_regwptr
= tcg_global_mem_new_ptr(cpu_env
,
5914 offsetof(CPUSPARCState
, regwptr
),
5917 for (i
= 0; i
< ARRAY_SIZE(r32
); ++i
) {
5918 *r32
[i
].ptr
= tcg_global_mem_new_i32(cpu_env
, r32
[i
].off
, r32
[i
].name
);
5921 for (i
= 0; i
< ARRAY_SIZE(rtl
); ++i
) {
5922 *rtl
[i
].ptr
= tcg_global_mem_new(cpu_env
, rtl
[i
].off
, rtl
[i
].name
);
5925 TCGV_UNUSED(cpu_regs
[0]);
5926 for (i
= 1; i
< 8; ++i
) {
5927 cpu_regs
[i
] = tcg_global_mem_new(cpu_env
,
5928 offsetof(CPUSPARCState
, gregs
[i
]),
5932 for (i
= 8; i
< 32; ++i
) {
5933 cpu_regs
[i
] = tcg_global_mem_new(cpu_regwptr
,
5934 (i
- 8) * sizeof(target_ulong
),
5938 for (i
= 0; i
< TARGET_DPREGS
; i
++) {
5939 cpu_fpr
[i
] = tcg_global_mem_new_i64(cpu_env
,
5940 offsetof(CPUSPARCState
, fpr
[i
]),
5945 void restore_state_to_opc(CPUSPARCState
*env
, TranslationBlock
*tb
,
5948 target_ulong pc
= data
[0];
5949 target_ulong npc
= data
[1];
5952 if (npc
== DYNAMIC_PC
) {
5953 /* dynamic NPC: already stored */
5954 } else if (npc
& JUMP_PC
) {
5955 /* jump PC: use 'cond' and the jump targets of the translation */
5957 env
->npc
= npc
& ~3;