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.1 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"
27 #include "tcg/tcg-op.h"
28 #include "tcg/tcg-op-gvec.h"
29 #include "exec/helper-gen.h"
30 #include "exec/translator.h"
34 #define HELPER_H "helper.h"
35 #include "exec/helper-info.c.inc"
39 # define gen_helper_rdpsr(D, E) qemu_build_not_reached()
40 # define gen_helper_rett(E) qemu_build_not_reached()
41 # define gen_helper_power_down(E) qemu_build_not_reached()
42 # define gen_helper_wrpsr(E, S) qemu_build_not_reached()
44 # define gen_helper_clear_softint(E, S) qemu_build_not_reached()
45 # define gen_helper_done(E) qemu_build_not_reached()
46 # define gen_helper_flushw(E) qemu_build_not_reached()
47 # define gen_helper_rdccr(D, E) qemu_build_not_reached()
48 # define gen_helper_rdcwp(D, E) qemu_build_not_reached()
49 # define gen_helper_restored(E) qemu_build_not_reached()
50 # define gen_helper_retry(E) qemu_build_not_reached()
51 # define gen_helper_saved(E) qemu_build_not_reached()
52 # define gen_helper_set_softint(E, S) qemu_build_not_reached()
53 # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
54 # define gen_helper_tick_set_count(P, S) qemu_build_not_reached()
55 # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached()
56 # define gen_helper_wrccr(E, S) qemu_build_not_reached()
57 # define gen_helper_wrcwp(E, S) qemu_build_not_reached()
58 # define gen_helper_wrgl(E, S) qemu_build_not_reached()
59 # define gen_helper_write_softint(E, S) qemu_build_not_reached()
60 # define gen_helper_wrpil(E, S) qemu_build_not_reached()
61 # define gen_helper_wrpstate(E, S) qemu_build_not_reached()
62 # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; })
63 # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; })
64 # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; })
65 # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; })
66 # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; })
67 # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; })
68 # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; })
69 # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; })
70 # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; })
71 # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; })
72 # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; })
73 # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; })
74 # define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; })
75 # define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; })
76 # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; })
77 # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; })
78 # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; })
79 # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; })
80 # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; })
81 # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; })
82 # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; })
83 # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; })
84 # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; })
85 # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; })
86 # define FSR_LDXFSR_MASK 0
87 # define FSR_LDXFSR_OLDMASK 0
91 /* Dynamic PC, must exit to main loop. */
93 /* Dynamic PC, one of two values according to jump_pc[T2]. */
95 /* Dynamic PC, may lookup next TB. */
96 #define DYNAMIC_PC_LOOKUP 3
98 #define DISAS_EXIT DISAS_TARGET_0
100 /* global register indexes */
101 static TCGv_ptr cpu_regwptr
;
102 static TCGv cpu_pc
, cpu_npc
;
103 static TCGv cpu_regs
[32];
106 static TCGv cpu_cond
;
107 static TCGv cpu_cc_N
;
108 static TCGv cpu_cc_V
;
109 static TCGv cpu_icc_Z
;
110 static TCGv cpu_icc_C
;
111 #ifdef TARGET_SPARC64
112 static TCGv cpu_xcc_Z
;
113 static TCGv cpu_xcc_C
;
114 static TCGv_i32 cpu_fprs
;
117 # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; })
118 # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; })
121 #ifdef TARGET_SPARC64
122 #define cpu_cc_Z cpu_xcc_Z
123 #define cpu_cc_C cpu_xcc_C
125 #define cpu_cc_Z cpu_icc_Z
126 #define cpu_cc_C cpu_icc_C
127 #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
128 #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
131 /* Floating point registers */
132 static TCGv_i64 cpu_fpr
[TARGET_DPREGS
];
134 #define env_field_offsetof(X) offsetof(CPUSPARCState, X)
135 #ifdef TARGET_SPARC64
136 # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
137 # define env64_field_offsetof(X) env_field_offsetof(X)
139 # define env32_field_offsetof(X) env_field_offsetof(X)
140 # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
143 typedef struct DisasCompare
{
149 typedef struct DisasDelayException
{
150 struct DisasDelayException
*next
;
153 /* Saved state at parent insn. */
156 } DisasDelayException
;
158 typedef struct DisasContext
{
159 DisasContextBase base
;
160 target_ulong pc
; /* current Program Counter: integer or DYNAMIC_PC */
161 target_ulong npc
; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
163 /* Used when JUMP_PC value is used. */
165 target_ulong jump_pc
[2];
170 bool address_mask_32bit
;
171 #ifndef CONFIG_USER_ONLY
173 #ifdef TARGET_SPARC64
179 #ifdef TARGET_SPARC64
183 DisasDelayException
*delay_excp_list
;
186 // This function uses non-native bit order
187 #define GET_FIELD(X, FROM, TO) \
188 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
190 // This function uses the order in the manuals, i.e. bit 0 is 2^0
191 #define GET_FIELD_SP(X, FROM, TO) \
192 GET_FIELD(X, 31 - (TO), 31 - (FROM))
194 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
195 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
197 #ifdef TARGET_SPARC64
198 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
199 #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
201 #define DFPREG(r) (r & 0x1e)
202 #define QFPREG(r) (r & 0x1c)
205 #define UA2005_HTRAP_MASK 0xff
206 #define V8_TRAP_MASK 0x7f
208 #define IS_IMM (insn & (1<<13))
210 static void gen_update_fprs_dirty(DisasContext
*dc
, int rd
)
212 #if defined(TARGET_SPARC64)
213 int bit
= (rd
< 32) ? 1 : 2;
214 /* If we know we've already set this bit within the TB,
215 we can avoid setting it again. */
216 if (!(dc
->fprs_dirty
& bit
)) {
217 dc
->fprs_dirty
|= bit
;
218 tcg_gen_ori_i32(cpu_fprs
, cpu_fprs
, bit
);
223 /* floating point registers moves */
224 static TCGv_i32
gen_load_fpr_F(DisasContext
*dc
, unsigned int src
)
226 TCGv_i32 ret
= tcg_temp_new_i32();
228 tcg_gen_extrl_i64_i32(ret
, cpu_fpr
[src
/ 2]);
230 tcg_gen_extrh_i64_i32(ret
, cpu_fpr
[src
/ 2]);
235 static void gen_store_fpr_F(DisasContext
*dc
, unsigned int dst
, TCGv_i32 v
)
237 TCGv_i64 t
= tcg_temp_new_i64();
239 tcg_gen_extu_i32_i64(t
, v
);
240 tcg_gen_deposit_i64(cpu_fpr
[dst
/ 2], cpu_fpr
[dst
/ 2], t
,
241 (dst
& 1 ? 0 : 32), 32);
242 gen_update_fprs_dirty(dc
, dst
);
245 static TCGv_i64
gen_load_fpr_D(DisasContext
*dc
, unsigned int src
)
248 return cpu_fpr
[src
/ 2];
251 static void gen_store_fpr_D(DisasContext
*dc
, unsigned int dst
, TCGv_i64 v
)
254 tcg_gen_mov_i64(cpu_fpr
[dst
/ 2], v
);
255 gen_update_fprs_dirty(dc
, dst
);
258 static TCGv_i64
gen_dest_fpr_D(DisasContext
*dc
, unsigned int dst
)
260 return cpu_fpr
[DFPREG(dst
) / 2];
263 static TCGv_i128
gen_load_fpr_Q(DisasContext
*dc
, unsigned int src
)
265 TCGv_i128 ret
= tcg_temp_new_i128();
268 tcg_gen_concat_i64_i128(ret
, cpu_fpr
[src
/ 2 + 1], cpu_fpr
[src
/ 2]);
272 static void gen_store_fpr_Q(DisasContext
*dc
, unsigned int dst
, TCGv_i128 v
)
275 tcg_gen_extr_i128_i64(cpu_fpr
[dst
/ 2 + 1], cpu_fpr
[dst
/ 2], v
);
276 gen_update_fprs_dirty(dc
, dst
);
280 #ifdef CONFIG_USER_ONLY
281 #define supervisor(dc) 0
282 #define hypervisor(dc) 0
284 #ifdef TARGET_SPARC64
285 #define hypervisor(dc) (dc->hypervisor)
286 #define supervisor(dc) (dc->supervisor | dc->hypervisor)
288 #define supervisor(dc) (dc->supervisor)
289 #define hypervisor(dc) 0
293 #if !defined(TARGET_SPARC64)
294 # define AM_CHECK(dc) false
295 #elif defined(TARGET_ABI32)
296 # define AM_CHECK(dc) true
297 #elif defined(CONFIG_USER_ONLY)
298 # define AM_CHECK(dc) false
300 # define AM_CHECK(dc) ((dc)->address_mask_32bit)
303 static void gen_address_mask(DisasContext
*dc
, TCGv addr
)
306 tcg_gen_andi_tl(addr
, addr
, 0xffffffffULL
);
310 static target_ulong
address_mask_i(DisasContext
*dc
, target_ulong addr
)
312 return AM_CHECK(dc
) ? (uint32_t)addr
: addr
;
315 static TCGv
gen_load_gpr(DisasContext
*dc
, int reg
)
319 return cpu_regs
[reg
];
321 TCGv t
= tcg_temp_new();
322 tcg_gen_movi_tl(t
, 0);
327 static void gen_store_gpr(DisasContext
*dc
, int reg
, TCGv v
)
331 tcg_gen_mov_tl(cpu_regs
[reg
], v
);
335 static TCGv
gen_dest_gpr(DisasContext
*dc
, int reg
)
339 return cpu_regs
[reg
];
341 return tcg_temp_new();
345 static bool use_goto_tb(DisasContext
*s
, target_ulong pc
, target_ulong npc
)
347 return translator_use_goto_tb(&s
->base
, pc
) &&
348 translator_use_goto_tb(&s
->base
, npc
);
351 static void gen_goto_tb(DisasContext
*s
, int tb_num
,
352 target_ulong pc
, target_ulong npc
)
354 if (use_goto_tb(s
, pc
, npc
)) {
355 /* jump to same page: we can use a direct jump */
356 tcg_gen_goto_tb(tb_num
);
357 tcg_gen_movi_tl(cpu_pc
, pc
);
358 tcg_gen_movi_tl(cpu_npc
, npc
);
359 tcg_gen_exit_tb(s
->base
.tb
, tb_num
);
361 /* jump to another page: we can use an indirect jump */
362 tcg_gen_movi_tl(cpu_pc
, pc
);
363 tcg_gen_movi_tl(cpu_npc
, npc
);
364 tcg_gen_lookup_and_goto_ptr();
368 static TCGv
gen_carry32(void)
370 if (TARGET_LONG_BITS
== 64) {
371 TCGv t
= tcg_temp_new();
372 tcg_gen_extract_tl(t
, cpu_icc_C
, 32, 1);
378 static void gen_op_addcc_int(TCGv dst
, TCGv src1
, TCGv src2
, TCGv cin
)
380 TCGv z
= tcg_constant_tl(0);
383 tcg_gen_add2_tl(cpu_cc_N
, cpu_cc_C
, src1
, z
, cin
, z
);
384 tcg_gen_add2_tl(cpu_cc_N
, cpu_cc_C
, cpu_cc_N
, cpu_cc_C
, src2
, z
);
386 tcg_gen_add2_tl(cpu_cc_N
, cpu_cc_C
, src1
, z
, src2
, z
);
388 tcg_gen_xor_tl(cpu_cc_Z
, src1
, src2
);
389 tcg_gen_xor_tl(cpu_cc_V
, cpu_cc_N
, src2
);
390 tcg_gen_andc_tl(cpu_cc_V
, cpu_cc_V
, cpu_cc_Z
);
391 if (TARGET_LONG_BITS
== 64) {
393 * Carry-in to bit 32 is result ^ src1 ^ src2.
394 * We already have the src xor term in Z, from computation of V.
396 tcg_gen_xor_tl(cpu_icc_C
, cpu_cc_Z
, cpu_cc_N
);
397 tcg_gen_mov_tl(cpu_icc_Z
, cpu_cc_N
);
399 tcg_gen_mov_tl(cpu_cc_Z
, cpu_cc_N
);
400 tcg_gen_mov_tl(dst
, cpu_cc_N
);
403 static void gen_op_addcc(TCGv dst
, TCGv src1
, TCGv src2
)
405 gen_op_addcc_int(dst
, src1
, src2
, NULL
);
408 static void gen_op_taddcc(TCGv dst
, TCGv src1
, TCGv src2
)
410 TCGv t
= tcg_temp_new();
412 /* Save the tag bits around modification of dst. */
413 tcg_gen_or_tl(t
, src1
, src2
);
415 gen_op_addcc(dst
, src1
, src2
);
417 /* Incorprate tag bits into icc.V */
418 tcg_gen_andi_tl(t
, t
, 3);
419 tcg_gen_neg_tl(t
, t
);
420 tcg_gen_ext32u_tl(t
, t
);
421 tcg_gen_or_tl(cpu_cc_V
, cpu_cc_V
, t
);
424 static void gen_op_addc(TCGv dst
, TCGv src1
, TCGv src2
)
426 tcg_gen_add_tl(dst
, src1
, src2
);
427 tcg_gen_add_tl(dst
, dst
, gen_carry32());
430 static void gen_op_addccc(TCGv dst
, TCGv src1
, TCGv src2
)
432 gen_op_addcc_int(dst
, src1
, src2
, gen_carry32());
435 static void gen_op_subcc_int(TCGv dst
, TCGv src1
, TCGv src2
, TCGv cin
)
437 TCGv z
= tcg_constant_tl(0);
440 tcg_gen_sub2_tl(cpu_cc_N
, cpu_cc_C
, src1
, z
, cin
, z
);
441 tcg_gen_sub2_tl(cpu_cc_N
, cpu_cc_C
, cpu_cc_N
, cpu_cc_C
, src2
, z
);
443 tcg_gen_sub2_tl(cpu_cc_N
, cpu_cc_C
, src1
, z
, src2
, z
);
445 tcg_gen_neg_tl(cpu_cc_C
, cpu_cc_C
);
446 tcg_gen_xor_tl(cpu_cc_Z
, src1
, src2
);
447 tcg_gen_xor_tl(cpu_cc_V
, cpu_cc_N
, src1
);
448 tcg_gen_and_tl(cpu_cc_V
, cpu_cc_V
, cpu_cc_Z
);
449 #ifdef TARGET_SPARC64
450 tcg_gen_xor_tl(cpu_icc_C
, cpu_cc_Z
, cpu_cc_N
);
451 tcg_gen_mov_tl(cpu_icc_Z
, cpu_cc_N
);
453 tcg_gen_mov_tl(cpu_cc_Z
, cpu_cc_N
);
454 tcg_gen_mov_tl(dst
, cpu_cc_N
);
457 static void gen_op_subcc(TCGv dst
, TCGv src1
, TCGv src2
)
459 gen_op_subcc_int(dst
, src1
, src2
, NULL
);
462 static void gen_op_tsubcc(TCGv dst
, TCGv src1
, TCGv src2
)
464 TCGv t
= tcg_temp_new();
466 /* Save the tag bits around modification of dst. */
467 tcg_gen_or_tl(t
, src1
, src2
);
469 gen_op_subcc(dst
, src1
, src2
);
471 /* Incorprate tag bits into icc.V */
472 tcg_gen_andi_tl(t
, t
, 3);
473 tcg_gen_neg_tl(t
, t
);
474 tcg_gen_ext32u_tl(t
, t
);
475 tcg_gen_or_tl(cpu_cc_V
, cpu_cc_V
, t
);
478 static void gen_op_subc(TCGv dst
, TCGv src1
, TCGv src2
)
480 tcg_gen_sub_tl(dst
, src1
, src2
);
481 tcg_gen_sub_tl(dst
, dst
, gen_carry32());
484 static void gen_op_subccc(TCGv dst
, TCGv src1
, TCGv src2
)
486 gen_op_subcc_int(dst
, src1
, src2
, gen_carry32());
489 static void gen_op_mulscc(TCGv dst
, TCGv src1
, TCGv src2
)
491 TCGv zero
= tcg_constant_tl(0);
492 TCGv t_src1
= tcg_temp_new();
493 TCGv t_src2
= tcg_temp_new();
494 TCGv t0
= tcg_temp_new();
496 tcg_gen_ext32u_tl(t_src1
, src1
);
497 tcg_gen_ext32u_tl(t_src2
, src2
);
503 tcg_gen_andi_tl(t0
, cpu_y
, 0x1);
504 tcg_gen_movcond_tl(TCG_COND_EQ
, t_src2
, t0
, zero
, zero
, t_src2
);
508 * y = (b2 << 31) | (y >> 1);
510 tcg_gen_extract_tl(t0
, cpu_y
, 1, 31);
511 tcg_gen_deposit_tl(cpu_y
, t0
, src1
, 31, 1);
514 tcg_gen_xor_tl(t0
, cpu_cc_N
, cpu_cc_V
);
517 * src1 = (b1 << 31) | (src1 >> 1)
519 tcg_gen_andi_tl(t0
, t0
, 1u << 31);
520 tcg_gen_shri_tl(t_src1
, t_src1
, 1);
521 tcg_gen_or_tl(t_src1
, t_src1
, t0
);
523 gen_op_addcc(dst
, t_src1
, t_src2
);
526 static void gen_op_multiply(TCGv dst
, TCGv src1
, TCGv src2
, int sign_ext
)
528 #if TARGET_LONG_BITS == 32
530 tcg_gen_muls2_tl(dst
, cpu_y
, src1
, src2
);
532 tcg_gen_mulu2_tl(dst
, cpu_y
, src1
, src2
);
535 TCGv t0
= tcg_temp_new_i64();
536 TCGv t1
= tcg_temp_new_i64();
539 tcg_gen_ext32s_i64(t0
, src1
);
540 tcg_gen_ext32s_i64(t1
, src2
);
542 tcg_gen_ext32u_i64(t0
, src1
);
543 tcg_gen_ext32u_i64(t1
, src2
);
546 tcg_gen_mul_i64(dst
, t0
, t1
);
547 tcg_gen_shri_i64(cpu_y
, dst
, 32);
551 static void gen_op_umul(TCGv dst
, TCGv src1
, TCGv src2
)
553 /* zero-extend truncated operands before multiplication */
554 gen_op_multiply(dst
, src1
, src2
, 0);
557 static void gen_op_smul(TCGv dst
, TCGv src1
, TCGv src2
)
559 /* sign-extend truncated operands before multiplication */
560 gen_op_multiply(dst
, src1
, src2
, 1);
563 static void gen_op_sdiv(TCGv dst
, TCGv src1
, TCGv src2
)
565 #ifdef TARGET_SPARC64
566 gen_helper_sdiv(dst
, tcg_env
, src1
, src2
);
567 tcg_gen_ext32s_tl(dst
, dst
);
569 TCGv_i64 t64
= tcg_temp_new_i64();
570 gen_helper_sdiv(t64
, tcg_env
, src1
, src2
);
571 tcg_gen_trunc_i64_tl(dst
, t64
);
575 static void gen_op_udivcc(TCGv dst
, TCGv src1
, TCGv src2
)
579 #ifdef TARGET_SPARC64
582 t64
= tcg_temp_new_i64();
585 gen_helper_udiv(t64
, tcg_env
, src1
, src2
);
587 #ifdef TARGET_SPARC64
588 tcg_gen_ext32u_tl(cpu_cc_N
, t64
);
589 tcg_gen_shri_tl(cpu_cc_V
, t64
, 32);
590 tcg_gen_mov_tl(cpu_icc_Z
, cpu_cc_N
);
591 tcg_gen_movi_tl(cpu_icc_C
, 0);
593 tcg_gen_extr_i64_tl(cpu_cc_N
, cpu_cc_V
, t64
);
595 tcg_gen_mov_tl(cpu_cc_Z
, cpu_cc_N
);
596 tcg_gen_movi_tl(cpu_cc_C
, 0);
597 tcg_gen_mov_tl(dst
, cpu_cc_N
);
600 static void gen_op_sdivcc(TCGv dst
, TCGv src1
, TCGv src2
)
604 #ifdef TARGET_SPARC64
607 t64
= tcg_temp_new_i64();
610 gen_helper_sdiv(t64
, tcg_env
, src1
, src2
);
612 #ifdef TARGET_SPARC64
613 tcg_gen_ext32s_tl(cpu_cc_N
, t64
);
614 tcg_gen_shri_tl(cpu_cc_V
, t64
, 32);
615 tcg_gen_mov_tl(cpu_icc_Z
, cpu_cc_N
);
616 tcg_gen_movi_tl(cpu_icc_C
, 0);
618 tcg_gen_extr_i64_tl(cpu_cc_N
, cpu_cc_V
, t64
);
620 tcg_gen_mov_tl(cpu_cc_Z
, cpu_cc_N
);
621 tcg_gen_movi_tl(cpu_cc_C
, 0);
622 tcg_gen_mov_tl(dst
, cpu_cc_N
);
625 static void gen_op_taddcctv(TCGv dst
, TCGv src1
, TCGv src2
)
627 gen_helper_taddcctv(dst
, tcg_env
, src1
, src2
);
630 static void gen_op_tsubcctv(TCGv dst
, TCGv src1
, TCGv src2
)
632 gen_helper_tsubcctv(dst
, tcg_env
, src1
, src2
);
635 static void gen_op_popc(TCGv dst
, TCGv src1
, TCGv src2
)
637 tcg_gen_ctpop_tl(dst
, src2
);
640 #ifndef TARGET_SPARC64
641 static void gen_helper_array8(TCGv dst
, TCGv src1
, TCGv src2
)
643 g_assert_not_reached();
647 static void gen_op_array16(TCGv dst
, TCGv src1
, TCGv src2
)
649 gen_helper_array8(dst
, src1
, src2
);
650 tcg_gen_shli_tl(dst
, dst
, 1);
653 static void gen_op_array32(TCGv dst
, TCGv src1
, TCGv src2
)
655 gen_helper_array8(dst
, src1
, src2
);
656 tcg_gen_shli_tl(dst
, dst
, 2);
659 static void gen_op_fpack16(TCGv_i32 dst
, TCGv_i64 src
)
661 #ifdef TARGET_SPARC64
662 gen_helper_fpack16(dst
, cpu_gsr
, src
);
664 g_assert_not_reached();
668 static void gen_op_fpackfix(TCGv_i32 dst
, TCGv_i64 src
)
670 #ifdef TARGET_SPARC64
671 gen_helper_fpackfix(dst
, cpu_gsr
, src
);
673 g_assert_not_reached();
677 static void gen_op_fpack32(TCGv_i64 dst
, TCGv_i64 src1
, TCGv_i64 src2
)
679 #ifdef TARGET_SPARC64
680 gen_helper_fpack32(dst
, cpu_gsr
, src1
, src2
);
682 g_assert_not_reached();
686 static void gen_op_faligndata(TCGv_i64 dst
, TCGv_i64 s1
, TCGv_i64 s2
)
688 #ifdef TARGET_SPARC64
693 shift
= tcg_temp_new();
695 tcg_gen_andi_tl(shift
, cpu_gsr
, 7);
696 tcg_gen_shli_tl(shift
, shift
, 3);
697 tcg_gen_shl_tl(t1
, s1
, shift
);
700 * A shift of 64 does not produce 0 in TCG. Divide this into a
701 * shift of (up to 63) followed by a constant shift of 1.
703 tcg_gen_xori_tl(shift
, shift
, 63);
704 tcg_gen_shr_tl(t2
, s2
, shift
);
705 tcg_gen_shri_tl(t2
, t2
, 1);
707 tcg_gen_or_tl(dst
, t1
, t2
);
709 g_assert_not_reached();
713 static void gen_op_bshuffle(TCGv_i64 dst
, TCGv_i64 src1
, TCGv_i64 src2
)
715 #ifdef TARGET_SPARC64
716 gen_helper_bshuffle(dst
, cpu_gsr
, src1
, src2
);
718 g_assert_not_reached();
723 static void gen_op_eval_ba(TCGv dst
)
725 tcg_gen_movi_tl(dst
, 1);
729 static void gen_op_eval_bn(TCGv dst
)
731 tcg_gen_movi_tl(dst
, 0);
735 FPSR bit field FCC1 | FCC0:
741 static void gen_mov_reg_FCC0(TCGv reg
, TCGv src
,
742 unsigned int fcc_offset
)
744 tcg_gen_shri_tl(reg
, src
, FSR_FCC0_SHIFT
+ fcc_offset
);
745 tcg_gen_andi_tl(reg
, reg
, 0x1);
748 static void gen_mov_reg_FCC1(TCGv reg
, TCGv src
, unsigned int fcc_offset
)
750 tcg_gen_shri_tl(reg
, src
, FSR_FCC1_SHIFT
+ fcc_offset
);
751 tcg_gen_andi_tl(reg
, reg
, 0x1);
755 static void gen_op_eval_fbne(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
757 TCGv t0
= tcg_temp_new();
758 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
759 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
760 tcg_gen_or_tl(dst
, dst
, t0
);
763 // 1 or 2: FCC0 ^ FCC1
764 static void gen_op_eval_fblg(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
766 TCGv t0
= tcg_temp_new();
767 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
768 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
769 tcg_gen_xor_tl(dst
, dst
, t0
);
773 static void gen_op_eval_fbul(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
775 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
779 static void gen_op_eval_fbl(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
781 TCGv t0
= tcg_temp_new();
782 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
783 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
784 tcg_gen_andc_tl(dst
, dst
, t0
);
788 static void gen_op_eval_fbug(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
790 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
794 static void gen_op_eval_fbg(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
796 TCGv t0
= tcg_temp_new();
797 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
798 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
799 tcg_gen_andc_tl(dst
, t0
, dst
);
803 static void gen_op_eval_fbu(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
805 TCGv t0
= tcg_temp_new();
806 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
807 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
808 tcg_gen_and_tl(dst
, dst
, t0
);
812 static void gen_op_eval_fbe(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
814 TCGv t0
= tcg_temp_new();
815 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
816 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
817 tcg_gen_or_tl(dst
, dst
, t0
);
818 tcg_gen_xori_tl(dst
, dst
, 0x1);
821 // 0 or 3: !(FCC0 ^ FCC1)
822 static void gen_op_eval_fbue(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
824 TCGv t0
= tcg_temp_new();
825 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
826 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
827 tcg_gen_xor_tl(dst
, dst
, t0
);
828 tcg_gen_xori_tl(dst
, dst
, 0x1);
832 static void gen_op_eval_fbge(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
834 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
835 tcg_gen_xori_tl(dst
, dst
, 0x1);
838 // !1: !(FCC0 & !FCC1)
839 static void gen_op_eval_fbuge(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
841 TCGv t0
= tcg_temp_new();
842 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
843 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
844 tcg_gen_andc_tl(dst
, dst
, t0
);
845 tcg_gen_xori_tl(dst
, dst
, 0x1);
849 static void gen_op_eval_fble(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
851 gen_mov_reg_FCC1(dst
, src
, fcc_offset
);
852 tcg_gen_xori_tl(dst
, dst
, 0x1);
855 // !2: !(!FCC0 & FCC1)
856 static void gen_op_eval_fbule(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
858 TCGv t0
= tcg_temp_new();
859 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
860 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
861 tcg_gen_andc_tl(dst
, t0
, dst
);
862 tcg_gen_xori_tl(dst
, dst
, 0x1);
865 // !3: !(FCC0 & FCC1)
866 static void gen_op_eval_fbo(TCGv dst
, TCGv src
, unsigned int fcc_offset
)
868 TCGv t0
= tcg_temp_new();
869 gen_mov_reg_FCC0(dst
, src
, fcc_offset
);
870 gen_mov_reg_FCC1(t0
, src
, fcc_offset
);
871 tcg_gen_and_tl(dst
, dst
, t0
);
872 tcg_gen_xori_tl(dst
, dst
, 0x1);
875 static void finishing_insn(DisasContext
*dc
)
878 * From here, there is no future path through an unwinding exception.
879 * If the current insn cannot raise an exception, the computation of
880 * cpu_cond may be able to be elided.
882 if (dc
->cpu_cond_live
) {
883 tcg_gen_discard_tl(cpu_cond
);
884 dc
->cpu_cond_live
= false;
888 static void gen_generic_branch(DisasContext
*dc
)
890 TCGv npc0
= tcg_constant_tl(dc
->jump_pc
[0]);
891 TCGv npc1
= tcg_constant_tl(dc
->jump_pc
[1]);
892 TCGv c2
= tcg_constant_tl(dc
->jump
.c2
);
894 tcg_gen_movcond_tl(dc
->jump
.cond
, cpu_npc
, dc
->jump
.c1
, c2
, npc0
, npc1
);
897 /* call this function before using the condition register as it may
898 have been set for a jump */
899 static void flush_cond(DisasContext
*dc
)
901 if (dc
->npc
== JUMP_PC
) {
902 gen_generic_branch(dc
);
903 dc
->npc
= DYNAMIC_PC_LOOKUP
;
907 static void save_npc(DisasContext
*dc
)
912 gen_generic_branch(dc
);
913 dc
->npc
= DYNAMIC_PC_LOOKUP
;
916 case DYNAMIC_PC_LOOKUP
:
919 g_assert_not_reached();
922 tcg_gen_movi_tl(cpu_npc
, dc
->npc
);
926 static void save_state(DisasContext
*dc
)
928 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
932 static void gen_exception(DisasContext
*dc
, int which
)
936 gen_helper_raise_exception(tcg_env
, tcg_constant_i32(which
));
937 dc
->base
.is_jmp
= DISAS_NORETURN
;
940 static TCGLabel
*delay_exceptionv(DisasContext
*dc
, TCGv_i32 excp
)
942 DisasDelayException
*e
= g_new0(DisasDelayException
, 1);
944 e
->next
= dc
->delay_excp_list
;
945 dc
->delay_excp_list
= e
;
947 e
->lab
= gen_new_label();
950 /* Caller must have used flush_cond before branch. */
951 assert(e
->npc
!= JUMP_PC
);
957 static TCGLabel
*delay_exception(DisasContext
*dc
, int excp
)
959 return delay_exceptionv(dc
, tcg_constant_i32(excp
));
962 static void gen_check_align(DisasContext
*dc
, TCGv addr
, int mask
)
964 TCGv t
= tcg_temp_new();
967 tcg_gen_andi_tl(t
, addr
, mask
);
970 lab
= delay_exception(dc
, TT_UNALIGNED
);
971 tcg_gen_brcondi_tl(TCG_COND_NE
, t
, 0, lab
);
974 static void gen_mov_pc_npc(DisasContext
*dc
)
981 gen_generic_branch(dc
);
982 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
983 dc
->pc
= DYNAMIC_PC_LOOKUP
;
986 case DYNAMIC_PC_LOOKUP
:
987 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
991 g_assert_not_reached();
998 static void gen_compare(DisasCompare
*cmp
, bool xcc
, unsigned int cond
,
1003 cmp
->c1
= t1
= tcg_temp_new();
1007 case 0x0: /* never */
1008 cmp
->cond
= TCG_COND_NEVER
;
1009 cmp
->c1
= tcg_constant_tl(0);
1012 case 0x1: /* eq: Z */
1013 cmp
->cond
= TCG_COND_EQ
;
1014 if (TARGET_LONG_BITS
== 32 || xcc
) {
1015 tcg_gen_mov_tl(t1
, cpu_cc_Z
);
1017 tcg_gen_ext32u_tl(t1
, cpu_icc_Z
);
1021 case 0x2: /* le: Z | (N ^ V) */
1024 * cc_Z || (N ^ V) < 0 NE
1025 * cc_Z && !((N ^ V) < 0) EQ
1026 * cc_Z & ~((N ^ V) >> TLB) EQ
1028 cmp
->cond
= TCG_COND_EQ
;
1029 tcg_gen_xor_tl(t1
, cpu_cc_N
, cpu_cc_V
);
1030 tcg_gen_sextract_tl(t1
, t1
, xcc
? 63 : 31, 1);
1031 tcg_gen_andc_tl(t1
, xcc
? cpu_cc_Z
: cpu_icc_Z
, t1
);
1032 if (TARGET_LONG_BITS
== 64 && !xcc
) {
1033 tcg_gen_ext32u_tl(t1
, t1
);
1037 case 0x3: /* lt: N ^ V */
1038 cmp
->cond
= TCG_COND_LT
;
1039 tcg_gen_xor_tl(t1
, cpu_cc_N
, cpu_cc_V
);
1040 if (TARGET_LONG_BITS
== 64 && !xcc
) {
1041 tcg_gen_ext32s_tl(t1
, t1
);
1045 case 0x4: /* leu: Z | C */
1048 * cc_Z == 0 || cc_C != 0 NE
1049 * cc_Z != 0 && cc_C == 0 EQ
1050 * cc_Z & (cc_C ? 0 : -1) EQ
1051 * cc_Z & (cc_C - 1) EQ
1053 cmp
->cond
= TCG_COND_EQ
;
1054 if (TARGET_LONG_BITS
== 32 || xcc
) {
1055 tcg_gen_subi_tl(t1
, cpu_cc_C
, 1);
1056 tcg_gen_and_tl(t1
, t1
, cpu_cc_Z
);
1058 tcg_gen_extract_tl(t1
, cpu_icc_C
, 32, 1);
1059 tcg_gen_subi_tl(t1
, t1
, 1);
1060 tcg_gen_and_tl(t1
, t1
, cpu_icc_Z
);
1061 tcg_gen_ext32u_tl(t1
, t1
);
1065 case 0x5: /* ltu: C */
1066 cmp
->cond
= TCG_COND_NE
;
1067 if (TARGET_LONG_BITS
== 32 || xcc
) {
1068 tcg_gen_mov_tl(t1
, cpu_cc_C
);
1070 tcg_gen_extract_tl(t1
, cpu_icc_C
, 32, 1);
1074 case 0x6: /* neg: N */
1075 cmp
->cond
= TCG_COND_LT
;
1076 if (TARGET_LONG_BITS
== 32 || xcc
) {
1077 tcg_gen_mov_tl(t1
, cpu_cc_N
);
1079 tcg_gen_ext32s_tl(t1
, cpu_cc_N
);
1083 case 0x7: /* vs: V */
1084 cmp
->cond
= TCG_COND_LT
;
1085 if (TARGET_LONG_BITS
== 32 || xcc
) {
1086 tcg_gen_mov_tl(t1
, cpu_cc_V
);
1088 tcg_gen_ext32s_tl(t1
, cpu_cc_V
);
1093 cmp
->cond
= tcg_invert_cond(cmp
->cond
);
1097 static void gen_fcompare(DisasCompare
*cmp
, unsigned int cc
, unsigned int cond
)
1099 unsigned int offset
;
1102 /* For now we still generate a straight boolean result. */
1103 cmp
->cond
= TCG_COND_NE
;
1104 cmp
->c1
= r_dst
= tcg_temp_new();
1123 fsr
= tcg_temp_new();
1124 tcg_gen_ld_tl(fsr
, tcg_env
, offsetof(CPUSPARCState
, fsr
));
1127 gen_op_eval_bn(r_dst
);
1130 gen_op_eval_fbne(r_dst
, fsr
, offset
);
1133 gen_op_eval_fblg(r_dst
, fsr
, offset
);
1136 gen_op_eval_fbul(r_dst
, fsr
, offset
);
1139 gen_op_eval_fbl(r_dst
, fsr
, offset
);
1142 gen_op_eval_fbug(r_dst
, fsr
, offset
);
1145 gen_op_eval_fbg(r_dst
, fsr
, offset
);
1148 gen_op_eval_fbu(r_dst
, fsr
, offset
);
1151 gen_op_eval_ba(r_dst
);
1154 gen_op_eval_fbe(r_dst
, fsr
, offset
);
1157 gen_op_eval_fbue(r_dst
, fsr
, offset
);
1160 gen_op_eval_fbge(r_dst
, fsr
, offset
);
1163 gen_op_eval_fbuge(r_dst
, fsr
, offset
);
1166 gen_op_eval_fble(r_dst
, fsr
, offset
);
1169 gen_op_eval_fbule(r_dst
, fsr
, offset
);
1172 gen_op_eval_fbo(r_dst
, fsr
, offset
);
1177 static bool gen_compare_reg(DisasCompare
*cmp
, int cond
, TCGv r_src
)
1179 static const TCGCond cond_reg
[4] = {
1180 TCG_COND_NEVER
, /* reserved */
1187 if ((cond
& 3) == 0) {
1190 tcond
= cond_reg
[cond
& 3];
1192 tcond
= tcg_invert_cond(tcond
);
1196 cmp
->c1
= tcg_temp_new();
1198 tcg_gen_mov_tl(cmp
->c1
, r_src
);
1202 static void gen_op_clear_ieee_excp_and_FTT(void)
1204 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env
,
1205 offsetof(CPUSPARCState
, fsr_cexc_ftt
));
1208 static void gen_op_fmovs(TCGv_i32 dst
, TCGv_i32 src
)
1210 gen_op_clear_ieee_excp_and_FTT();
1211 tcg_gen_mov_i32(dst
, src
);
1214 static void gen_op_fnegs(TCGv_i32 dst
, TCGv_i32 src
)
1216 gen_op_clear_ieee_excp_and_FTT();
1217 tcg_gen_xori_i32(dst
, src
, 1u << 31);
1220 static void gen_op_fabss(TCGv_i32 dst
, TCGv_i32 src
)
1222 gen_op_clear_ieee_excp_and_FTT();
1223 tcg_gen_andi_i32(dst
, src
, ~(1u << 31));
1226 static void gen_op_fmovd(TCGv_i64 dst
, TCGv_i64 src
)
1228 gen_op_clear_ieee_excp_and_FTT();
1229 tcg_gen_mov_i64(dst
, src
);
1232 static void gen_op_fnegd(TCGv_i64 dst
, TCGv_i64 src
)
1234 gen_op_clear_ieee_excp_and_FTT();
1235 tcg_gen_xori_i64(dst
, src
, 1ull << 63);
1238 static void gen_op_fabsd(TCGv_i64 dst
, TCGv_i64 src
)
1240 gen_op_clear_ieee_excp_and_FTT();
1241 tcg_gen_andi_i64(dst
, src
, ~(1ull << 63));
1244 static void gen_op_fnegq(TCGv_i128 dst
, TCGv_i128 src
)
1246 TCGv_i64 l
= tcg_temp_new_i64();
1247 TCGv_i64 h
= tcg_temp_new_i64();
1249 tcg_gen_extr_i128_i64(l
, h
, src
);
1250 tcg_gen_xori_i64(h
, h
, 1ull << 63);
1251 tcg_gen_concat_i64_i128(dst
, l
, h
);
1254 static void gen_op_fabsq(TCGv_i128 dst
, TCGv_i128 src
)
1256 TCGv_i64 l
= tcg_temp_new_i64();
1257 TCGv_i64 h
= tcg_temp_new_i64();
1259 tcg_gen_extr_i128_i64(l
, h
, src
);
1260 tcg_gen_andi_i64(h
, h
, ~(1ull << 63));
1261 tcg_gen_concat_i64_i128(dst
, l
, h
);
1264 #ifdef TARGET_SPARC64
1265 static void gen_op_fcmps(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1269 gen_helper_fcmps(tcg_env
, r_rs1
, r_rs2
);
1272 gen_helper_fcmps_fcc1(tcg_env
, r_rs1
, r_rs2
);
1275 gen_helper_fcmps_fcc2(tcg_env
, r_rs1
, r_rs2
);
1278 gen_helper_fcmps_fcc3(tcg_env
, r_rs1
, r_rs2
);
1283 static void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1287 gen_helper_fcmpd(tcg_env
, r_rs1
, r_rs2
);
1290 gen_helper_fcmpd_fcc1(tcg_env
, r_rs1
, r_rs2
);
1293 gen_helper_fcmpd_fcc2(tcg_env
, r_rs1
, r_rs2
);
1296 gen_helper_fcmpd_fcc3(tcg_env
, r_rs1
, r_rs2
);
1301 static void gen_op_fcmpq(int fccno
, TCGv_i128 r_rs1
, TCGv_i128 r_rs2
)
1305 gen_helper_fcmpq(tcg_env
, r_rs1
, r_rs2
);
1308 gen_helper_fcmpq_fcc1(tcg_env
, r_rs1
, r_rs2
);
1311 gen_helper_fcmpq_fcc2(tcg_env
, r_rs1
, r_rs2
);
1314 gen_helper_fcmpq_fcc3(tcg_env
, r_rs1
, r_rs2
);
1319 static void gen_op_fcmpes(int fccno
, TCGv_i32 r_rs1
, TCGv_i32 r_rs2
)
1323 gen_helper_fcmpes(tcg_env
, r_rs1
, r_rs2
);
1326 gen_helper_fcmpes_fcc1(tcg_env
, r_rs1
, r_rs2
);
1329 gen_helper_fcmpes_fcc2(tcg_env
, r_rs1
, r_rs2
);
1332 gen_helper_fcmpes_fcc3(tcg_env
, r_rs1
, r_rs2
);
1337 static void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1341 gen_helper_fcmped(tcg_env
, r_rs1
, r_rs2
);
1344 gen_helper_fcmped_fcc1(tcg_env
, r_rs1
, r_rs2
);
1347 gen_helper_fcmped_fcc2(tcg_env
, r_rs1
, r_rs2
);
1350 gen_helper_fcmped_fcc3(tcg_env
, r_rs1
, r_rs2
);
1355 static void gen_op_fcmpeq(int fccno
, TCGv_i128 r_rs1
, TCGv_i128 r_rs2
)
1359 gen_helper_fcmpeq(tcg_env
, r_rs1
, r_rs2
);
1362 gen_helper_fcmpeq_fcc1(tcg_env
, r_rs1
, r_rs2
);
1365 gen_helper_fcmpeq_fcc2(tcg_env
, r_rs1
, r_rs2
);
1368 gen_helper_fcmpeq_fcc3(tcg_env
, r_rs1
, r_rs2
);
1375 static void gen_op_fcmps(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1377 gen_helper_fcmps(tcg_env
, r_rs1
, r_rs2
);
1380 static void gen_op_fcmpd(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1382 gen_helper_fcmpd(tcg_env
, r_rs1
, r_rs2
);
1385 static void gen_op_fcmpq(int fccno
, TCGv_i128 r_rs1
, TCGv_i128 r_rs2
)
1387 gen_helper_fcmpq(tcg_env
, r_rs1
, r_rs2
);
1390 static void gen_op_fcmpes(int fccno
, TCGv r_rs1
, TCGv r_rs2
)
1392 gen_helper_fcmpes(tcg_env
, r_rs1
, r_rs2
);
1395 static void gen_op_fcmped(int fccno
, TCGv_i64 r_rs1
, TCGv_i64 r_rs2
)
1397 gen_helper_fcmped(tcg_env
, r_rs1
, r_rs2
);
1400 static void gen_op_fcmpeq(int fccno
, TCGv_i128 r_rs1
, TCGv_i128 r_rs2
)
1402 gen_helper_fcmpeq(tcg_env
, r_rs1
, r_rs2
);
1406 static void gen_op_fpexception_im(DisasContext
*dc
, int ftt
)
1409 * CEXC is only set when succesfully completing an FPop,
1410 * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception.
1411 * Thus we can simply store FTT into this field.
1413 tcg_gen_st_i32(tcg_constant_i32(ftt
), tcg_env
,
1414 offsetof(CPUSPARCState
, fsr_cexc_ftt
));
1415 gen_exception(dc
, TT_FP_EXCP
);
1418 static int gen_trap_ifnofpu(DisasContext
*dc
)
1420 #if !defined(CONFIG_USER_ONLY)
1421 if (!dc
->fpu_enabled
) {
1422 gen_exception(dc
, TT_NFPU_INSN
);
1450 * For asi == -1, treat as non-asi.
1451 * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1453 static DisasASI
resolve_asi(DisasContext
*dc
, int asi
, MemOp memop
)
1455 ASIType type
= GET_ASI_HELPER
;
1456 int mem_idx
= dc
->mem_idx
;
1459 /* Artificial "non-asi" case. */
1460 type
= GET_ASI_DIRECT
;
1464 #ifndef TARGET_SPARC64
1465 /* Before v9, all asis are immediate and privileged. */
1467 gen_exception(dc
, TT_ILL_INSN
);
1468 type
= GET_ASI_EXCP
;
1469 } else if (supervisor(dc
)
1470 /* Note that LEON accepts ASI_USERDATA in user mode, for
1471 use with CASA. Also note that previous versions of
1472 QEMU allowed (and old versions of gcc emitted) ASI_P
1473 for LEON, which is incorrect. */
1474 || (asi
== ASI_USERDATA
1475 && (dc
->def
->features
& CPU_FEATURE_CASA
))) {
1477 case ASI_USERDATA
: /* User data access */
1478 mem_idx
= MMU_USER_IDX
;
1479 type
= GET_ASI_DIRECT
;
1481 case ASI_KERNELDATA
: /* Supervisor data access */
1482 mem_idx
= MMU_KERNEL_IDX
;
1483 type
= GET_ASI_DIRECT
;
1485 case ASI_M_BYPASS
: /* MMU passthrough */
1486 case ASI_LEON_BYPASS
: /* LEON MMU passthrough */
1487 mem_idx
= MMU_PHYS_IDX
;
1488 type
= GET_ASI_DIRECT
;
1490 case ASI_M_BCOPY
: /* Block copy, sta access */
1491 mem_idx
= MMU_KERNEL_IDX
;
1492 type
= GET_ASI_BCOPY
;
1494 case ASI_M_BFILL
: /* Block fill, stda access */
1495 mem_idx
= MMU_KERNEL_IDX
;
1496 type
= GET_ASI_BFILL
;
1500 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
1501 * permissions check in get_physical_address(..).
1503 mem_idx
= (dc
->mem_idx
== MMU_PHYS_IDX
) ? MMU_PHYS_IDX
: mem_idx
;
1505 gen_exception(dc
, TT_PRIV_INSN
);
1506 type
= GET_ASI_EXCP
;
1512 /* With v9, all asis below 0x80 are privileged. */
1513 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1514 down that bit into DisasContext. For the moment that's ok,
1515 since the direct implementations below doesn't have any ASIs
1516 in the restricted [0x30, 0x7f] range, and the check will be
1517 done properly in the helper. */
1518 if (!supervisor(dc
) && asi
< 0x80) {
1519 gen_exception(dc
, TT_PRIV_ACT
);
1520 type
= GET_ASI_EXCP
;
1523 case ASI_REAL
: /* Bypass */
1524 case ASI_REAL_IO
: /* Bypass, non-cacheable */
1525 case ASI_REAL_L
: /* Bypass LE */
1526 case ASI_REAL_IO_L
: /* Bypass, non-cacheable LE */
1527 case ASI_TWINX_REAL
: /* Real address, twinx */
1528 case ASI_TWINX_REAL_L
: /* Real address, twinx, LE */
1529 case ASI_QUAD_LDD_PHYS
:
1530 case ASI_QUAD_LDD_PHYS_L
:
1531 mem_idx
= MMU_PHYS_IDX
;
1533 case ASI_N
: /* Nucleus */
1534 case ASI_NL
: /* Nucleus LE */
1537 case ASI_NUCLEUS_QUAD_LDD
:
1538 case ASI_NUCLEUS_QUAD_LDD_L
:
1539 if (hypervisor(dc
)) {
1540 mem_idx
= MMU_PHYS_IDX
;
1542 mem_idx
= MMU_NUCLEUS_IDX
;
1545 case ASI_AIUP
: /* As if user primary */
1546 case ASI_AIUPL
: /* As if user primary LE */
1547 case ASI_TWINX_AIUP
:
1548 case ASI_TWINX_AIUP_L
:
1549 case ASI_BLK_AIUP_4V
:
1550 case ASI_BLK_AIUP_L_4V
:
1553 mem_idx
= MMU_USER_IDX
;
1555 case ASI_AIUS
: /* As if user secondary */
1556 case ASI_AIUSL
: /* As if user secondary LE */
1557 case ASI_TWINX_AIUS
:
1558 case ASI_TWINX_AIUS_L
:
1559 case ASI_BLK_AIUS_4V
:
1560 case ASI_BLK_AIUS_L_4V
:
1563 mem_idx
= MMU_USER_SECONDARY_IDX
;
1565 case ASI_S
: /* Secondary */
1566 case ASI_SL
: /* Secondary LE */
1569 case ASI_BLK_COMMIT_S
:
1576 if (mem_idx
== MMU_USER_IDX
) {
1577 mem_idx
= MMU_USER_SECONDARY_IDX
;
1578 } else if (mem_idx
== MMU_KERNEL_IDX
) {
1579 mem_idx
= MMU_KERNEL_SECONDARY_IDX
;
1582 case ASI_P
: /* Primary */
1583 case ASI_PL
: /* Primary LE */
1586 case ASI_BLK_COMMIT_P
:
1610 type
= GET_ASI_DIRECT
;
1612 case ASI_TWINX_REAL
:
1613 case ASI_TWINX_REAL_L
:
1616 case ASI_TWINX_AIUP
:
1617 case ASI_TWINX_AIUP_L
:
1618 case ASI_TWINX_AIUS
:
1619 case ASI_TWINX_AIUS_L
:
1624 case ASI_QUAD_LDD_PHYS
:
1625 case ASI_QUAD_LDD_PHYS_L
:
1626 case ASI_NUCLEUS_QUAD_LDD
:
1627 case ASI_NUCLEUS_QUAD_LDD_L
:
1628 type
= GET_ASI_DTWINX
;
1630 case ASI_BLK_COMMIT_P
:
1631 case ASI_BLK_COMMIT_S
:
1632 case ASI_BLK_AIUP_4V
:
1633 case ASI_BLK_AIUP_L_4V
:
1636 case ASI_BLK_AIUS_4V
:
1637 case ASI_BLK_AIUS_L_4V
:
1644 type
= GET_ASI_BLOCK
;
1651 type
= GET_ASI_SHORT
;
1658 type
= GET_ASI_SHORT
;
1661 /* The little-endian asis all have bit 3 set. */
1669 return (DisasASI
){ type
, asi
, mem_idx
, memop
};
1672 #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1673 static void gen_helper_ld_asi(TCGv_i64 r
, TCGv_env e
, TCGv a
,
1674 TCGv_i32 asi
, TCGv_i32 mop
)
1676 g_assert_not_reached();
1679 static void gen_helper_st_asi(TCGv_env e
, TCGv a
, TCGv_i64 r
,
1680 TCGv_i32 asi
, TCGv_i32 mop
)
1682 g_assert_not_reached();
1686 static void gen_ld_asi(DisasContext
*dc
, DisasASI
*da
, TCGv dst
, TCGv addr
)
1691 case GET_ASI_DTWINX
: /* Reserved for ldda. */
1692 gen_exception(dc
, TT_ILL_INSN
);
1694 case GET_ASI_DIRECT
:
1695 tcg_gen_qemu_ld_tl(dst
, addr
, da
->mem_idx
, da
->memop
| MO_ALIGN
);
1699 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
1700 TCGv_i32 r_mop
= tcg_constant_i32(da
->memop
| MO_ALIGN
);
1703 #ifdef TARGET_SPARC64
1704 gen_helper_ld_asi(dst
, tcg_env
, addr
, r_asi
, r_mop
);
1707 TCGv_i64 t64
= tcg_temp_new_i64();
1708 gen_helper_ld_asi(t64
, tcg_env
, addr
, r_asi
, r_mop
);
1709 tcg_gen_trunc_i64_tl(dst
, t64
);
1717 static void gen_st_asi(DisasContext
*dc
, DisasASI
*da
, TCGv src
, TCGv addr
)
1723 case GET_ASI_DTWINX
: /* Reserved for stda. */
1724 if (TARGET_LONG_BITS
== 32) {
1725 gen_exception(dc
, TT_ILL_INSN
);
1727 } else if (!(dc
->def
->features
& CPU_FEATURE_HYPV
)) {
1728 /* Pre OpenSPARC CPUs don't have these */
1729 gen_exception(dc
, TT_ILL_INSN
);
1732 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1735 case GET_ASI_DIRECT
:
1736 tcg_gen_qemu_st_tl(src
, addr
, da
->mem_idx
, da
->memop
| MO_ALIGN
);
1740 assert(TARGET_LONG_BITS
== 32);
1742 * Copy 32 bytes from the address in SRC to ADDR.
1744 * From Ross RT625 hyperSPARC manual, section 4.6:
1745 * "Block Copy and Block Fill will work only on cache line boundaries."
1747 * It does not specify if an unaliged address is truncated or trapped.
1748 * Previous qemu behaviour was to truncate to 4 byte alignment, which
1749 * is obviously wrong. The only place I can see this used is in the
1750 * Linux kernel which begins with page alignment, advancing by 32,
1751 * so is always aligned. Assume truncation as the simpler option.
1753 * Since the loads and stores are paired, allow the copy to happen
1754 * in the host endianness. The copy need not be atomic.
1757 MemOp mop
= MO_128
| MO_ATOM_IFALIGN_PAIR
;
1758 TCGv saddr
= tcg_temp_new();
1759 TCGv daddr
= tcg_temp_new();
1760 TCGv_i128 tmp
= tcg_temp_new_i128();
1762 tcg_gen_andi_tl(saddr
, src
, -32);
1763 tcg_gen_andi_tl(daddr
, addr
, -32);
1764 tcg_gen_qemu_ld_i128(tmp
, saddr
, da
->mem_idx
, mop
);
1765 tcg_gen_qemu_st_i128(tmp
, daddr
, da
->mem_idx
, mop
);
1766 tcg_gen_addi_tl(saddr
, saddr
, 16);
1767 tcg_gen_addi_tl(daddr
, daddr
, 16);
1768 tcg_gen_qemu_ld_i128(tmp
, saddr
, da
->mem_idx
, mop
);
1769 tcg_gen_qemu_st_i128(tmp
, daddr
, da
->mem_idx
, mop
);
1775 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
1776 TCGv_i32 r_mop
= tcg_constant_i32(da
->memop
| MO_ALIGN
);
1779 #ifdef TARGET_SPARC64
1780 gen_helper_st_asi(tcg_env
, addr
, src
, r_asi
, r_mop
);
1783 TCGv_i64 t64
= tcg_temp_new_i64();
1784 tcg_gen_extu_tl_i64(t64
, src
);
1785 gen_helper_st_asi(tcg_env
, addr
, t64
, r_asi
, r_mop
);
1789 /* A write to a TLB register may alter page maps. End the TB. */
1790 dc
->npc
= DYNAMIC_PC
;
1796 static void gen_swap_asi(DisasContext
*dc
, DisasASI
*da
,
1797 TCGv dst
, TCGv src
, TCGv addr
)
1802 case GET_ASI_DIRECT
:
1803 tcg_gen_atomic_xchg_tl(dst
, addr
, src
,
1804 da
->mem_idx
, da
->memop
| MO_ALIGN
);
1807 /* ??? Should be DAE_invalid_asi. */
1808 gen_exception(dc
, TT_DATA_ACCESS
);
1813 static void gen_cas_asi(DisasContext
*dc
, DisasASI
*da
,
1814 TCGv oldv
, TCGv newv
, TCGv cmpv
, TCGv addr
)
1819 case GET_ASI_DIRECT
:
1820 tcg_gen_atomic_cmpxchg_tl(oldv
, addr
, cmpv
, newv
,
1821 da
->mem_idx
, da
->memop
| MO_ALIGN
);
1824 /* ??? Should be DAE_invalid_asi. */
1825 gen_exception(dc
, TT_DATA_ACCESS
);
1830 static void gen_ldstub_asi(DisasContext
*dc
, DisasASI
*da
, TCGv dst
, TCGv addr
)
1835 case GET_ASI_DIRECT
:
1836 tcg_gen_atomic_xchg_tl(dst
, addr
, tcg_constant_tl(0xff),
1837 da
->mem_idx
, MO_UB
);
1840 /* ??? In theory, this should be raise DAE_invalid_asi.
1841 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
1842 if (tb_cflags(dc
->base
.tb
) & CF_PARALLEL
) {
1843 gen_helper_exit_atomic(tcg_env
);
1845 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
1846 TCGv_i32 r_mop
= tcg_constant_i32(MO_UB
);
1850 t64
= tcg_temp_new_i64();
1851 gen_helper_ld_asi(t64
, tcg_env
, addr
, r_asi
, r_mop
);
1853 s64
= tcg_constant_i64(0xff);
1854 gen_helper_st_asi(tcg_env
, addr
, s64
, r_asi
, r_mop
);
1856 tcg_gen_trunc_i64_tl(dst
, t64
);
1859 dc
->npc
= DYNAMIC_PC
;
1865 static void gen_ldf_asi(DisasContext
*dc
, DisasASI
*da
, MemOp orig_size
,
1868 MemOp memop
= da
->memop
;
1869 MemOp size
= memop
& MO_SIZE
;
1874 /* TODO: Use 128-bit load/store below. */
1875 if (size
== MO_128
) {
1876 memop
= (memop
& ~MO_SIZE
) | MO_64
;
1883 case GET_ASI_DIRECT
:
1884 memop
|= MO_ALIGN_4
;
1887 d32
= tcg_temp_new_i32();
1888 tcg_gen_qemu_ld_i32(d32
, addr
, da
->mem_idx
, memop
);
1889 gen_store_fpr_F(dc
, rd
, d32
);
1893 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
->mem_idx
, memop
);
1897 d64
= tcg_temp_new_i64();
1898 tcg_gen_qemu_ld_i64(d64
, addr
, da
->mem_idx
, memop
);
1899 addr_tmp
= tcg_temp_new();
1900 tcg_gen_addi_tl(addr_tmp
, addr
, 8);
1901 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2 + 1], addr_tmp
, da
->mem_idx
, memop
);
1902 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
1905 g_assert_not_reached();
1910 /* Valid for lddfa on aligned registers only. */
1911 if (orig_size
== MO_64
&& (rd
& 7) == 0) {
1912 /* The first operation checks required alignment. */
1913 addr_tmp
= tcg_temp_new();
1914 for (int i
= 0; ; ++i
) {
1915 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2 + i
], addr
, da
->mem_idx
,
1916 memop
| (i
== 0 ? MO_ALIGN_64
: 0));
1920 tcg_gen_addi_tl(addr_tmp
, addr
, 8);
1924 gen_exception(dc
, TT_ILL_INSN
);
1929 /* Valid for lddfa only. */
1930 if (orig_size
== MO_64
) {
1931 tcg_gen_qemu_ld_i64(cpu_fpr
[rd
/ 2], addr
, da
->mem_idx
,
1934 gen_exception(dc
, TT_ILL_INSN
);
1940 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
1941 TCGv_i32 r_mop
= tcg_constant_i32(memop
| MO_ALIGN
);
1944 /* According to the table in the UA2011 manual, the only
1945 other asis that are valid for ldfa/lddfa/ldqfa are
1946 the NO_FAULT asis. We still need a helper for these,
1947 but we can just use the integer asi helper for them. */
1950 d64
= tcg_temp_new_i64();
1951 gen_helper_ld_asi(d64
, tcg_env
, addr
, r_asi
, r_mop
);
1952 d32
= tcg_temp_new_i32();
1953 tcg_gen_extrl_i64_i32(d32
, d64
);
1954 gen_store_fpr_F(dc
, rd
, d32
);
1957 gen_helper_ld_asi(cpu_fpr
[rd
/ 2], tcg_env
, addr
,
1961 d64
= tcg_temp_new_i64();
1962 gen_helper_ld_asi(d64
, tcg_env
, addr
, r_asi
, r_mop
);
1963 addr_tmp
= tcg_temp_new();
1964 tcg_gen_addi_tl(addr_tmp
, addr
, 8);
1965 gen_helper_ld_asi(cpu_fpr
[rd
/ 2 + 1], tcg_env
, addr_tmp
,
1967 tcg_gen_mov_i64(cpu_fpr
[rd
/ 2], d64
);
1970 g_assert_not_reached();
1977 static void gen_stf_asi(DisasContext
*dc
, DisasASI
*da
, MemOp orig_size
,
1980 MemOp memop
= da
->memop
;
1981 MemOp size
= memop
& MO_SIZE
;
1985 /* TODO: Use 128-bit load/store below. */
1986 if (size
== MO_128
) {
1987 memop
= (memop
& ~MO_SIZE
) | MO_64
;
1994 case GET_ASI_DIRECT
:
1995 memop
|= MO_ALIGN_4
;
1998 d32
= gen_load_fpr_F(dc
, rd
);
1999 tcg_gen_qemu_st_i32(d32
, addr
, da
->mem_idx
, memop
| MO_ALIGN
);
2002 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
->mem_idx
,
2003 memop
| MO_ALIGN_4
);
2006 /* Only 4-byte alignment required. However, it is legal for the
2007 cpu to signal the alignment fault, and the OS trap handler is
2008 required to fix it up. Requiring 16-byte alignment here avoids
2009 having to probe the second page before performing the first
2011 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
->mem_idx
,
2012 memop
| MO_ALIGN_16
);
2013 addr_tmp
= tcg_temp_new();
2014 tcg_gen_addi_tl(addr_tmp
, addr
, 8);
2015 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2 + 1], addr_tmp
, da
->mem_idx
, memop
);
2018 g_assert_not_reached();
2023 /* Valid for stdfa on aligned registers only. */
2024 if (orig_size
== MO_64
&& (rd
& 7) == 0) {
2025 /* The first operation checks required alignment. */
2026 addr_tmp
= tcg_temp_new();
2027 for (int i
= 0; ; ++i
) {
2028 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2 + i
], addr
, da
->mem_idx
,
2029 memop
| (i
== 0 ? MO_ALIGN_64
: 0));
2033 tcg_gen_addi_tl(addr_tmp
, addr
, 8);
2037 gen_exception(dc
, TT_ILL_INSN
);
2042 /* Valid for stdfa only. */
2043 if (orig_size
== MO_64
) {
2044 tcg_gen_qemu_st_i64(cpu_fpr
[rd
/ 2], addr
, da
->mem_idx
,
2047 gen_exception(dc
, TT_ILL_INSN
);
2052 /* According to the table in the UA2011 manual, the only
2053 other asis that are valid for ldfa/lddfa/ldqfa are
2054 the PST* asis, which aren't currently handled. */
2055 gen_exception(dc
, TT_ILL_INSN
);
2060 static void gen_ldda_asi(DisasContext
*dc
, DisasASI
*da
, TCGv addr
, int rd
)
2062 TCGv hi
= gen_dest_gpr(dc
, rd
);
2063 TCGv lo
= gen_dest_gpr(dc
, rd
+ 1);
2069 case GET_ASI_DTWINX
:
2070 #ifdef TARGET_SPARC64
2072 MemOp mop
= (da
->memop
& MO_BSWAP
) | MO_128
| MO_ALIGN_16
;
2073 TCGv_i128 t
= tcg_temp_new_i128();
2075 tcg_gen_qemu_ld_i128(t
, addr
, da
->mem_idx
, mop
);
2077 * Note that LE twinx acts as if each 64-bit register result is
2078 * byte swapped. We perform one 128-bit LE load, so must swap
2079 * the order of the writebacks.
2081 if ((mop
& MO_BSWAP
) == MO_TE
) {
2082 tcg_gen_extr_i128_i64(lo
, hi
, t
);
2084 tcg_gen_extr_i128_i64(hi
, lo
, t
);
2089 g_assert_not_reached();
2092 case GET_ASI_DIRECT
:
2094 TCGv_i64 tmp
= tcg_temp_new_i64();
2096 tcg_gen_qemu_ld_i64(tmp
, addr
, da
->mem_idx
, da
->memop
| MO_ALIGN
);
2098 /* Note that LE ldda acts as if each 32-bit register
2099 result is byte swapped. Having just performed one
2100 64-bit bswap, we need now to swap the writebacks. */
2101 if ((da
->memop
& MO_BSWAP
) == MO_TE
) {
2102 tcg_gen_extr_i64_tl(lo
, hi
, tmp
);
2104 tcg_gen_extr_i64_tl(hi
, lo
, tmp
);
2110 /* ??? In theory we've handled all of the ASIs that are valid
2111 for ldda, and this should raise DAE_invalid_asi. However,
2112 real hardware allows others. This can be seen with e.g.
2113 FreeBSD 10.3 wrt ASI_IC_TAG. */
2115 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
2116 TCGv_i32 r_mop
= tcg_constant_i32(da
->memop
);
2117 TCGv_i64 tmp
= tcg_temp_new_i64();
2120 gen_helper_ld_asi(tmp
, tcg_env
, addr
, r_asi
, r_mop
);
2123 if ((da
->memop
& MO_BSWAP
) == MO_TE
) {
2124 tcg_gen_extr_i64_tl(lo
, hi
, tmp
);
2126 tcg_gen_extr_i64_tl(hi
, lo
, tmp
);
2132 gen_store_gpr(dc
, rd
, hi
);
2133 gen_store_gpr(dc
, rd
+ 1, lo
);
2136 static void gen_stda_asi(DisasContext
*dc
, DisasASI
*da
, TCGv addr
, int rd
)
2138 TCGv hi
= gen_load_gpr(dc
, rd
);
2139 TCGv lo
= gen_load_gpr(dc
, rd
+ 1);
2145 case GET_ASI_DTWINX
:
2146 #ifdef TARGET_SPARC64
2148 MemOp mop
= (da
->memop
& MO_BSWAP
) | MO_128
| MO_ALIGN_16
;
2149 TCGv_i128 t
= tcg_temp_new_i128();
2152 * Note that LE twinx acts as if each 64-bit register result is
2153 * byte swapped. We perform one 128-bit LE store, so must swap
2154 * the order of the construction.
2156 if ((mop
& MO_BSWAP
) == MO_TE
) {
2157 tcg_gen_concat_i64_i128(t
, lo
, hi
);
2159 tcg_gen_concat_i64_i128(t
, hi
, lo
);
2161 tcg_gen_qemu_st_i128(t
, addr
, da
->mem_idx
, mop
);
2165 g_assert_not_reached();
2168 case GET_ASI_DIRECT
:
2170 TCGv_i64 t64
= tcg_temp_new_i64();
2172 /* Note that LE stda acts as if each 32-bit register result is
2173 byte swapped. We will perform one 64-bit LE store, so now
2174 we must swap the order of the construction. */
2175 if ((da
->memop
& MO_BSWAP
) == MO_TE
) {
2176 tcg_gen_concat_tl_i64(t64
, lo
, hi
);
2178 tcg_gen_concat_tl_i64(t64
, hi
, lo
);
2180 tcg_gen_qemu_st_i64(t64
, addr
, da
->mem_idx
, da
->memop
| MO_ALIGN
);
2185 assert(TARGET_LONG_BITS
== 32);
2187 * Store 32 bytes of [rd:rd+1] to ADDR.
2188 * See comments for GET_ASI_COPY above.
2191 MemOp mop
= MO_TE
| MO_128
| MO_ATOM_IFALIGN_PAIR
;
2192 TCGv_i64 t8
= tcg_temp_new_i64();
2193 TCGv_i128 t16
= tcg_temp_new_i128();
2194 TCGv daddr
= tcg_temp_new();
2196 tcg_gen_concat_tl_i64(t8
, lo
, hi
);
2197 tcg_gen_concat_i64_i128(t16
, t8
, t8
);
2198 tcg_gen_andi_tl(daddr
, addr
, -32);
2199 tcg_gen_qemu_st_i128(t16
, daddr
, da
->mem_idx
, mop
);
2200 tcg_gen_addi_tl(daddr
, daddr
, 16);
2201 tcg_gen_qemu_st_i128(t16
, daddr
, da
->mem_idx
, mop
);
2206 /* ??? In theory we've handled all of the ASIs that are valid
2207 for stda, and this should raise DAE_invalid_asi. */
2209 TCGv_i32 r_asi
= tcg_constant_i32(da
->asi
);
2210 TCGv_i32 r_mop
= tcg_constant_i32(da
->memop
);
2211 TCGv_i64 t64
= tcg_temp_new_i64();
2214 if ((da
->memop
& MO_BSWAP
) == MO_TE
) {
2215 tcg_gen_concat_tl_i64(t64
, lo
, hi
);
2217 tcg_gen_concat_tl_i64(t64
, hi
, lo
);
2221 gen_helper_st_asi(tcg_env
, addr
, t64
, r_asi
, r_mop
);
2227 static void gen_fmovs(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2229 #ifdef TARGET_SPARC64
2230 TCGv_i32 c32
, zero
, dst
, s1
, s2
;
2231 TCGv_i64 c64
= tcg_temp_new_i64();
2233 /* We have two choices here: extend the 32 bit data and use movcond_i64,
2234 or fold the comparison down to 32 bits and use movcond_i32. Choose
2236 c32
= tcg_temp_new_i32();
2237 tcg_gen_setcondi_i64(cmp
->cond
, c64
, cmp
->c1
, cmp
->c2
);
2238 tcg_gen_extrl_i64_i32(c32
, c64
);
2240 s1
= gen_load_fpr_F(dc
, rs
);
2241 s2
= gen_load_fpr_F(dc
, rd
);
2242 dst
= tcg_temp_new_i32();
2243 zero
= tcg_constant_i32(0);
2245 tcg_gen_movcond_i32(TCG_COND_NE
, dst
, c32
, zero
, s1
, s2
);
2247 gen_store_fpr_F(dc
, rd
, dst
);
2249 qemu_build_not_reached();
2253 static void gen_fmovd(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2255 #ifdef TARGET_SPARC64
2256 TCGv_i64 dst
= gen_dest_fpr_D(dc
, rd
);
2257 tcg_gen_movcond_i64(cmp
->cond
, dst
, cmp
->c1
, tcg_constant_tl(cmp
->c2
),
2258 gen_load_fpr_D(dc
, rs
),
2259 gen_load_fpr_D(dc
, rd
));
2260 gen_store_fpr_D(dc
, rd
, dst
);
2262 qemu_build_not_reached();
2266 static void gen_fmovq(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, int rs
)
2268 #ifdef TARGET_SPARC64
2269 int qd
= QFPREG(rd
);
2270 int qs
= QFPREG(rs
);
2271 TCGv c2
= tcg_constant_tl(cmp
->c2
);
2273 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2], cmp
->c1
, c2
,
2274 cpu_fpr
[qs
/ 2], cpu_fpr
[qd
/ 2]);
2275 tcg_gen_movcond_i64(cmp
->cond
, cpu_fpr
[qd
/ 2 + 1], cmp
->c1
, c2
,
2276 cpu_fpr
[qs
/ 2 + 1], cpu_fpr
[qd
/ 2 + 1]);
2278 gen_update_fprs_dirty(dc
, qd
);
2280 qemu_build_not_reached();
2284 #ifdef TARGET_SPARC64
2285 static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr
)
2287 TCGv_i32 r_tl
= tcg_temp_new_i32();
2289 /* load env->tl into r_tl */
2290 tcg_gen_ld_i32(r_tl
, tcg_env
, offsetof(CPUSPARCState
, tl
));
2292 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2293 tcg_gen_andi_i32(r_tl
, r_tl
, MAXTL_MASK
);
2295 /* calculate offset to current trap state from env->ts, reuse r_tl */
2296 tcg_gen_muli_i32(r_tl
, r_tl
, sizeof (trap_state
));
2297 tcg_gen_addi_ptr(r_tsptr
, tcg_env
, offsetof(CPUSPARCState
, ts
));
2299 /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2301 TCGv_ptr r_tl_tmp
= tcg_temp_new_ptr();
2302 tcg_gen_ext_i32_ptr(r_tl_tmp
, r_tl
);
2303 tcg_gen_add_ptr(r_tsptr
, r_tsptr
, r_tl_tmp
);
2308 static int extract_dfpreg(DisasContext
*dc
, int x
)
2313 static int extract_qfpreg(DisasContext
*dc
, int x
)
2318 /* Include the auto-generated decoder. */
2319 #include "decode-insns.c.inc"
2321 #define TRANS(NAME, AVAIL, FUNC, ...) \
2322 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2323 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2325 #define avail_ALL(C) true
2326 #ifdef TARGET_SPARC64
2327 # define avail_32(C) false
2328 # define avail_ASR17(C) false
2329 # define avail_CASA(C) true
2330 # define avail_DIV(C) true
2331 # define avail_MUL(C) true
2332 # define avail_POWERDOWN(C) false
2333 # define avail_64(C) true
2334 # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
2335 # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
2336 # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1)
2337 # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2)
2339 # define avail_32(C) true
2340 # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
2341 # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA)
2342 # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV)
2343 # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL)
2344 # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2345 # define avail_64(C) false
2346 # define avail_GL(C) false
2347 # define avail_HYPV(C) false
2348 # define avail_VIS1(C) false
2349 # define avail_VIS2(C) false
2352 /* Default case for non jump instructions. */
2353 static bool advance_pc(DisasContext
*dc
)
2362 case DYNAMIC_PC_LOOKUP
:
2364 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
2365 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
2369 /* we can do a static jump */
2370 l1
= gen_new_label();
2371 tcg_gen_brcondi_tl(dc
->jump
.cond
, dc
->jump
.c1
, dc
->jump
.c2
, l1
);
2373 /* jump not taken */
2374 gen_goto_tb(dc
, 1, dc
->jump_pc
[1], dc
->jump_pc
[1] + 4);
2378 gen_goto_tb(dc
, 0, dc
->jump_pc
[0], dc
->jump_pc
[0] + 4);
2380 dc
->base
.is_jmp
= DISAS_NORETURN
;
2384 g_assert_not_reached();
2388 dc
->npc
= dc
->npc
+ 4;
2394 * Major opcodes 00 and 01 -- branches, call, and sethi
2397 static bool advance_jump_cond(DisasContext
*dc
, DisasCompare
*cmp
,
2398 bool annul
, int disp
)
2400 target_ulong dest
= address_mask_i(dc
, dc
->pc
+ disp
* 4);
2405 if (cmp
->cond
== TCG_COND_ALWAYS
) {
2416 if (cmp
->cond
== TCG_COND_NEVER
) {
2421 tcg_gen_addi_tl(cpu_pc
, cpu_pc
, 4);
2423 tcg_gen_addi_tl(cpu_npc
, cpu_pc
, 4);
2425 dc
->pc
= npc
+ (annul
? 4 : 0);
2426 dc
->npc
= dc
->pc
+ 4;
2435 TCGLabel
*l1
= gen_new_label();
2437 tcg_gen_brcondi_tl(tcg_invert_cond(cmp
->cond
), cmp
->c1
, cmp
->c2
, l1
);
2438 gen_goto_tb(dc
, 0, npc
, dest
);
2440 gen_goto_tb(dc
, 1, npc
+ 4, npc
+ 8);
2442 dc
->base
.is_jmp
= DISAS_NORETURN
;
2447 case DYNAMIC_PC_LOOKUP
:
2448 tcg_gen_mov_tl(cpu_pc
, cpu_npc
);
2449 tcg_gen_addi_tl(cpu_npc
, cpu_npc
, 4);
2450 tcg_gen_movcond_tl(cmp
->cond
, cpu_npc
,
2451 cmp
->c1
, tcg_constant_tl(cmp
->c2
),
2452 tcg_constant_tl(dest
), cpu_npc
);
2456 g_assert_not_reached();
2462 dc
->jump_pc
[0] = dest
;
2463 dc
->jump_pc
[1] = npc
+ 4;
2465 /* The condition for cpu_cond is always NE -- normalize. */
2466 if (cmp
->cond
== TCG_COND_NE
) {
2467 tcg_gen_xori_tl(cpu_cond
, cmp
->c1
, cmp
->c2
);
2469 tcg_gen_setcondi_tl(cmp
->cond
, cpu_cond
, cmp
->c1
, cmp
->c2
);
2471 dc
->cpu_cond_live
= true;
2477 static bool raise_priv(DisasContext
*dc
)
2479 gen_exception(dc
, TT_PRIV_INSN
);
2483 static bool raise_unimpfpop(DisasContext
*dc
)
2485 gen_op_fpexception_im(dc
, FSR_FTT_UNIMPFPOP
);
2489 static bool gen_trap_float128(DisasContext
*dc
)
2491 if (dc
->def
->features
& CPU_FEATURE_FLOAT128
) {
2494 return raise_unimpfpop(dc
);
2497 static bool do_bpcc(DisasContext
*dc
, arg_bcc
*a
)
2501 gen_compare(&cmp
, a
->cc
, a
->cond
, dc
);
2502 return advance_jump_cond(dc
, &cmp
, a
->a
, a
->i
);
2505 TRANS(Bicc
, ALL
, do_bpcc
, a
)
2506 TRANS(BPcc
, 64, do_bpcc
, a
)
2508 static bool do_fbpfcc(DisasContext
*dc
, arg_bcc
*a
)
2512 if (gen_trap_ifnofpu(dc
)) {
2515 gen_fcompare(&cmp
, a
->cc
, a
->cond
);
2516 return advance_jump_cond(dc
, &cmp
, a
->a
, a
->i
);
2519 TRANS(FBPfcc
, 64, do_fbpfcc
, a
)
2520 TRANS(FBfcc
, ALL
, do_fbpfcc
, a
)
2522 static bool trans_BPr(DisasContext
*dc
, arg_BPr
*a
)
2526 if (!avail_64(dc
)) {
2529 if (!gen_compare_reg(&cmp
, a
->cond
, gen_load_gpr(dc
, a
->rs1
))) {
2532 return advance_jump_cond(dc
, &cmp
, a
->a
, a
->i
);
2535 static bool trans_CALL(DisasContext
*dc
, arg_CALL
*a
)
2537 target_long target
= address_mask_i(dc
, dc
->pc
+ a
->i
* 4);
2539 gen_store_gpr(dc
, 15, tcg_constant_tl(dc
->pc
));
2545 static bool trans_NCP(DisasContext
*dc
, arg_NCP
*a
)
2548 * For sparc32, always generate the no-coprocessor exception.
2549 * For sparc64, always generate illegal instruction.
2551 #ifdef TARGET_SPARC64
2554 gen_exception(dc
, TT_NCP_INSN
);
2559 static bool trans_SETHI(DisasContext
*dc
, arg_SETHI
*a
)
2561 /* Special-case %g0 because that's the canonical nop. */
2563 gen_store_gpr(dc
, a
->rd
, tcg_constant_tl((uint32_t)a
->i
<< 10));
2565 return advance_pc(dc
);
2569 * Major Opcode 10 -- integer, floating-point, vis, and system insns.
2572 static bool do_tcc(DisasContext
*dc
, int cond
, int cc
,
2573 int rs1
, bool imm
, int rs2_or_imm
)
2575 int mask
= ((dc
->def
->features
& CPU_FEATURE_HYPV
) && supervisor(dc
)
2576 ? UA2005_HTRAP_MASK
: V8_TRAP_MASK
);
2583 return advance_pc(dc
);
2587 * Immediate traps are the most common case. Since this value is
2588 * live across the branch, it really pays to evaluate the constant.
2590 if (rs1
== 0 && (imm
|| rs2_or_imm
== 0)) {
2591 trap
= tcg_constant_i32((rs2_or_imm
& mask
) + TT_TRAP
);
2593 trap
= tcg_temp_new_i32();
2594 tcg_gen_trunc_tl_i32(trap
, gen_load_gpr(dc
, rs1
));
2596 tcg_gen_addi_i32(trap
, trap
, rs2_or_imm
);
2598 TCGv_i32 t2
= tcg_temp_new_i32();
2599 tcg_gen_trunc_tl_i32(t2
, gen_load_gpr(dc
, rs2_or_imm
));
2600 tcg_gen_add_i32(trap
, trap
, t2
);
2602 tcg_gen_andi_i32(trap
, trap
, mask
);
2603 tcg_gen_addi_i32(trap
, trap
, TT_TRAP
);
2611 gen_helper_raise_exception(tcg_env
, trap
);
2612 dc
->base
.is_jmp
= DISAS_NORETURN
;
2616 /* Conditional trap. */
2618 lab
= delay_exceptionv(dc
, trap
);
2619 gen_compare(&cmp
, cc
, cond
, dc
);
2620 tcg_gen_brcondi_tl(cmp
.cond
, cmp
.c1
, cmp
.c2
, lab
);
2622 return advance_pc(dc
);
2625 static bool trans_Tcc_r(DisasContext
*dc
, arg_Tcc_r
*a
)
2627 if (avail_32(dc
) && a
->cc
) {
2630 return do_tcc(dc
, a
->cond
, a
->cc
, a
->rs1
, false, a
->rs2
);
2633 static bool trans_Tcc_i_v7(DisasContext
*dc
, arg_Tcc_i_v7
*a
)
2638 return do_tcc(dc
, a
->cond
, 0, a
->rs1
, true, a
->i
);
2641 static bool trans_Tcc_i_v9(DisasContext
*dc
, arg_Tcc_i_v9
*a
)
2646 return do_tcc(dc
, a
->cond
, a
->cc
, a
->rs1
, true, a
->i
);
2649 static bool trans_STBAR(DisasContext
*dc
, arg_STBAR
*a
)
2651 tcg_gen_mb(TCG_MO_ST_ST
| TCG_BAR_SC
);
2652 return advance_pc(dc
);
2655 static bool trans_MEMBAR(DisasContext
*dc
, arg_MEMBAR
*a
)
2661 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2662 tcg_gen_mb(a
->mmask
| TCG_BAR_SC
);
2665 /* For #Sync, etc, end the TB to recognize interrupts. */
2666 dc
->base
.is_jmp
= DISAS_EXIT
;
2668 return advance_pc(dc
);
2671 static bool do_rd_special(DisasContext
*dc
, bool priv
, int rd
,
2672 TCGv (*func
)(DisasContext
*, TCGv
))
2675 return raise_priv(dc
);
2677 gen_store_gpr(dc
, rd
, func(dc
, gen_dest_gpr(dc
, rd
)));
2678 return advance_pc(dc
);
2681 static TCGv
do_rdy(DisasContext
*dc
, TCGv dst
)
2686 static bool trans_RDY(DisasContext
*dc
, arg_RDY
*a
)
2689 * TODO: Need a feature bit for sparcv8. In the meantime, treat all
2690 * 32-bit cpus like sparcv7, which ignores the rs1 field.
2691 * This matches after all other ASR, so Leon3 Asr17 is handled first.
2693 if (avail_64(dc
) && a
->rs1
!= 0) {
2696 return do_rd_special(dc
, true, a
->rd
, do_rdy
);
2699 static TCGv
do_rd_leon3_config(DisasContext
*dc
, TCGv dst
)
2704 * TODO: There are many more fields to be filled,
2705 * some of which are writable.
2707 val
= dc
->def
->nwindows
- 1; /* [4:0] NWIN */
2708 val
|= 1 << 8; /* [8] V8 */
2710 return tcg_constant_tl(val
);
2713 TRANS(RDASR17
, ASR17
, do_rd_special
, true, a
->rd
, do_rd_leon3_config
)
2715 static TCGv
do_rdccr(DisasContext
*dc
, TCGv dst
)
2717 gen_helper_rdccr(dst
, tcg_env
);
2721 TRANS(RDCCR
, 64, do_rd_special
, true, a
->rd
, do_rdccr
)
2723 static TCGv
do_rdasi(DisasContext
*dc
, TCGv dst
)
2725 #ifdef TARGET_SPARC64
2726 return tcg_constant_tl(dc
->asi
);
2728 qemu_build_not_reached();
2732 TRANS(RDASI
, 64, do_rd_special
, true, a
->rd
, do_rdasi
)
2734 static TCGv
do_rdtick(DisasContext
*dc
, TCGv dst
)
2736 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
2738 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(tick
));
2739 if (translator_io_start(&dc
->base
)) {
2740 dc
->base
.is_jmp
= DISAS_EXIT
;
2742 gen_helper_tick_get_count(dst
, tcg_env
, r_tickptr
,
2743 tcg_constant_i32(dc
->mem_idx
));
2747 /* TODO: non-priv access only allowed when enabled. */
2748 TRANS(RDTICK
, 64, do_rd_special
, true, a
->rd
, do_rdtick
)
2750 static TCGv
do_rdpc(DisasContext
*dc
, TCGv dst
)
2752 return tcg_constant_tl(address_mask_i(dc
, dc
->pc
));
2755 TRANS(RDPC
, 64, do_rd_special
, true, a
->rd
, do_rdpc
)
2757 static TCGv
do_rdfprs(DisasContext
*dc
, TCGv dst
)
2759 tcg_gen_ext_i32_tl(dst
, cpu_fprs
);
2763 TRANS(RDFPRS
, 64, do_rd_special
, true, a
->rd
, do_rdfprs
)
2765 static TCGv
do_rdgsr(DisasContext
*dc
, TCGv dst
)
2767 gen_trap_ifnofpu(dc
);
2771 TRANS(RDGSR
, 64, do_rd_special
, true, a
->rd
, do_rdgsr
)
2773 static TCGv
do_rdsoftint(DisasContext
*dc
, TCGv dst
)
2775 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(softint
));
2779 TRANS(RDSOFTINT
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdsoftint
)
2781 static TCGv
do_rdtick_cmpr(DisasContext
*dc
, TCGv dst
)
2783 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(tick_cmpr
));
2787 /* TODO: non-priv access only allowed when enabled. */
2788 TRANS(RDTICK_CMPR
, 64, do_rd_special
, true, a
->rd
, do_rdtick_cmpr
)
2790 static TCGv
do_rdstick(DisasContext
*dc
, TCGv dst
)
2792 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
2794 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(stick
));
2795 if (translator_io_start(&dc
->base
)) {
2796 dc
->base
.is_jmp
= DISAS_EXIT
;
2798 gen_helper_tick_get_count(dst
, tcg_env
, r_tickptr
,
2799 tcg_constant_i32(dc
->mem_idx
));
2803 /* TODO: non-priv access only allowed when enabled. */
2804 TRANS(RDSTICK
, 64, do_rd_special
, true, a
->rd
, do_rdstick
)
2806 static TCGv
do_rdstick_cmpr(DisasContext
*dc
, TCGv dst
)
2808 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(stick_cmpr
));
2812 /* TODO: supervisor access only allowed when enabled by hypervisor. */
2813 TRANS(RDSTICK_CMPR
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdstick_cmpr
)
2816 * UltraSPARC-T1 Strand status.
2817 * HYPV check maybe not enough, UA2005 & UA2007 describe
2818 * this ASR as impl. dep
2820 static TCGv
do_rdstrand_status(DisasContext
*dc
, TCGv dst
)
2822 return tcg_constant_tl(1);
2825 TRANS(RDSTRAND_STATUS
, HYPV
, do_rd_special
, true, a
->rd
, do_rdstrand_status
)
2827 static TCGv
do_rdpsr(DisasContext
*dc
, TCGv dst
)
2829 gen_helper_rdpsr(dst
, tcg_env
);
2833 TRANS(RDPSR
, 32, do_rd_special
, supervisor(dc
), a
->rd
, do_rdpsr
)
2835 static TCGv
do_rdhpstate(DisasContext
*dc
, TCGv dst
)
2837 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(hpstate
));
2841 TRANS(RDHPR_hpstate
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdhpstate
)
2843 static TCGv
do_rdhtstate(DisasContext
*dc
, TCGv dst
)
2845 TCGv_i32 tl
= tcg_temp_new_i32();
2846 TCGv_ptr tp
= tcg_temp_new_ptr();
2848 tcg_gen_ld_i32(tl
, tcg_env
, env64_field_offsetof(tl
));
2849 tcg_gen_andi_i32(tl
, tl
, MAXTL_MASK
);
2850 tcg_gen_shli_i32(tl
, tl
, 3);
2851 tcg_gen_ext_i32_ptr(tp
, tl
);
2852 tcg_gen_add_ptr(tp
, tp
, tcg_env
);
2854 tcg_gen_ld_tl(dst
, tp
, env64_field_offsetof(htstate
));
2858 TRANS(RDHPR_htstate
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdhtstate
)
2860 static TCGv
do_rdhintp(DisasContext
*dc
, TCGv dst
)
2862 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(hintp
));
2866 TRANS(RDHPR_hintp
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdhintp
)
2868 static TCGv
do_rdhtba(DisasContext
*dc
, TCGv dst
)
2870 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(htba
));
2874 TRANS(RDHPR_htba
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdhtba
)
2876 static TCGv
do_rdhver(DisasContext
*dc
, TCGv dst
)
2878 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(hver
));
2882 TRANS(RDHPR_hver
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdhver
)
2884 static TCGv
do_rdhstick_cmpr(DisasContext
*dc
, TCGv dst
)
2886 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(hstick_cmpr
));
2890 TRANS(RDHPR_hstick_cmpr
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
,
2893 static TCGv
do_rdwim(DisasContext
*dc
, TCGv dst
)
2895 tcg_gen_ld_tl(dst
, tcg_env
, env32_field_offsetof(wim
));
2899 TRANS(RDWIM
, 32, do_rd_special
, supervisor(dc
), a
->rd
, do_rdwim
)
2901 static TCGv
do_rdtpc(DisasContext
*dc
, TCGv dst
)
2903 #ifdef TARGET_SPARC64
2904 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
2906 gen_load_trap_state_at_tl(r_tsptr
);
2907 tcg_gen_ld_tl(dst
, r_tsptr
, offsetof(trap_state
, tpc
));
2910 qemu_build_not_reached();
2914 TRANS(RDPR_tpc
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtpc
)
2916 static TCGv
do_rdtnpc(DisasContext
*dc
, TCGv dst
)
2918 #ifdef TARGET_SPARC64
2919 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
2921 gen_load_trap_state_at_tl(r_tsptr
);
2922 tcg_gen_ld_tl(dst
, r_tsptr
, offsetof(trap_state
, tnpc
));
2925 qemu_build_not_reached();
2929 TRANS(RDPR_tnpc
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtnpc
)
2931 static TCGv
do_rdtstate(DisasContext
*dc
, TCGv dst
)
2933 #ifdef TARGET_SPARC64
2934 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
2936 gen_load_trap_state_at_tl(r_tsptr
);
2937 tcg_gen_ld_tl(dst
, r_tsptr
, offsetof(trap_state
, tstate
));
2940 qemu_build_not_reached();
2944 TRANS(RDPR_tstate
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtstate
)
2946 static TCGv
do_rdtt(DisasContext
*dc
, TCGv dst
)
2948 #ifdef TARGET_SPARC64
2949 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
2951 gen_load_trap_state_at_tl(r_tsptr
);
2952 tcg_gen_ld32s_tl(dst
, r_tsptr
, offsetof(trap_state
, tt
));
2955 qemu_build_not_reached();
2959 TRANS(RDPR_tt
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtt
)
2960 TRANS(RDPR_tick
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtick
)
2962 static TCGv
do_rdtba(DisasContext
*dc
, TCGv dst
)
2967 TRANS(RDTBR
, 32, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtba
)
2968 TRANS(RDPR_tba
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtba
)
2970 static TCGv
do_rdpstate(DisasContext
*dc
, TCGv dst
)
2972 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(pstate
));
2976 TRANS(RDPR_pstate
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdpstate
)
2978 static TCGv
do_rdtl(DisasContext
*dc
, TCGv dst
)
2980 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(tl
));
2984 TRANS(RDPR_tl
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdtl
)
2986 static TCGv
do_rdpil(DisasContext
*dc
, TCGv dst
)
2988 tcg_gen_ld32s_tl(dst
, tcg_env
, env_field_offsetof(psrpil
));
2992 TRANS(RDPR_pil
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdpil
)
2994 static TCGv
do_rdcwp(DisasContext
*dc
, TCGv dst
)
2996 gen_helper_rdcwp(dst
, tcg_env
);
3000 TRANS(RDPR_cwp
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdcwp
)
3002 static TCGv
do_rdcansave(DisasContext
*dc
, TCGv dst
)
3004 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(cansave
));
3008 TRANS(RDPR_cansave
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdcansave
)
3010 static TCGv
do_rdcanrestore(DisasContext
*dc
, TCGv dst
)
3012 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(canrestore
));
3016 TRANS(RDPR_canrestore
, 64, do_rd_special
, supervisor(dc
), a
->rd
,
3019 static TCGv
do_rdcleanwin(DisasContext
*dc
, TCGv dst
)
3021 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(cleanwin
));
3025 TRANS(RDPR_cleanwin
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdcleanwin
)
3027 static TCGv
do_rdotherwin(DisasContext
*dc
, TCGv dst
)
3029 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(otherwin
));
3033 TRANS(RDPR_otherwin
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdotherwin
)
3035 static TCGv
do_rdwstate(DisasContext
*dc
, TCGv dst
)
3037 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(wstate
));
3041 TRANS(RDPR_wstate
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdwstate
)
3043 static TCGv
do_rdgl(DisasContext
*dc
, TCGv dst
)
3045 tcg_gen_ld32s_tl(dst
, tcg_env
, env64_field_offsetof(gl
));
3049 TRANS(RDPR_gl
, GL
, do_rd_special
, supervisor(dc
), a
->rd
, do_rdgl
)
3051 /* UA2005 strand status */
3052 static TCGv
do_rdssr(DisasContext
*dc
, TCGv dst
)
3054 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(ssr
));
3058 TRANS(RDPR_strand_status
, HYPV
, do_rd_special
, hypervisor(dc
), a
->rd
, do_rdssr
)
3060 static TCGv
do_rdver(DisasContext
*dc
, TCGv dst
)
3062 tcg_gen_ld_tl(dst
, tcg_env
, env64_field_offsetof(version
));
3066 TRANS(RDPR_ver
, 64, do_rd_special
, supervisor(dc
), a
->rd
, do_rdver
)
3068 static bool trans_FLUSHW(DisasContext
*dc
, arg_FLUSHW
*a
)
3071 gen_helper_flushw(tcg_env
);
3072 return advance_pc(dc
);
3077 static bool do_wr_special(DisasContext
*dc
, arg_r_r_ri
*a
, bool priv
,
3078 void (*func
)(DisasContext
*, TCGv
))
3082 /* For simplicity, we under-decoded the rs2 form. */
3083 if (!a
->imm
&& (a
->rs2_or_imm
& ~0x1f)) {
3087 return raise_priv(dc
);
3090 if (a
->rs1
== 0 && (a
->imm
|| a
->rs2_or_imm
== 0)) {
3091 src
= tcg_constant_tl(a
->rs2_or_imm
);
3093 TCGv src1
= gen_load_gpr(dc
, a
->rs1
);
3094 if (a
->rs2_or_imm
== 0) {
3097 src
= tcg_temp_new();
3099 tcg_gen_xori_tl(src
, src1
, a
->rs2_or_imm
);
3101 tcg_gen_xor_tl(src
, src1
, gen_load_gpr(dc
, a
->rs2_or_imm
));
3106 return advance_pc(dc
);
3109 static void do_wry(DisasContext
*dc
, TCGv src
)
3111 tcg_gen_ext32u_tl(cpu_y
, src
);
3114 TRANS(WRY
, ALL
, do_wr_special
, a
, true, do_wry
)
3116 static void do_wrccr(DisasContext
*dc
, TCGv src
)
3118 gen_helper_wrccr(tcg_env
, src
);
3121 TRANS(WRCCR
, 64, do_wr_special
, a
, true, do_wrccr
)
3123 static void do_wrasi(DisasContext
*dc
, TCGv src
)
3125 TCGv tmp
= tcg_temp_new();
3127 tcg_gen_ext8u_tl(tmp
, src
);
3128 tcg_gen_st32_tl(tmp
, tcg_env
, env64_field_offsetof(asi
));
3129 /* End TB to notice changed ASI. */
3130 dc
->base
.is_jmp
= DISAS_EXIT
;
3133 TRANS(WRASI
, 64, do_wr_special
, a
, true, do_wrasi
)
3135 static void do_wrfprs(DisasContext
*dc
, TCGv src
)
3137 #ifdef TARGET_SPARC64
3138 tcg_gen_trunc_tl_i32(cpu_fprs
, src
);
3140 dc
->base
.is_jmp
= DISAS_EXIT
;
3142 qemu_build_not_reached();
3146 TRANS(WRFPRS
, 64, do_wr_special
, a
, true, do_wrfprs
)
3148 static void do_wrgsr(DisasContext
*dc
, TCGv src
)
3150 gen_trap_ifnofpu(dc
);
3151 tcg_gen_mov_tl(cpu_gsr
, src
);
3154 TRANS(WRGSR
, 64, do_wr_special
, a
, true, do_wrgsr
)
3156 static void do_wrsoftint_set(DisasContext
*dc
, TCGv src
)
3158 gen_helper_set_softint(tcg_env
, src
);
3161 TRANS(WRSOFTINT_SET
, 64, do_wr_special
, a
, supervisor(dc
), do_wrsoftint_set
)
3163 static void do_wrsoftint_clr(DisasContext
*dc
, TCGv src
)
3165 gen_helper_clear_softint(tcg_env
, src
);
3168 TRANS(WRSOFTINT_CLR
, 64, do_wr_special
, a
, supervisor(dc
), do_wrsoftint_clr
)
3170 static void do_wrsoftint(DisasContext
*dc
, TCGv src
)
3172 gen_helper_write_softint(tcg_env
, src
);
3175 TRANS(WRSOFTINT
, 64, do_wr_special
, a
, supervisor(dc
), do_wrsoftint
)
3177 static void do_wrtick_cmpr(DisasContext
*dc
, TCGv src
)
3179 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
3181 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(tick_cmpr
));
3182 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(tick
));
3183 translator_io_start(&dc
->base
);
3184 gen_helper_tick_set_limit(r_tickptr
, src
);
3185 /* End TB to handle timer interrupt */
3186 dc
->base
.is_jmp
= DISAS_EXIT
;
3189 TRANS(WRTICK_CMPR
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtick_cmpr
)
3191 static void do_wrstick(DisasContext
*dc
, TCGv src
)
3193 #ifdef TARGET_SPARC64
3194 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
3196 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, offsetof(CPUSPARCState
, stick
));
3197 translator_io_start(&dc
->base
);
3198 gen_helper_tick_set_count(r_tickptr
, src
);
3199 /* End TB to handle timer interrupt */
3200 dc
->base
.is_jmp
= DISAS_EXIT
;
3202 qemu_build_not_reached();
3206 TRANS(WRSTICK
, 64, do_wr_special
, a
, supervisor(dc
), do_wrstick
)
3208 static void do_wrstick_cmpr(DisasContext
*dc
, TCGv src
)
3210 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
3212 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(stick_cmpr
));
3213 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(stick
));
3214 translator_io_start(&dc
->base
);
3215 gen_helper_tick_set_limit(r_tickptr
, src
);
3216 /* End TB to handle timer interrupt */
3217 dc
->base
.is_jmp
= DISAS_EXIT
;
3220 TRANS(WRSTICK_CMPR
, 64, do_wr_special
, a
, supervisor(dc
), do_wrstick_cmpr
)
3222 static void do_wrpowerdown(DisasContext
*dc
, TCGv src
)
3226 gen_helper_power_down(tcg_env
);
3229 TRANS(WRPOWERDOWN
, POWERDOWN
, do_wr_special
, a
, supervisor(dc
), do_wrpowerdown
)
3231 static void do_wrpsr(DisasContext
*dc
, TCGv src
)
3233 gen_helper_wrpsr(tcg_env
, src
);
3234 dc
->base
.is_jmp
= DISAS_EXIT
;
3237 TRANS(WRPSR
, 32, do_wr_special
, a
, supervisor(dc
), do_wrpsr
)
3239 static void do_wrwim(DisasContext
*dc
, TCGv src
)
3241 target_ulong mask
= MAKE_64BIT_MASK(0, dc
->def
->nwindows
);
3242 TCGv tmp
= tcg_temp_new();
3244 tcg_gen_andi_tl(tmp
, src
, mask
);
3245 tcg_gen_st_tl(tmp
, tcg_env
, env32_field_offsetof(wim
));
3248 TRANS(WRWIM
, 32, do_wr_special
, a
, supervisor(dc
), do_wrwim
)
3250 static void do_wrtpc(DisasContext
*dc
, TCGv src
)
3252 #ifdef TARGET_SPARC64
3253 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3255 gen_load_trap_state_at_tl(r_tsptr
);
3256 tcg_gen_st_tl(src
, r_tsptr
, offsetof(trap_state
, tpc
));
3258 qemu_build_not_reached();
3262 TRANS(WRPR_tpc
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtpc
)
3264 static void do_wrtnpc(DisasContext
*dc
, TCGv src
)
3266 #ifdef TARGET_SPARC64
3267 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3269 gen_load_trap_state_at_tl(r_tsptr
);
3270 tcg_gen_st_tl(src
, r_tsptr
, offsetof(trap_state
, tnpc
));
3272 qemu_build_not_reached();
3276 TRANS(WRPR_tnpc
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtnpc
)
3278 static void do_wrtstate(DisasContext
*dc
, TCGv src
)
3280 #ifdef TARGET_SPARC64
3281 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3283 gen_load_trap_state_at_tl(r_tsptr
);
3284 tcg_gen_st_tl(src
, r_tsptr
, offsetof(trap_state
, tstate
));
3286 qemu_build_not_reached();
3290 TRANS(WRPR_tstate
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtstate
)
3292 static void do_wrtt(DisasContext
*dc
, TCGv src
)
3294 #ifdef TARGET_SPARC64
3295 TCGv_ptr r_tsptr
= tcg_temp_new_ptr();
3297 gen_load_trap_state_at_tl(r_tsptr
);
3298 tcg_gen_st32_tl(src
, r_tsptr
, offsetof(trap_state
, tt
));
3300 qemu_build_not_reached();
3304 TRANS(WRPR_tt
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtt
)
3306 static void do_wrtick(DisasContext
*dc
, TCGv src
)
3308 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
3310 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(tick
));
3311 translator_io_start(&dc
->base
);
3312 gen_helper_tick_set_count(r_tickptr
, src
);
3313 /* End TB to handle timer interrupt */
3314 dc
->base
.is_jmp
= DISAS_EXIT
;
3317 TRANS(WRPR_tick
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtick
)
3319 static void do_wrtba(DisasContext
*dc
, TCGv src
)
3321 tcg_gen_mov_tl(cpu_tbr
, src
);
3324 TRANS(WRPR_tba
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtba
)
3326 static void do_wrpstate(DisasContext
*dc
, TCGv src
)
3329 if (translator_io_start(&dc
->base
)) {
3330 dc
->base
.is_jmp
= DISAS_EXIT
;
3332 gen_helper_wrpstate(tcg_env
, src
);
3333 dc
->npc
= DYNAMIC_PC
;
3336 TRANS(WRPR_pstate
, 64, do_wr_special
, a
, supervisor(dc
), do_wrpstate
)
3338 static void do_wrtl(DisasContext
*dc
, TCGv src
)
3341 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(tl
));
3342 dc
->npc
= DYNAMIC_PC
;
3345 TRANS(WRPR_tl
, 64, do_wr_special
, a
, supervisor(dc
), do_wrtl
)
3347 static void do_wrpil(DisasContext
*dc
, TCGv src
)
3349 if (translator_io_start(&dc
->base
)) {
3350 dc
->base
.is_jmp
= DISAS_EXIT
;
3352 gen_helper_wrpil(tcg_env
, src
);
3355 TRANS(WRPR_pil
, 64, do_wr_special
, a
, supervisor(dc
), do_wrpil
)
3357 static void do_wrcwp(DisasContext
*dc
, TCGv src
)
3359 gen_helper_wrcwp(tcg_env
, src
);
3362 TRANS(WRPR_cwp
, 64, do_wr_special
, a
, supervisor(dc
), do_wrcwp
)
3364 static void do_wrcansave(DisasContext
*dc
, TCGv src
)
3366 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(cansave
));
3369 TRANS(WRPR_cansave
, 64, do_wr_special
, a
, supervisor(dc
), do_wrcansave
)
3371 static void do_wrcanrestore(DisasContext
*dc
, TCGv src
)
3373 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(canrestore
));
3376 TRANS(WRPR_canrestore
, 64, do_wr_special
, a
, supervisor(dc
), do_wrcanrestore
)
3378 static void do_wrcleanwin(DisasContext
*dc
, TCGv src
)
3380 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(cleanwin
));
3383 TRANS(WRPR_cleanwin
, 64, do_wr_special
, a
, supervisor(dc
), do_wrcleanwin
)
3385 static void do_wrotherwin(DisasContext
*dc
, TCGv src
)
3387 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(otherwin
));
3390 TRANS(WRPR_otherwin
, 64, do_wr_special
, a
, supervisor(dc
), do_wrotherwin
)
3392 static void do_wrwstate(DisasContext
*dc
, TCGv src
)
3394 tcg_gen_st32_tl(src
, tcg_env
, env64_field_offsetof(wstate
));
3397 TRANS(WRPR_wstate
, 64, do_wr_special
, a
, supervisor(dc
), do_wrwstate
)
3399 static void do_wrgl(DisasContext
*dc
, TCGv src
)
3401 gen_helper_wrgl(tcg_env
, src
);
3404 TRANS(WRPR_gl
, GL
, do_wr_special
, a
, supervisor(dc
), do_wrgl
)
3406 /* UA2005 strand status */
3407 static void do_wrssr(DisasContext
*dc
, TCGv src
)
3409 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(ssr
));
3412 TRANS(WRPR_strand_status
, HYPV
, do_wr_special
, a
, hypervisor(dc
), do_wrssr
)
3414 TRANS(WRTBR
, 32, do_wr_special
, a
, supervisor(dc
), do_wrtba
)
3416 static void do_wrhpstate(DisasContext
*dc
, TCGv src
)
3418 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(hpstate
));
3419 dc
->base
.is_jmp
= DISAS_EXIT
;
3422 TRANS(WRHPR_hpstate
, HYPV
, do_wr_special
, a
, hypervisor(dc
), do_wrhpstate
)
3424 static void do_wrhtstate(DisasContext
*dc
, TCGv src
)
3426 TCGv_i32 tl
= tcg_temp_new_i32();
3427 TCGv_ptr tp
= tcg_temp_new_ptr();
3429 tcg_gen_ld_i32(tl
, tcg_env
, env64_field_offsetof(tl
));
3430 tcg_gen_andi_i32(tl
, tl
, MAXTL_MASK
);
3431 tcg_gen_shli_i32(tl
, tl
, 3);
3432 tcg_gen_ext_i32_ptr(tp
, tl
);
3433 tcg_gen_add_ptr(tp
, tp
, tcg_env
);
3435 tcg_gen_st_tl(src
, tp
, env64_field_offsetof(htstate
));
3438 TRANS(WRHPR_htstate
, HYPV
, do_wr_special
, a
, hypervisor(dc
), do_wrhtstate
)
3440 static void do_wrhintp(DisasContext
*dc
, TCGv src
)
3442 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(hintp
));
3445 TRANS(WRHPR_hintp
, HYPV
, do_wr_special
, a
, hypervisor(dc
), do_wrhintp
)
3447 static void do_wrhtba(DisasContext
*dc
, TCGv src
)
3449 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(htba
));
3452 TRANS(WRHPR_htba
, HYPV
, do_wr_special
, a
, hypervisor(dc
), do_wrhtba
)
3454 static void do_wrhstick_cmpr(DisasContext
*dc
, TCGv src
)
3456 TCGv_ptr r_tickptr
= tcg_temp_new_ptr();
3458 tcg_gen_st_tl(src
, tcg_env
, env64_field_offsetof(hstick_cmpr
));
3459 tcg_gen_ld_ptr(r_tickptr
, tcg_env
, env64_field_offsetof(hstick
));
3460 translator_io_start(&dc
->base
);
3461 gen_helper_tick_set_limit(r_tickptr
, src
);
3462 /* End TB to handle timer interrupt */
3463 dc
->base
.is_jmp
= DISAS_EXIT
;
3466 TRANS(WRHPR_hstick_cmpr
, HYPV
, do_wr_special
, a
, hypervisor(dc
),
3469 static bool do_saved_restored(DisasContext
*dc
, bool saved
)
3471 if (!supervisor(dc
)) {
3472 return raise_priv(dc
);
3475 gen_helper_saved(tcg_env
);
3477 gen_helper_restored(tcg_env
);
3479 return advance_pc(dc
);
3482 TRANS(SAVED
, 64, do_saved_restored
, true)
3483 TRANS(RESTORED
, 64, do_saved_restored
, false)
3485 static bool trans_NOP(DisasContext
*dc
, arg_NOP
*a
)
3487 return advance_pc(dc
);
3491 * TODO: Need a feature bit for sparcv8.
3492 * In the meantime, treat all 32-bit cpus like sparcv7.
3494 TRANS(NOP_v7
, 32, trans_NOP
, a
)
3495 TRANS(NOP_v9
, 64, trans_NOP
, a
)
3497 static bool do_arith_int(DisasContext
*dc
, arg_r_r_ri_cc
*a
,
3498 void (*func
)(TCGv
, TCGv
, TCGv
),
3499 void (*funci
)(TCGv
, TCGv
, target_long
),
3504 /* For simplicity, we under-decoded the rs2 form. */
3505 if (!a
->imm
&& a
->rs2_or_imm
& ~0x1f) {
3512 dst
= gen_dest_gpr(dc
, a
->rd
);
3514 src1
= gen_load_gpr(dc
, a
->rs1
);
3516 if (a
->imm
|| a
->rs2_or_imm
== 0) {
3518 funci(dst
, src1
, a
->rs2_or_imm
);
3520 func(dst
, src1
, tcg_constant_tl(a
->rs2_or_imm
));
3523 func(dst
, src1
, cpu_regs
[a
->rs2_or_imm
]);
3527 if (TARGET_LONG_BITS
== 64) {
3528 tcg_gen_mov_tl(cpu_icc_Z
, cpu_cc_N
);
3529 tcg_gen_movi_tl(cpu_icc_C
, 0);
3531 tcg_gen_mov_tl(cpu_cc_Z
, cpu_cc_N
);
3532 tcg_gen_movi_tl(cpu_cc_C
, 0);
3533 tcg_gen_movi_tl(cpu_cc_V
, 0);
3536 gen_store_gpr(dc
, a
->rd
, dst
);
3537 return advance_pc(dc
);
3540 static bool do_arith(DisasContext
*dc
, arg_r_r_ri_cc
*a
,
3541 void (*func
)(TCGv
, TCGv
, TCGv
),
3542 void (*funci
)(TCGv
, TCGv
, target_long
),
3543 void (*func_cc
)(TCGv
, TCGv
, TCGv
))
3546 return do_arith_int(dc
, a
, func_cc
, NULL
, false);
3548 return do_arith_int(dc
, a
, func
, funci
, false);
3551 static bool do_logic(DisasContext
*dc
, arg_r_r_ri_cc
*a
,
3552 void (*func
)(TCGv
, TCGv
, TCGv
),
3553 void (*funci
)(TCGv
, TCGv
, target_long
))
3555 return do_arith_int(dc
, a
, func
, funci
, a
->cc
);
3558 TRANS(ADD
, ALL
, do_arith
, a
, tcg_gen_add_tl
, tcg_gen_addi_tl
, gen_op_addcc
)
3559 TRANS(SUB
, ALL
, do_arith
, a
, tcg_gen_sub_tl
, tcg_gen_subi_tl
, gen_op_subcc
)
3560 TRANS(ADDC
, ALL
, do_arith
, a
, gen_op_addc
, NULL
, gen_op_addccc
)
3561 TRANS(SUBC
, ALL
, do_arith
, a
, gen_op_subc
, NULL
, gen_op_subccc
)
3563 TRANS(TADDcc
, ALL
, do_arith
, a
, NULL
, NULL
, gen_op_taddcc
)
3564 TRANS(TSUBcc
, ALL
, do_arith
, a
, NULL
, NULL
, gen_op_tsubcc
)
3565 TRANS(TADDccTV
, ALL
, do_arith
, a
, NULL
, NULL
, gen_op_taddcctv
)
3566 TRANS(TSUBccTV
, ALL
, do_arith
, a
, NULL
, NULL
, gen_op_tsubcctv
)
3568 TRANS(AND
, ALL
, do_logic
, a
, tcg_gen_and_tl
, tcg_gen_andi_tl
)
3569 TRANS(XOR
, ALL
, do_logic
, a
, tcg_gen_xor_tl
, tcg_gen_xori_tl
)
3570 TRANS(ANDN
, ALL
, do_logic
, a
, tcg_gen_andc_tl
, NULL
)
3571 TRANS(ORN
, ALL
, do_logic
, a
, tcg_gen_orc_tl
, NULL
)
3572 TRANS(XORN
, ALL
, do_logic
, a
, tcg_gen_eqv_tl
, NULL
)
3574 TRANS(MULX
, 64, do_arith
, a
, tcg_gen_mul_tl
, tcg_gen_muli_tl
, NULL
)
3575 TRANS(UMUL
, MUL
, do_logic
, a
, gen_op_umul
, NULL
)
3576 TRANS(SMUL
, MUL
, do_logic
, a
, gen_op_smul
, NULL
)
3577 TRANS(MULScc
, ALL
, do_arith
, a
, NULL
, NULL
, gen_op_mulscc
)
3579 TRANS(UDIVcc
, DIV
, do_arith
, a
, NULL
, NULL
, gen_op_udivcc
)
3580 TRANS(SDIV
, DIV
, do_arith
, a
, gen_op_sdiv
, NULL
, gen_op_sdivcc
)
3582 /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3583 TRANS(POPC
, 64, do_arith
, a
, gen_op_popc
, NULL
, NULL
)
3585 static bool trans_OR(DisasContext
*dc
, arg_r_r_ri_cc
*a
)
3587 /* OR with %g0 is the canonical alias for MOV. */
3588 if (!a
->cc
&& a
->rs1
== 0) {
3589 if (a
->imm
|| a
->rs2_or_imm
== 0) {
3590 gen_store_gpr(dc
, a
->rd
, tcg_constant_tl(a
->rs2_or_imm
));
3591 } else if (a
->rs2_or_imm
& ~0x1f) {
3592 /* For simplicity, we under-decoded the rs2 form. */
3595 gen_store_gpr(dc
, a
->rd
, cpu_regs
[a
->rs2_or_imm
]);
3597 return advance_pc(dc
);
3599 return do_logic(dc
, a
, tcg_gen_or_tl
, tcg_gen_ori_tl
);
3602 static bool trans_UDIV(DisasContext
*dc
, arg_r_r_ri
*a
)
3607 if (!avail_DIV(dc
)) {
3610 /* For simplicity, we under-decoded the rs2 form. */
3611 if (!a
->imm
&& a
->rs2_or_imm
& ~0x1f) {
3615 if (unlikely(a
->rs2_or_imm
== 0)) {
3616 gen_exception(dc
, TT_DIV_ZERO
);
3621 t2
= tcg_constant_i64((uint32_t)a
->rs2_or_imm
);
3629 n2
= tcg_temp_new_i32();
3630 tcg_gen_trunc_tl_i32(n2
, cpu_regs
[a
->rs2_or_imm
]);
3632 lab
= delay_exception(dc
, TT_DIV_ZERO
);
3633 tcg_gen_brcondi_i32(TCG_COND_EQ
, n2
, 0, lab
);
3635 t2
= tcg_temp_new_i64();
3636 #ifdef TARGET_SPARC64
3637 tcg_gen_ext32u_i64(t2
, cpu_regs
[a
->rs2_or_imm
]);
3639 tcg_gen_extu_i32_i64(t2
, cpu_regs
[a
->rs2_or_imm
]);
3643 t1
= tcg_temp_new_i64();
3644 tcg_gen_concat_tl_i64(t1
, gen_load_gpr(dc
, a
->rs1
), cpu_y
);
3646 tcg_gen_divu_i64(t1
, t1
, t2
);
3647 tcg_gen_umin_i64(t1
, t1
, tcg_constant_i64(UINT32_MAX
));
3649 dst
= gen_dest_gpr(dc
, a
->rd
);
3650 tcg_gen_trunc_i64_tl(dst
, t1
);
3651 gen_store_gpr(dc
, a
->rd
, dst
);
3652 return advance_pc(dc
);
3655 static bool trans_UDIVX(DisasContext
*dc
, arg_r_r_ri
*a
)
3657 TCGv dst
, src1
, src2
;
3659 if (!avail_64(dc
)) {
3662 /* For simplicity, we under-decoded the rs2 form. */
3663 if (!a
->imm
&& a
->rs2_or_imm
& ~0x1f) {
3667 if (unlikely(a
->rs2_or_imm
== 0)) {
3668 gen_exception(dc
, TT_DIV_ZERO
);
3673 src2
= tcg_constant_tl(a
->rs2_or_imm
);
3680 lab
= delay_exception(dc
, TT_DIV_ZERO
);
3681 src2
= cpu_regs
[a
->rs2_or_imm
];
3682 tcg_gen_brcondi_tl(TCG_COND_EQ
, src2
, 0, lab
);
3685 dst
= gen_dest_gpr(dc
, a
->rd
);
3686 src1
= gen_load_gpr(dc
, a
->rs1
);
3688 tcg_gen_divu_tl(dst
, src1
, src2
);
3689 gen_store_gpr(dc
, a
->rd
, dst
);
3690 return advance_pc(dc
);
3693 static bool trans_SDIVX(DisasContext
*dc
, arg_r_r_ri
*a
)
3695 TCGv dst
, src1
, src2
;
3697 if (!avail_64(dc
)) {
3700 /* For simplicity, we under-decoded the rs2 form. */
3701 if (!a
->imm
&& a
->rs2_or_imm
& ~0x1f) {
3705 if (unlikely(a
->rs2_or_imm
== 0)) {
3706 gen_exception(dc
, TT_DIV_ZERO
);
3710 dst
= gen_dest_gpr(dc
, a
->rd
);
3711 src1
= gen_load_gpr(dc
, a
->rs1
);
3714 if (unlikely(a
->rs2_or_imm
== -1)) {
3715 tcg_gen_neg_tl(dst
, src1
);
3716 gen_store_gpr(dc
, a
->rd
, dst
);
3717 return advance_pc(dc
);
3719 src2
= tcg_constant_tl(a
->rs2_or_imm
);
3727 lab
= delay_exception(dc
, TT_DIV_ZERO
);
3728 src2
= cpu_regs
[a
->rs2_or_imm
];
3729 tcg_gen_brcondi_tl(TCG_COND_EQ
, src2
, 0, lab
);
3732 * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3733 * Set SRC2 to 1 as a new divisor, to produce the correct result.
3735 t1
= tcg_temp_new();
3736 t2
= tcg_temp_new();
3737 tcg_gen_setcondi_tl(TCG_COND_EQ
, t1
, src1
, (target_long
)INT64_MIN
);
3738 tcg_gen_setcondi_tl(TCG_COND_EQ
, t2
, src2
, -1);
3739 tcg_gen_and_tl(t1
, t1
, t2
);
3740 tcg_gen_movcond_tl(TCG_COND_NE
, t1
, t1
, tcg_constant_tl(0),
3741 tcg_constant_tl(1), src2
);
3745 tcg_gen_div_tl(dst
, src1
, src2
);
3746 gen_store_gpr(dc
, a
->rd
, dst
);
3747 return advance_pc(dc
);
3750 static bool gen_edge(DisasContext
*dc
, arg_r_r_r
*a
,
3751 int width
, bool cc
, bool left
)
3753 TCGv dst
, s1
, s2
, lo1
, lo2
;
3754 uint64_t amask
, tabl
, tabr
;
3755 int shift
, imask
, omask
;
3757 dst
= gen_dest_gpr(dc
, a
->rd
);
3758 s1
= gen_load_gpr(dc
, a
->rs1
);
3759 s2
= gen_load_gpr(dc
, a
->rs2
);
3762 gen_op_subcc(cpu_cc_N
, s1
, s2
);
3766 * Theory of operation: there are two tables, left and right (not to
3767 * be confused with the left and right versions of the opcode). These
3768 * are indexed by the low 3 bits of the inputs. To make things "easy",
3769 * these tables are loaded into two constants, TABL and TABR below.
3770 * The operation index = (input & imask) << shift calculates the index
3771 * into the constant, while val = (table >> index) & omask calculates
3772 * the value we're looking for.
3780 tabl
= 0x80c0e0f0f8fcfeffULL
;
3781 tabr
= 0xff7f3f1f0f070301ULL
;
3783 tabl
= 0x0103070f1f3f7fffULL
;
3784 tabr
= 0xfffefcf8f0e0c080ULL
;
3804 tabl
= (2 << 2) | 3;
3805 tabr
= (3 << 2) | 1;
3807 tabl
= (1 << 2) | 3;
3808 tabr
= (3 << 2) | 2;
3815 lo1
= tcg_temp_new();
3816 lo2
= tcg_temp_new();
3817 tcg_gen_andi_tl(lo1
, s1
, imask
);
3818 tcg_gen_andi_tl(lo2
, s2
, imask
);
3819 tcg_gen_shli_tl(lo1
, lo1
, shift
);
3820 tcg_gen_shli_tl(lo2
, lo2
, shift
);
3822 tcg_gen_shr_tl(lo1
, tcg_constant_tl(tabl
), lo1
);
3823 tcg_gen_shr_tl(lo2
, tcg_constant_tl(tabr
), lo2
);
3824 tcg_gen_andi_tl(lo1
, lo1
, omask
);
3825 tcg_gen_andi_tl(lo2
, lo2
, omask
);
3827 amask
= address_mask_i(dc
, -8);
3828 tcg_gen_andi_tl(s1
, s1
, amask
);
3829 tcg_gen_andi_tl(s2
, s2
, amask
);
3831 /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
3832 tcg_gen_and_tl(lo2
, lo2
, lo1
);
3833 tcg_gen_movcond_tl(TCG_COND_EQ
, dst
, s1
, s2
, lo1
, lo2
);
3835 gen_store_gpr(dc
, a
->rd
, dst
);
3836 return advance_pc(dc
);
3839 TRANS(EDGE8cc
, VIS1
, gen_edge
, a
, 8, 1, 0)
3840 TRANS(EDGE8Lcc
, VIS1
, gen_edge
, a
, 8, 1, 1)
3841 TRANS(EDGE16cc
, VIS1
, gen_edge
, a
, 16, 1, 0)
3842 TRANS(EDGE16Lcc
, VIS1
, gen_edge
, a
, 16, 1, 1)
3843 TRANS(EDGE32cc
, VIS1
, gen_edge
, a
, 32, 1, 0)
3844 TRANS(EDGE32Lcc
, VIS1
, gen_edge
, a
, 32, 1, 1)
3846 TRANS(EDGE8N
, VIS2
, gen_edge
, a
, 8, 0, 0)
3847 TRANS(EDGE8LN
, VIS2
, gen_edge
, a
, 8, 0, 1)
3848 TRANS(EDGE16N
, VIS2
, gen_edge
, a
, 16, 0, 0)
3849 TRANS(EDGE16LN
, VIS2
, gen_edge
, a
, 16, 0, 1)
3850 TRANS(EDGE32N
, VIS2
, gen_edge
, a
, 32, 0, 0)
3851 TRANS(EDGE32LN
, VIS2
, gen_edge
, a
, 32, 0, 1)
3853 static bool do_rrr(DisasContext
*dc
, arg_r_r_r
*a
,
3854 void (*func
)(TCGv
, TCGv
, TCGv
))
3856 TCGv dst
= gen_dest_gpr(dc
, a
->rd
);
3857 TCGv src1
= gen_load_gpr(dc
, a
->rs1
);
3858 TCGv src2
= gen_load_gpr(dc
, a
->rs2
);
3860 func(dst
, src1
, src2
);
3861 gen_store_gpr(dc
, a
->rd
, dst
);
3862 return advance_pc(dc
);
3865 TRANS(ARRAY8
, VIS1
, do_rrr
, a
, gen_helper_array8
)
3866 TRANS(ARRAY16
, VIS1
, do_rrr
, a
, gen_op_array16
)
3867 TRANS(ARRAY32
, VIS1
, do_rrr
, a
, gen_op_array32
)
3869 static void gen_op_alignaddr(TCGv dst
, TCGv s1
, TCGv s2
)
3871 #ifdef TARGET_SPARC64
3872 TCGv tmp
= tcg_temp_new();
3874 tcg_gen_add_tl(tmp
, s1
, s2
);
3875 tcg_gen_andi_tl(dst
, tmp
, -8);
3876 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, tmp
, 0, 3);
3878 g_assert_not_reached();
3882 static void gen_op_alignaddrl(TCGv dst
, TCGv s1
, TCGv s2
)
3884 #ifdef TARGET_SPARC64
3885 TCGv tmp
= tcg_temp_new();
3887 tcg_gen_add_tl(tmp
, s1
, s2
);
3888 tcg_gen_andi_tl(dst
, tmp
, -8);
3889 tcg_gen_neg_tl(tmp
, tmp
);
3890 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, tmp
, 0, 3);
3892 g_assert_not_reached();
3896 TRANS(ALIGNADDR
, VIS1
, do_rrr
, a
, gen_op_alignaddr
)
3897 TRANS(ALIGNADDRL
, VIS1
, do_rrr
, a
, gen_op_alignaddrl
)
3899 static void gen_op_bmask(TCGv dst
, TCGv s1
, TCGv s2
)
3901 #ifdef TARGET_SPARC64
3902 tcg_gen_add_tl(dst
, s1
, s2
);
3903 tcg_gen_deposit_tl(cpu_gsr
, cpu_gsr
, dst
, 32, 32);
3905 g_assert_not_reached();
3909 TRANS(BMASK
, VIS2
, do_rrr
, a
, gen_op_bmask
)
3911 static bool do_shift_r(DisasContext
*dc
, arg_shiftr
*a
, bool l
, bool u
)
3913 TCGv dst
, src1
, src2
;
3915 /* Reject 64-bit shifts for sparc32. */
3916 if (avail_32(dc
) && a
->x
) {
3920 src2
= tcg_temp_new();
3921 tcg_gen_andi_tl(src2
, gen_load_gpr(dc
, a
->rs2
), a
->x
? 63 : 31);
3922 src1
= gen_load_gpr(dc
, a
->rs1
);
3923 dst
= gen_dest_gpr(dc
, a
->rd
);
3926 tcg_gen_shl_tl(dst
, src1
, src2
);
3928 tcg_gen_ext32u_tl(dst
, dst
);
3932 tcg_gen_ext32u_tl(dst
, src1
);
3935 tcg_gen_shr_tl(dst
, src1
, src2
);
3938 tcg_gen_ext32s_tl(dst
, src1
);
3941 tcg_gen_sar_tl(dst
, src1
, src2
);
3943 gen_store_gpr(dc
, a
->rd
, dst
);
3944 return advance_pc(dc
);
3947 TRANS(SLL_r
, ALL
, do_shift_r
, a
, true, true)
3948 TRANS(SRL_r
, ALL
, do_shift_r
, a
, false, true)
3949 TRANS(SRA_r
, ALL
, do_shift_r
, a
, false, false)
3951 static bool do_shift_i(DisasContext
*dc
, arg_shifti
*a
, bool l
, bool u
)
3955 /* Reject 64-bit shifts for sparc32. */
3956 if (avail_32(dc
) && (a
->x
|| a
->i
>= 32)) {
3960 src1
= gen_load_gpr(dc
, a
->rs1
);
3961 dst
= gen_dest_gpr(dc
, a
->rd
);
3963 if (avail_32(dc
) || a
->x
) {
3965 tcg_gen_shli_tl(dst
, src1
, a
->i
);
3967 tcg_gen_shri_tl(dst
, src1
, a
->i
);
3969 tcg_gen_sari_tl(dst
, src1
, a
->i
);
3973 tcg_gen_deposit_z_tl(dst
, src1
, a
->i
, 32 - a
->i
);
3975 tcg_gen_extract_tl(dst
, src1
, a
->i
, 32 - a
->i
);
3977 tcg_gen_sextract_tl(dst
, src1
, a
->i
, 32 - a
->i
);
3980 gen_store_gpr(dc
, a
->rd
, dst
);
3981 return advance_pc(dc
);
3984 TRANS(SLL_i
, ALL
, do_shift_i
, a
, true, true)
3985 TRANS(SRL_i
, ALL
, do_shift_i
, a
, false, true)
3986 TRANS(SRA_i
, ALL
, do_shift_i
, a
, false, false)
3988 static TCGv
gen_rs2_or_imm(DisasContext
*dc
, bool imm
, int rs2_or_imm
)
3990 /* For simplicity, we under-decoded the rs2 form. */
3991 if (!imm
&& rs2_or_imm
& ~0x1f) {
3994 if (imm
|| rs2_or_imm
== 0) {
3995 return tcg_constant_tl(rs2_or_imm
);
3997 return cpu_regs
[rs2_or_imm
];
4001 static bool do_mov_cond(DisasContext
*dc
, DisasCompare
*cmp
, int rd
, TCGv src2
)
4003 TCGv dst
= gen_load_gpr(dc
, rd
);
4004 TCGv c2
= tcg_constant_tl(cmp
->c2
);
4006 tcg_gen_movcond_tl(cmp
->cond
, dst
, cmp
->c1
, c2
, src2
, dst
);
4007 gen_store_gpr(dc
, rd
, dst
);
4008 return advance_pc(dc
);
4011 static bool trans_MOVcc(DisasContext
*dc
, arg_MOVcc
*a
)
4013 TCGv src2
= gen_rs2_or_imm(dc
, a
->imm
, a
->rs2_or_imm
);
4019 gen_compare(&cmp
, a
->cc
, a
->cond
, dc
);
4020 return do_mov_cond(dc
, &cmp
, a
->rd
, src2
);
4023 static bool trans_MOVfcc(DisasContext
*dc
, arg_MOVfcc
*a
)
4025 TCGv src2
= gen_rs2_or_imm(dc
, a
->imm
, a
->rs2_or_imm
);
4031 gen_fcompare(&cmp
, a
->cc
, a
->cond
);
4032 return do_mov_cond(dc
, &cmp
, a
->rd
, src2
);
4035 static bool trans_MOVR(DisasContext
*dc
, arg_MOVR
*a
)
4037 TCGv src2
= gen_rs2_or_imm(dc
, a
->imm
, a
->rs2_or_imm
);
4043 if (!gen_compare_reg(&cmp
, a
->cond
, gen_load_gpr(dc
, a
->rs1
))) {
4046 return do_mov_cond(dc
, &cmp
, a
->rd
, src2
);
4049 static bool do_add_special(DisasContext
*dc
, arg_r_r_ri
*a
,
4050 bool (*func
)(DisasContext
*dc
, int rd
, TCGv src
))
4054 /* For simplicity, we under-decoded the rs2 form. */
4055 if (!a
->imm
&& a
->rs2_or_imm
& ~0x1f) {
4060 * Always load the sum into a new temporary.
4061 * This is required to capture the value across a window change,
4062 * e.g. SAVE and RESTORE, and may be optimized away otherwise.
4064 sum
= tcg_temp_new();
4065 src1
= gen_load_gpr(dc
, a
->rs1
);
4066 if (a
->imm
|| a
->rs2_or_imm
== 0) {
4067 tcg_gen_addi_tl(sum
, src1
, a
->rs2_or_imm
);
4069 tcg_gen_add_tl(sum
, src1
, cpu_regs
[a
->rs2_or_imm
]);
4071 return func(dc
, a
->rd
, sum
);
4074 static bool do_jmpl(DisasContext
*dc
, int rd
, TCGv src
)
4077 * Preserve pc across advance, so that we can delay
4078 * the writeback to rd until after src is consumed.
4080 target_ulong cur_pc
= dc
->pc
;
4082 gen_check_align(dc
, src
, 3);
4085 tcg_gen_mov_tl(cpu_npc
, src
);
4086 gen_address_mask(dc
, cpu_npc
);
4087 gen_store_gpr(dc
, rd
, tcg_constant_tl(cur_pc
));
4089 dc
->npc
= DYNAMIC_PC_LOOKUP
;
4093 TRANS(JMPL
, ALL
, do_add_special
, a
, do_jmpl
)
4095 static bool do_rett(DisasContext
*dc
, int rd
, TCGv src
)
4097 if (!supervisor(dc
)) {
4098 return raise_priv(dc
);
4101 gen_check_align(dc
, src
, 3);
4104 tcg_gen_mov_tl(cpu_npc
, src
);
4105 gen_helper_rett(tcg_env
);
4107 dc
->npc
= DYNAMIC_PC
;
4111 TRANS(RETT
, 32, do_add_special
, a
, do_rett
)
4113 static bool do_return(DisasContext
*dc
, int rd
, TCGv src
)
4115 gen_check_align(dc
, src
, 3);
4116 gen_helper_restore(tcg_env
);
4119 tcg_gen_mov_tl(cpu_npc
, src
);
4120 gen_address_mask(dc
, cpu_npc
);
4122 dc
->npc
= DYNAMIC_PC_LOOKUP
;
4126 TRANS(RETURN
, 64, do_add_special
, a
, do_return
)
4128 static bool do_save(DisasContext
*dc
, int rd
, TCGv src
)
4130 gen_helper_save(tcg_env
);
4131 gen_store_gpr(dc
, rd
, src
);
4132 return advance_pc(dc
);
4135 TRANS(SAVE
, ALL
, do_add_special
, a
, do_save
)
4137 static bool do_restore(DisasContext
*dc
, int rd
, TCGv src
)
4139 gen_helper_restore(tcg_env
);
4140 gen_store_gpr(dc
, rd
, src
);
4141 return advance_pc(dc
);
4144 TRANS(RESTORE
, ALL
, do_add_special
, a
, do_restore
)
4146 static bool do_done_retry(DisasContext
*dc
, bool done
)
4148 if (!supervisor(dc
)) {
4149 return raise_priv(dc
);
4151 dc
->npc
= DYNAMIC_PC
;
4152 dc
->pc
= DYNAMIC_PC
;
4153 translator_io_start(&dc
->base
);
4155 gen_helper_done(tcg_env
);
4157 gen_helper_retry(tcg_env
);
4162 TRANS(DONE
, 64, do_done_retry
, true)
4163 TRANS(RETRY
, 64, do_done_retry
, false)
4166 * Major opcode 11 -- load and store instructions
4169 static TCGv
gen_ldst_addr(DisasContext
*dc
, int rs1
, bool imm
, int rs2_or_imm
)
4171 TCGv addr
, tmp
= NULL
;
4173 /* For simplicity, we under-decoded the rs2 form. */
4174 if (!imm
&& rs2_or_imm
& ~0x1f) {
4178 addr
= gen_load_gpr(dc
, rs1
);
4180 tmp
= tcg_temp_new();
4182 tcg_gen_addi_tl(tmp
, addr
, rs2_or_imm
);
4184 tcg_gen_add_tl(tmp
, addr
, cpu_regs
[rs2_or_imm
]);
4190 tmp
= tcg_temp_new();
4192 tcg_gen_ext32u_tl(tmp
, addr
);
4198 static bool do_ld_gpr(DisasContext
*dc
, arg_r_r_ri_asi
*a
, MemOp mop
)
4200 TCGv reg
, addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4206 da
= resolve_asi(dc
, a
->asi
, mop
);
4208 reg
= gen_dest_gpr(dc
, a
->rd
);
4209 gen_ld_asi(dc
, &da
, reg
, addr
);
4210 gen_store_gpr(dc
, a
->rd
, reg
);
4211 return advance_pc(dc
);
4214 TRANS(LDUW
, ALL
, do_ld_gpr
, a
, MO_TEUL
)
4215 TRANS(LDUB
, ALL
, do_ld_gpr
, a
, MO_UB
)
4216 TRANS(LDUH
, ALL
, do_ld_gpr
, a
, MO_TEUW
)
4217 TRANS(LDSB
, ALL
, do_ld_gpr
, a
, MO_SB
)
4218 TRANS(LDSH
, ALL
, do_ld_gpr
, a
, MO_TESW
)
4219 TRANS(LDSW
, 64, do_ld_gpr
, a
, MO_TESL
)
4220 TRANS(LDX
, 64, do_ld_gpr
, a
, MO_TEUQ
)
4222 static bool do_st_gpr(DisasContext
*dc
, arg_r_r_ri_asi
*a
, MemOp mop
)
4224 TCGv reg
, addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4230 da
= resolve_asi(dc
, a
->asi
, mop
);
4232 reg
= gen_load_gpr(dc
, a
->rd
);
4233 gen_st_asi(dc
, &da
, reg
, addr
);
4234 return advance_pc(dc
);
4237 TRANS(STW
, ALL
, do_st_gpr
, a
, MO_TEUL
)
4238 TRANS(STB
, ALL
, do_st_gpr
, a
, MO_UB
)
4239 TRANS(STH
, ALL
, do_st_gpr
, a
, MO_TEUW
)
4240 TRANS(STX
, 64, do_st_gpr
, a
, MO_TEUQ
)
4242 static bool trans_LDD(DisasContext
*dc
, arg_r_r_ri_asi
*a
)
4250 addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4254 da
= resolve_asi(dc
, a
->asi
, MO_TEUQ
);
4255 gen_ldda_asi(dc
, &da
, addr
, a
->rd
);
4256 return advance_pc(dc
);
4259 static bool trans_STD(DisasContext
*dc
, arg_r_r_ri_asi
*a
)
4267 addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4271 da
= resolve_asi(dc
, a
->asi
, MO_TEUQ
);
4272 gen_stda_asi(dc
, &da
, addr
, a
->rd
);
4273 return advance_pc(dc
);
4276 static bool trans_LDSTUB(DisasContext
*dc
, arg_r_r_ri_asi
*a
)
4281 addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4285 da
= resolve_asi(dc
, a
->asi
, MO_UB
);
4287 reg
= gen_dest_gpr(dc
, a
->rd
);
4288 gen_ldstub_asi(dc
, &da
, reg
, addr
);
4289 gen_store_gpr(dc
, a
->rd
, reg
);
4290 return advance_pc(dc
);
4293 static bool trans_SWAP(DisasContext
*dc
, arg_r_r_ri_asi
*a
)
4295 TCGv addr
, dst
, src
;
4298 addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4302 da
= resolve_asi(dc
, a
->asi
, MO_TEUL
);
4304 dst
= gen_dest_gpr(dc
, a
->rd
);
4305 src
= gen_load_gpr(dc
, a
->rd
);
4306 gen_swap_asi(dc
, &da
, dst
, src
, addr
);
4307 gen_store_gpr(dc
, a
->rd
, dst
);
4308 return advance_pc(dc
);
4311 static bool do_casa(DisasContext
*dc
, arg_r_r_ri_asi
*a
, MemOp mop
)
4316 addr
= gen_ldst_addr(dc
, a
->rs1
, true, 0);
4320 da
= resolve_asi(dc
, a
->asi
, mop
);
4322 o
= gen_dest_gpr(dc
, a
->rd
);
4323 n
= gen_load_gpr(dc
, a
->rd
);
4324 c
= gen_load_gpr(dc
, a
->rs2_or_imm
);
4325 gen_cas_asi(dc
, &da
, o
, n
, c
, addr
);
4326 gen_store_gpr(dc
, a
->rd
, o
);
4327 return advance_pc(dc
);
4330 TRANS(CASA
, CASA
, do_casa
, a
, MO_TEUL
)
4331 TRANS(CASXA
, 64, do_casa
, a
, MO_TEUQ
)
4333 static bool do_ld_fpr(DisasContext
*dc
, arg_r_r_ri_asi
*a
, MemOp sz
)
4335 TCGv addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4341 if (gen_trap_ifnofpu(dc
)) {
4344 if (sz
== MO_128
&& gen_trap_float128(dc
)) {
4347 da
= resolve_asi(dc
, a
->asi
, MO_TE
| sz
);
4348 gen_ldf_asi(dc
, &da
, sz
, addr
, a
->rd
);
4349 gen_update_fprs_dirty(dc
, a
->rd
);
4350 return advance_pc(dc
);
4353 TRANS(LDF
, ALL
, do_ld_fpr
, a
, MO_32
)
4354 TRANS(LDDF
, ALL
, do_ld_fpr
, a
, MO_64
)
4355 TRANS(LDQF
, ALL
, do_ld_fpr
, a
, MO_128
)
4357 TRANS(LDFA
, 64, do_ld_fpr
, a
, MO_32
)
4358 TRANS(LDDFA
, 64, do_ld_fpr
, a
, MO_64
)
4359 TRANS(LDQFA
, 64, do_ld_fpr
, a
, MO_128
)
4361 static bool do_st_fpr(DisasContext
*dc
, arg_r_r_ri_asi
*a
, MemOp sz
)
4363 TCGv addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4369 if (gen_trap_ifnofpu(dc
)) {
4372 if (sz
== MO_128
&& gen_trap_float128(dc
)) {
4375 da
= resolve_asi(dc
, a
->asi
, MO_TE
| sz
);
4376 gen_stf_asi(dc
, &da
, sz
, addr
, a
->rd
);
4377 return advance_pc(dc
);
4380 TRANS(STF
, ALL
, do_st_fpr
, a
, MO_32
)
4381 TRANS(STDF
, ALL
, do_st_fpr
, a
, MO_64
)
4382 TRANS(STQF
, ALL
, do_st_fpr
, a
, MO_128
)
4384 TRANS(STFA
, 64, do_st_fpr
, a
, MO_32
)
4385 TRANS(STDFA
, 64, do_st_fpr
, a
, MO_64
)
4386 TRANS(STQFA
, 64, do_st_fpr
, a
, MO_128
)
4388 static bool trans_STDFQ(DisasContext
*dc
, arg_STDFQ
*a
)
4390 if (!avail_32(dc
)) {
4393 if (!supervisor(dc
)) {
4394 return raise_priv(dc
);
4396 if (gen_trap_ifnofpu(dc
)) {
4399 gen_op_fpexception_im(dc
, FSR_FTT_SEQ_ERROR
);
4403 static bool do_ldfsr(DisasContext
*dc
, arg_r_r_ri
*a
, MemOp mop
,
4404 target_ulong new_mask
, target_ulong old_mask
)
4406 TCGv addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4412 if (gen_trap_ifnofpu(dc
)) {
4415 tnew
= tcg_temp_new();
4416 told
= tcg_temp_new();
4417 tcg_gen_qemu_ld_tl(tnew
, addr
, dc
->mem_idx
, mop
| MO_ALIGN
);
4418 tcg_gen_ld_tl(told
, tcg_env
, offsetof(CPUSPARCState
, fsr
));
4419 tcg_gen_andi_tl(tnew
, tnew
, new_mask
);
4420 tcg_gen_andi_tl(told
, told
, old_mask
);
4421 tcg_gen_or_tl(tnew
, tnew
, told
);
4422 gen_helper_set_fsr_noftt(tcg_env
, tnew
);
4423 return advance_pc(dc
);
4426 TRANS(LDFSR
, ALL
, do_ldfsr
, a
, MO_TEUL
, FSR_LDFSR_MASK
, FSR_LDFSR_OLDMASK
)
4427 TRANS(LDXFSR
, 64, do_ldfsr
, a
, MO_TEUQ
, FSR_LDXFSR_MASK
, FSR_LDXFSR_OLDMASK
)
4429 static bool do_stfsr(DisasContext
*dc
, arg_r_r_ri
*a
, MemOp mop
)
4431 TCGv addr
= gen_ldst_addr(dc
, a
->rs1
, a
->imm
, a
->rs2_or_imm
);
4437 if (gen_trap_ifnofpu(dc
)) {
4441 fsr
= tcg_temp_new();
4442 gen_helper_get_fsr(fsr
, tcg_env
);
4443 tcg_gen_qemu_st_tl(fsr
, addr
, dc
->mem_idx
, mop
| MO_ALIGN
);
4444 return advance_pc(dc
);
4447 TRANS(STFSR
, ALL
, do_stfsr
, a
, MO_TEUL
)
4448 TRANS(STXFSR
, 64, do_stfsr
, a
, MO_TEUQ
)
4450 static bool do_fc(DisasContext
*dc
, int rd
, bool c
)
4454 if (gen_trap_ifnofpu(dc
)) {
4459 mask
= MAKE_64BIT_MASK(0, 32);
4461 mask
= MAKE_64BIT_MASK(32, 32);
4464 tcg_gen_ori_i64(cpu_fpr
[rd
/ 2], cpu_fpr
[rd
/ 2], mask
);
4466 tcg_gen_andi_i64(cpu_fpr
[rd
/ 2], cpu_fpr
[rd
/ 2], ~mask
);
4468 gen_update_fprs_dirty(dc
, rd
);
4469 return advance_pc(dc
);
4472 TRANS(FZEROs
, VIS1
, do_fc
, a
->rd
, 0)
4473 TRANS(FONEs
, VIS1
, do_fc
, a
->rd
, 1)
4475 static bool do_dc(DisasContext
*dc
, int rd
, int64_t c
)
4477 if (gen_trap_ifnofpu(dc
)) {
4481 tcg_gen_movi_i64(cpu_fpr
[rd
/ 2], c
);
4482 gen_update_fprs_dirty(dc
, rd
);
4483 return advance_pc(dc
);
4486 TRANS(FZEROd
, VIS1
, do_dc
, a
->rd
, 0)
4487 TRANS(FONEd
, VIS1
, do_dc
, a
->rd
, -1)
4489 static bool do_ff(DisasContext
*dc
, arg_r_r
*a
,
4490 void (*func
)(TCGv_i32
, TCGv_i32
))
4494 if (gen_trap_ifnofpu(dc
)) {
4498 tmp
= gen_load_fpr_F(dc
, a
->rs
);
4500 gen_store_fpr_F(dc
, a
->rd
, tmp
);
4501 return advance_pc(dc
);
4504 TRANS(FMOVs
, ALL
, do_ff
, a
, gen_op_fmovs
)
4505 TRANS(FNEGs
, ALL
, do_ff
, a
, gen_op_fnegs
)
4506 TRANS(FABSs
, ALL
, do_ff
, a
, gen_op_fabss
)
4507 TRANS(FSRCs
, VIS1
, do_ff
, a
, tcg_gen_mov_i32
)
4508 TRANS(FNOTs
, VIS1
, do_ff
, a
, tcg_gen_not_i32
)
4510 static bool do_fd(DisasContext
*dc
, arg_r_r
*a
,
4511 void (*func
)(TCGv_i32
, TCGv_i64
))
4516 if (gen_trap_ifnofpu(dc
)) {
4520 dst
= tcg_temp_new_i32();
4521 src
= gen_load_fpr_D(dc
, a
->rs
);
4523 gen_store_fpr_F(dc
, a
->rd
, dst
);
4524 return advance_pc(dc
);
4527 TRANS(FPACK16
, VIS1
, do_fd
, a
, gen_op_fpack16
)
4528 TRANS(FPACKFIX
, VIS1
, do_fd
, a
, gen_op_fpackfix
)
4530 static bool do_env_ff(DisasContext
*dc
, arg_r_r
*a
,
4531 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i32
))
4535 if (gen_trap_ifnofpu(dc
)) {
4539 tmp
= gen_load_fpr_F(dc
, a
->rs
);
4540 func(tmp
, tcg_env
, tmp
);
4541 gen_store_fpr_F(dc
, a
->rd
, tmp
);
4542 return advance_pc(dc
);
4545 TRANS(FSQRTs
, ALL
, do_env_ff
, a
, gen_helper_fsqrts
)
4546 TRANS(FiTOs
, ALL
, do_env_ff
, a
, gen_helper_fitos
)
4547 TRANS(FsTOi
, ALL
, do_env_ff
, a
, gen_helper_fstoi
)
4549 static bool do_env_fd(DisasContext
*dc
, arg_r_r
*a
,
4550 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i64
))
4555 if (gen_trap_ifnofpu(dc
)) {
4559 dst
= tcg_temp_new_i32();
4560 src
= gen_load_fpr_D(dc
, a
->rs
);
4561 func(dst
, tcg_env
, src
);
4562 gen_store_fpr_F(dc
, a
->rd
, dst
);
4563 return advance_pc(dc
);
4566 TRANS(FdTOs
, ALL
, do_env_fd
, a
, gen_helper_fdtos
)
4567 TRANS(FdTOi
, ALL
, do_env_fd
, a
, gen_helper_fdtoi
)
4568 TRANS(FxTOs
, 64, do_env_fd
, a
, gen_helper_fxtos
)
4570 static bool do_dd(DisasContext
*dc
, arg_r_r
*a
,
4571 void (*func
)(TCGv_i64
, TCGv_i64
))
4575 if (gen_trap_ifnofpu(dc
)) {
4579 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4580 src
= gen_load_fpr_D(dc
, a
->rs
);
4582 gen_store_fpr_D(dc
, a
->rd
, dst
);
4583 return advance_pc(dc
);
4586 TRANS(FMOVd
, 64, do_dd
, a
, gen_op_fmovd
)
4587 TRANS(FNEGd
, 64, do_dd
, a
, gen_op_fnegd
)
4588 TRANS(FABSd
, 64, do_dd
, a
, gen_op_fabsd
)
4589 TRANS(FSRCd
, VIS1
, do_dd
, a
, tcg_gen_mov_i64
)
4590 TRANS(FNOTd
, VIS1
, do_dd
, a
, tcg_gen_not_i64
)
4592 static bool do_env_dd(DisasContext
*dc
, arg_r_r
*a
,
4593 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i64
))
4597 if (gen_trap_ifnofpu(dc
)) {
4601 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4602 src
= gen_load_fpr_D(dc
, a
->rs
);
4603 func(dst
, tcg_env
, src
);
4604 gen_store_fpr_D(dc
, a
->rd
, dst
);
4605 return advance_pc(dc
);
4608 TRANS(FSQRTd
, ALL
, do_env_dd
, a
, gen_helper_fsqrtd
)
4609 TRANS(FxTOd
, 64, do_env_dd
, a
, gen_helper_fxtod
)
4610 TRANS(FdTOx
, 64, do_env_dd
, a
, gen_helper_fdtox
)
4612 static bool do_env_df(DisasContext
*dc
, arg_r_r
*a
,
4613 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i32
))
4618 if (gen_trap_ifnofpu(dc
)) {
4622 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4623 src
= gen_load_fpr_F(dc
, a
->rs
);
4624 func(dst
, tcg_env
, src
);
4625 gen_store_fpr_D(dc
, a
->rd
, dst
);
4626 return advance_pc(dc
);
4629 TRANS(FiTOd
, ALL
, do_env_df
, a
, gen_helper_fitod
)
4630 TRANS(FsTOd
, ALL
, do_env_df
, a
, gen_helper_fstod
)
4631 TRANS(FsTOx
, 64, do_env_df
, a
, gen_helper_fstox
)
4633 static bool do_qq(DisasContext
*dc
, arg_r_r
*a
,
4634 void (*func
)(TCGv_i128
, TCGv_i128
))
4638 if (gen_trap_ifnofpu(dc
)) {
4641 if (gen_trap_float128(dc
)) {
4645 gen_op_clear_ieee_excp_and_FTT();
4646 t
= gen_load_fpr_Q(dc
, a
->rs
);
4648 gen_store_fpr_Q(dc
, a
->rd
, t
);
4649 return advance_pc(dc
);
4652 TRANS(FMOVq
, 64, do_qq
, a
, tcg_gen_mov_i128
)
4653 TRANS(FNEGq
, 64, do_qq
, a
, gen_op_fnegq
)
4654 TRANS(FABSq
, 64, do_qq
, a
, gen_op_fabsq
)
4656 static bool do_env_qq(DisasContext
*dc
, arg_r_r
*a
,
4657 void (*func
)(TCGv_i128
, TCGv_env
, TCGv_i128
))
4661 if (gen_trap_ifnofpu(dc
)) {
4664 if (gen_trap_float128(dc
)) {
4668 t
= gen_load_fpr_Q(dc
, a
->rs
);
4669 func(t
, tcg_env
, t
);
4670 gen_store_fpr_Q(dc
, a
->rd
, t
);
4671 return advance_pc(dc
);
4674 TRANS(FSQRTq
, ALL
, do_env_qq
, a
, gen_helper_fsqrtq
)
4676 static bool do_env_fq(DisasContext
*dc
, arg_r_r
*a
,
4677 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i128
))
4682 if (gen_trap_ifnofpu(dc
)) {
4685 if (gen_trap_float128(dc
)) {
4689 src
= gen_load_fpr_Q(dc
, a
->rs
);
4690 dst
= tcg_temp_new_i32();
4691 func(dst
, tcg_env
, src
);
4692 gen_store_fpr_F(dc
, a
->rd
, dst
);
4693 return advance_pc(dc
);
4696 TRANS(FqTOs
, ALL
, do_env_fq
, a
, gen_helper_fqtos
)
4697 TRANS(FqTOi
, ALL
, do_env_fq
, a
, gen_helper_fqtoi
)
4699 static bool do_env_dq(DisasContext
*dc
, arg_r_r
*a
,
4700 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i128
))
4705 if (gen_trap_ifnofpu(dc
)) {
4708 if (gen_trap_float128(dc
)) {
4712 src
= gen_load_fpr_Q(dc
, a
->rs
);
4713 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4714 func(dst
, tcg_env
, src
);
4715 gen_store_fpr_D(dc
, a
->rd
, dst
);
4716 return advance_pc(dc
);
4719 TRANS(FqTOd
, ALL
, do_env_dq
, a
, gen_helper_fqtod
)
4720 TRANS(FqTOx
, 64, do_env_dq
, a
, gen_helper_fqtox
)
4722 static bool do_env_qf(DisasContext
*dc
, arg_r_r
*a
,
4723 void (*func
)(TCGv_i128
, TCGv_env
, TCGv_i32
))
4728 if (gen_trap_ifnofpu(dc
)) {
4731 if (gen_trap_float128(dc
)) {
4735 src
= gen_load_fpr_F(dc
, a
->rs
);
4736 dst
= tcg_temp_new_i128();
4737 func(dst
, tcg_env
, src
);
4738 gen_store_fpr_Q(dc
, a
->rd
, dst
);
4739 return advance_pc(dc
);
4742 TRANS(FiTOq
, ALL
, do_env_qf
, a
, gen_helper_fitoq
)
4743 TRANS(FsTOq
, ALL
, do_env_qf
, a
, gen_helper_fstoq
)
4745 static bool do_env_qd(DisasContext
*dc
, arg_r_r
*a
,
4746 void (*func
)(TCGv_i128
, TCGv_env
, TCGv_i64
))
4751 if (gen_trap_ifnofpu(dc
)) {
4754 if (gen_trap_float128(dc
)) {
4758 src
= gen_load_fpr_D(dc
, a
->rs
);
4759 dst
= tcg_temp_new_i128();
4760 func(dst
, tcg_env
, src
);
4761 gen_store_fpr_Q(dc
, a
->rd
, dst
);
4762 return advance_pc(dc
);
4765 TRANS(FdTOq
, ALL
, do_env_qd
, a
, gen_helper_fdtoq
)
4766 TRANS(FxTOq
, 64, do_env_qd
, a
, gen_helper_fxtoq
)
4768 static bool do_fff(DisasContext
*dc
, arg_r_r_r
*a
,
4769 void (*func
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
4771 TCGv_i32 src1
, src2
;
4773 if (gen_trap_ifnofpu(dc
)) {
4777 src1
= gen_load_fpr_F(dc
, a
->rs1
);
4778 src2
= gen_load_fpr_F(dc
, a
->rs2
);
4779 func(src1
, src1
, src2
);
4780 gen_store_fpr_F(dc
, a
->rd
, src1
);
4781 return advance_pc(dc
);
4784 TRANS(FPADD16s
, VIS1
, do_fff
, a
, tcg_gen_vec_add16_i32
)
4785 TRANS(FPADD32s
, VIS1
, do_fff
, a
, tcg_gen_add_i32
)
4786 TRANS(FPSUB16s
, VIS1
, do_fff
, a
, tcg_gen_vec_sub16_i32
)
4787 TRANS(FPSUB32s
, VIS1
, do_fff
, a
, tcg_gen_sub_i32
)
4788 TRANS(FNORs
, VIS1
, do_fff
, a
, tcg_gen_nor_i32
)
4789 TRANS(FANDNOTs
, VIS1
, do_fff
, a
, tcg_gen_andc_i32
)
4790 TRANS(FXORs
, VIS1
, do_fff
, a
, tcg_gen_xor_i32
)
4791 TRANS(FNANDs
, VIS1
, do_fff
, a
, tcg_gen_nand_i32
)
4792 TRANS(FANDs
, VIS1
, do_fff
, a
, tcg_gen_and_i32
)
4793 TRANS(FXNORs
, VIS1
, do_fff
, a
, tcg_gen_eqv_i32
)
4794 TRANS(FORNOTs
, VIS1
, do_fff
, a
, tcg_gen_orc_i32
)
4795 TRANS(FORs
, VIS1
, do_fff
, a
, tcg_gen_or_i32
)
4797 static bool do_env_fff(DisasContext
*dc
, arg_r_r_r
*a
,
4798 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i32
, TCGv_i32
))
4800 TCGv_i32 src1
, src2
;
4802 if (gen_trap_ifnofpu(dc
)) {
4806 src1
= gen_load_fpr_F(dc
, a
->rs1
);
4807 src2
= gen_load_fpr_F(dc
, a
->rs2
);
4808 func(src1
, tcg_env
, src1
, src2
);
4809 gen_store_fpr_F(dc
, a
->rd
, src1
);
4810 return advance_pc(dc
);
4813 TRANS(FADDs
, ALL
, do_env_fff
, a
, gen_helper_fadds
)
4814 TRANS(FSUBs
, ALL
, do_env_fff
, a
, gen_helper_fsubs
)
4815 TRANS(FMULs
, ALL
, do_env_fff
, a
, gen_helper_fmuls
)
4816 TRANS(FDIVs
, ALL
, do_env_fff
, a
, gen_helper_fdivs
)
4818 static bool do_ddd(DisasContext
*dc
, arg_r_r_r
*a
,
4819 void (*func
)(TCGv_i64
, TCGv_i64
, TCGv_i64
))
4821 TCGv_i64 dst
, src1
, src2
;
4823 if (gen_trap_ifnofpu(dc
)) {
4827 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4828 src1
= gen_load_fpr_D(dc
, a
->rs1
);
4829 src2
= gen_load_fpr_D(dc
, a
->rs2
);
4830 func(dst
, src1
, src2
);
4831 gen_store_fpr_D(dc
, a
->rd
, dst
);
4832 return advance_pc(dc
);
4835 TRANS(FMUL8x16
, VIS1
, do_ddd
, a
, gen_helper_fmul8x16
)
4836 TRANS(FMUL8x16AU
, VIS1
, do_ddd
, a
, gen_helper_fmul8x16au
)
4837 TRANS(FMUL8x16AL
, VIS1
, do_ddd
, a
, gen_helper_fmul8x16al
)
4838 TRANS(FMUL8SUx16
, VIS1
, do_ddd
, a
, gen_helper_fmul8sux16
)
4839 TRANS(FMUL8ULx16
, VIS1
, do_ddd
, a
, gen_helper_fmul8ulx16
)
4840 TRANS(FMULD8SUx16
, VIS1
, do_ddd
, a
, gen_helper_fmuld8sux16
)
4841 TRANS(FMULD8ULx16
, VIS1
, do_ddd
, a
, gen_helper_fmuld8ulx16
)
4842 TRANS(FPMERGE
, VIS1
, do_ddd
, a
, gen_helper_fpmerge
)
4843 TRANS(FEXPAND
, VIS1
, do_ddd
, a
, gen_helper_fexpand
)
4845 TRANS(FPADD16
, VIS1
, do_ddd
, a
, tcg_gen_vec_add16_i64
)
4846 TRANS(FPADD32
, VIS1
, do_ddd
, a
, tcg_gen_vec_add32_i64
)
4847 TRANS(FPSUB16
, VIS1
, do_ddd
, a
, tcg_gen_vec_sub16_i64
)
4848 TRANS(FPSUB32
, VIS1
, do_ddd
, a
, tcg_gen_vec_sub32_i64
)
4849 TRANS(FNORd
, VIS1
, do_ddd
, a
, tcg_gen_nor_i64
)
4850 TRANS(FANDNOTd
, VIS1
, do_ddd
, a
, tcg_gen_andc_i64
)
4851 TRANS(FXORd
, VIS1
, do_ddd
, a
, tcg_gen_xor_i64
)
4852 TRANS(FNANDd
, VIS1
, do_ddd
, a
, tcg_gen_nand_i64
)
4853 TRANS(FANDd
, VIS1
, do_ddd
, a
, tcg_gen_and_i64
)
4854 TRANS(FXNORd
, VIS1
, do_ddd
, a
, tcg_gen_eqv_i64
)
4855 TRANS(FORNOTd
, VIS1
, do_ddd
, a
, tcg_gen_orc_i64
)
4856 TRANS(FORd
, VIS1
, do_ddd
, a
, tcg_gen_or_i64
)
4858 TRANS(FPACK32
, VIS1
, do_ddd
, a
, gen_op_fpack32
)
4859 TRANS(FALIGNDATAg
, VIS1
, do_ddd
, a
, gen_op_faligndata
)
4860 TRANS(BSHUFFLE
, VIS2
, do_ddd
, a
, gen_op_bshuffle
)
4862 static bool do_rdd(DisasContext
*dc
, arg_r_r_r
*a
,
4863 void (*func
)(TCGv
, TCGv_i64
, TCGv_i64
))
4865 TCGv_i64 src1
, src2
;
4868 if (gen_trap_ifnofpu(dc
)) {
4872 dst
= gen_dest_gpr(dc
, a
->rd
);
4873 src1
= gen_load_fpr_D(dc
, a
->rs1
);
4874 src2
= gen_load_fpr_D(dc
, a
->rs2
);
4875 func(dst
, src1
, src2
);
4876 gen_store_gpr(dc
, a
->rd
, dst
);
4877 return advance_pc(dc
);
4880 TRANS(FPCMPLE16
, VIS1
, do_rdd
, a
, gen_helper_fcmple16
)
4881 TRANS(FPCMPNE16
, VIS1
, do_rdd
, a
, gen_helper_fcmpne16
)
4882 TRANS(FPCMPGT16
, VIS1
, do_rdd
, a
, gen_helper_fcmpgt16
)
4883 TRANS(FPCMPEQ16
, VIS1
, do_rdd
, a
, gen_helper_fcmpeq16
)
4885 TRANS(FPCMPLE32
, VIS1
, do_rdd
, a
, gen_helper_fcmple32
)
4886 TRANS(FPCMPNE32
, VIS1
, do_rdd
, a
, gen_helper_fcmpne32
)
4887 TRANS(FPCMPGT32
, VIS1
, do_rdd
, a
, gen_helper_fcmpgt32
)
4888 TRANS(FPCMPEQ32
, VIS1
, do_rdd
, a
, gen_helper_fcmpeq32
)
4890 static bool do_env_ddd(DisasContext
*dc
, arg_r_r_r
*a
,
4891 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i64
, TCGv_i64
))
4893 TCGv_i64 dst
, src1
, src2
;
4895 if (gen_trap_ifnofpu(dc
)) {
4899 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4900 src1
= gen_load_fpr_D(dc
, a
->rs1
);
4901 src2
= gen_load_fpr_D(dc
, a
->rs2
);
4902 func(dst
, tcg_env
, src1
, src2
);
4903 gen_store_fpr_D(dc
, a
->rd
, dst
);
4904 return advance_pc(dc
);
4907 TRANS(FADDd
, ALL
, do_env_ddd
, a
, gen_helper_faddd
)
4908 TRANS(FSUBd
, ALL
, do_env_ddd
, a
, gen_helper_fsubd
)
4909 TRANS(FMULd
, ALL
, do_env_ddd
, a
, gen_helper_fmuld
)
4910 TRANS(FDIVd
, ALL
, do_env_ddd
, a
, gen_helper_fdivd
)
4912 static bool trans_FsMULd(DisasContext
*dc
, arg_r_r_r
*a
)
4915 TCGv_i32 src1
, src2
;
4917 if (gen_trap_ifnofpu(dc
)) {
4920 if (!(dc
->def
->features
& CPU_FEATURE_FSMULD
)) {
4921 return raise_unimpfpop(dc
);
4924 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4925 src1
= gen_load_fpr_F(dc
, a
->rs1
);
4926 src2
= gen_load_fpr_F(dc
, a
->rs2
);
4927 gen_helper_fsmuld(dst
, tcg_env
, src1
, src2
);
4928 gen_store_fpr_D(dc
, a
->rd
, dst
);
4929 return advance_pc(dc
);
4932 static bool do_dddd(DisasContext
*dc
, arg_r_r_r
*a
,
4933 void (*func
)(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_i64
))
4935 TCGv_i64 dst
, src0
, src1
, src2
;
4937 if (gen_trap_ifnofpu(dc
)) {
4941 dst
= gen_dest_fpr_D(dc
, a
->rd
);
4942 src0
= gen_load_fpr_D(dc
, a
->rd
);
4943 src1
= gen_load_fpr_D(dc
, a
->rs1
);
4944 src2
= gen_load_fpr_D(dc
, a
->rs2
);
4945 func(dst
, src0
, src1
, src2
);
4946 gen_store_fpr_D(dc
, a
->rd
, dst
);
4947 return advance_pc(dc
);
4950 TRANS(PDIST
, VIS1
, do_dddd
, a
, gen_helper_pdist
)
4952 static bool do_env_qqq(DisasContext
*dc
, arg_r_r_r
*a
,
4953 void (*func
)(TCGv_i128
, TCGv_env
, TCGv_i128
, TCGv_i128
))
4955 TCGv_i128 src1
, src2
;
4957 if (gen_trap_ifnofpu(dc
)) {
4960 if (gen_trap_float128(dc
)) {
4964 src1
= gen_load_fpr_Q(dc
, a
->rs1
);
4965 src2
= gen_load_fpr_Q(dc
, a
->rs2
);
4966 func(src1
, tcg_env
, src1
, src2
);
4967 gen_store_fpr_Q(dc
, a
->rd
, src1
);
4968 return advance_pc(dc
);
4971 TRANS(FADDq
, ALL
, do_env_qqq
, a
, gen_helper_faddq
)
4972 TRANS(FSUBq
, ALL
, do_env_qqq
, a
, gen_helper_fsubq
)
4973 TRANS(FMULq
, ALL
, do_env_qqq
, a
, gen_helper_fmulq
)
4974 TRANS(FDIVq
, ALL
, do_env_qqq
, a
, gen_helper_fdivq
)
4976 static bool trans_FdMULq(DisasContext
*dc
, arg_r_r_r
*a
)
4978 TCGv_i64 src1
, src2
;
4981 if (gen_trap_ifnofpu(dc
)) {
4984 if (gen_trap_float128(dc
)) {
4988 src1
= gen_load_fpr_D(dc
, a
->rs1
);
4989 src2
= gen_load_fpr_D(dc
, a
->rs2
);
4990 dst
= tcg_temp_new_i128();
4991 gen_helper_fdmulq(dst
, tcg_env
, src1
, src2
);
4992 gen_store_fpr_Q(dc
, a
->rd
, dst
);
4993 return advance_pc(dc
);
4996 static bool do_fmovr(DisasContext
*dc
, arg_FMOVRs
*a
, bool is_128
,
4997 void (*func
)(DisasContext
*, DisasCompare
*, int, int))
5001 if (!gen_compare_reg(&cmp
, a
->cond
, gen_load_gpr(dc
, a
->rs1
))) {
5004 if (gen_trap_ifnofpu(dc
)) {
5007 if (is_128
&& gen_trap_float128(dc
)) {
5011 gen_op_clear_ieee_excp_and_FTT();
5012 func(dc
, &cmp
, a
->rd
, a
->rs2
);
5013 return advance_pc(dc
);
5016 TRANS(FMOVRs
, 64, do_fmovr
, a
, false, gen_fmovs
)
5017 TRANS(FMOVRd
, 64, do_fmovr
, a
, false, gen_fmovd
)
5018 TRANS(FMOVRq
, 64, do_fmovr
, a
, true, gen_fmovq
)
5020 static bool do_fmovcc(DisasContext
*dc
, arg_FMOVscc
*a
, bool is_128
,
5021 void (*func
)(DisasContext
*, DisasCompare
*, int, int))
5025 if (gen_trap_ifnofpu(dc
)) {
5028 if (is_128
&& gen_trap_float128(dc
)) {
5032 gen_op_clear_ieee_excp_and_FTT();
5033 gen_compare(&cmp
, a
->cc
, a
->cond
, dc
);
5034 func(dc
, &cmp
, a
->rd
, a
->rs2
);
5035 return advance_pc(dc
);
5038 TRANS(FMOVscc
, 64, do_fmovcc
, a
, false, gen_fmovs
)
5039 TRANS(FMOVdcc
, 64, do_fmovcc
, a
, false, gen_fmovd
)
5040 TRANS(FMOVqcc
, 64, do_fmovcc
, a
, true, gen_fmovq
)
5042 static bool do_fmovfcc(DisasContext
*dc
, arg_FMOVsfcc
*a
, bool is_128
,
5043 void (*func
)(DisasContext
*, DisasCompare
*, int, int))
5047 if (gen_trap_ifnofpu(dc
)) {
5050 if (is_128
&& gen_trap_float128(dc
)) {
5054 gen_op_clear_ieee_excp_and_FTT();
5055 gen_fcompare(&cmp
, a
->cc
, a
->cond
);
5056 func(dc
, &cmp
, a
->rd
, a
->rs2
);
5057 return advance_pc(dc
);
5060 TRANS(FMOVsfcc
, 64, do_fmovfcc
, a
, false, gen_fmovs
)
5061 TRANS(FMOVdfcc
, 64, do_fmovfcc
, a
, false, gen_fmovd
)
5062 TRANS(FMOVqfcc
, 64, do_fmovfcc
, a
, true, gen_fmovq
)
5064 static bool do_fcmps(DisasContext
*dc
, arg_FCMPs
*a
, bool e
)
5066 TCGv_i32 src1
, src2
;
5068 if (avail_32(dc
) && a
->cc
!= 0) {
5071 if (gen_trap_ifnofpu(dc
)) {
5075 src1
= gen_load_fpr_F(dc
, a
->rs1
);
5076 src2
= gen_load_fpr_F(dc
, a
->rs2
);
5078 gen_op_fcmpes(a
->cc
, src1
, src2
);
5080 gen_op_fcmps(a
->cc
, src1
, src2
);
5082 return advance_pc(dc
);
5085 TRANS(FCMPs
, ALL
, do_fcmps
, a
, false)
5086 TRANS(FCMPEs
, ALL
, do_fcmps
, a
, true)
5088 static bool do_fcmpd(DisasContext
*dc
, arg_FCMPd
*a
, bool e
)
5090 TCGv_i64 src1
, src2
;
5092 if (avail_32(dc
) && a
->cc
!= 0) {
5095 if (gen_trap_ifnofpu(dc
)) {
5099 src1
= gen_load_fpr_D(dc
, a
->rs1
);
5100 src2
= gen_load_fpr_D(dc
, a
->rs2
);
5102 gen_op_fcmped(a
->cc
, src1
, src2
);
5104 gen_op_fcmpd(a
->cc
, src1
, src2
);
5106 return advance_pc(dc
);
5109 TRANS(FCMPd
, ALL
, do_fcmpd
, a
, false)
5110 TRANS(FCMPEd
, ALL
, do_fcmpd
, a
, true)
5112 static bool do_fcmpq(DisasContext
*dc
, arg_FCMPq
*a
, bool e
)
5114 TCGv_i128 src1
, src2
;
5116 if (avail_32(dc
) && a
->cc
!= 0) {
5119 if (gen_trap_ifnofpu(dc
)) {
5122 if (gen_trap_float128(dc
)) {
5126 src1
= gen_load_fpr_Q(dc
, a
->rs1
);
5127 src2
= gen_load_fpr_Q(dc
, a
->rs2
);
5129 gen_op_fcmpeq(a
->cc
, src1
, src2
);
5131 gen_op_fcmpq(a
->cc
, src1
, src2
);
5133 return advance_pc(dc
);
5136 TRANS(FCMPq
, ALL
, do_fcmpq
, a
, false)
5137 TRANS(FCMPEq
, ALL
, do_fcmpq
, a
, true)
5139 static void sparc_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
5141 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
5142 CPUSPARCState
*env
= cpu_env(cs
);
5145 dc
->pc
= dc
->base
.pc_first
;
5146 dc
->npc
= (target_ulong
)dc
->base
.tb
->cs_base
;
5147 dc
->mem_idx
= dc
->base
.tb
->flags
& TB_FLAG_MMU_MASK
;
5148 dc
->def
= &env
->def
;
5149 dc
->fpu_enabled
= tb_fpu_enabled(dc
->base
.tb
->flags
);
5150 dc
->address_mask_32bit
= tb_am_enabled(dc
->base
.tb
->flags
);
5151 #ifndef CONFIG_USER_ONLY
5152 dc
->supervisor
= (dc
->base
.tb
->flags
& TB_FLAG_SUPER
) != 0;
5154 #ifdef TARGET_SPARC64
5156 dc
->asi
= (dc
->base
.tb
->flags
>> TB_FLAG_ASI_SHIFT
) & 0xff;
5157 #ifndef CONFIG_USER_ONLY
5158 dc
->hypervisor
= (dc
->base
.tb
->flags
& TB_FLAG_HYPER
) != 0;
5162 * if we reach a page boundary, we stop generation so that the
5163 * PC of a TT_TFAULT exception is always in the right page
5165 bound
= -(dc
->base
.pc_first
| TARGET_PAGE_MASK
) / 4;
5166 dc
->base
.max_insns
= MIN(dc
->base
.max_insns
, bound
);
5169 static void sparc_tr_tb_start(DisasContextBase
*db
, CPUState
*cs
)
5173 static void sparc_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cs
)
5175 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
5176 target_ulong npc
= dc
->npc
;
5181 assert(dc
->jump_pc
[1] == dc
->pc
+ 4);
5182 npc
= dc
->jump_pc
[0] | JUMP_PC
;
5185 case DYNAMIC_PC_LOOKUP
:
5189 g_assert_not_reached();
5192 tcg_gen_insn_start(dc
->pc
, npc
);
5195 static void sparc_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cs
)
5197 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
5198 CPUSPARCState
*env
= cpu_env(cs
);
5201 insn
= translator_ldl(env
, &dc
->base
, dc
->pc
);
5202 dc
->base
.pc_next
+= 4;
5204 if (!decode(dc
, insn
)) {
5205 gen_exception(dc
, TT_ILL_INSN
);
5208 if (dc
->base
.is_jmp
== DISAS_NORETURN
) {
5211 if (dc
->pc
!= dc
->base
.pc_next
) {
5212 dc
->base
.is_jmp
= DISAS_TOO_MANY
;
5216 static void sparc_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cs
)
5218 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
5219 DisasDelayException
*e
, *e_next
;
5224 switch (dc
->base
.is_jmp
) {
5226 case DISAS_TOO_MANY
:
5227 if (((dc
->pc
| dc
->npc
) & 3) == 0) {
5228 /* static PC and NPC: we can use direct chaining */
5229 gen_goto_tb(dc
, 0, dc
->pc
, dc
->npc
);
5236 case DYNAMIC_PC_LOOKUP
:
5242 g_assert_not_reached();
5245 tcg_gen_movi_tl(cpu_pc
, dc
->pc
);
5251 gen_generic_branch(dc
);
5256 case DYNAMIC_PC_LOOKUP
:
5259 g_assert_not_reached();
5262 tcg_gen_movi_tl(cpu_npc
, dc
->npc
);
5265 tcg_gen_lookup_and_goto_ptr();
5267 tcg_gen_exit_tb(NULL
, 0);
5271 case DISAS_NORETURN
:
5277 tcg_gen_exit_tb(NULL
, 0);
5281 g_assert_not_reached();
5284 for (e
= dc
->delay_excp_list
; e
; e
= e_next
) {
5285 gen_set_label(e
->lab
);
5287 tcg_gen_movi_tl(cpu_pc
, e
->pc
);
5288 if (e
->npc
% 4 == 0) {
5289 tcg_gen_movi_tl(cpu_npc
, e
->npc
);
5291 gen_helper_raise_exception(tcg_env
, e
->excp
);
5298 static void sparc_tr_disas_log(const DisasContextBase
*dcbase
,
5299 CPUState
*cpu
, FILE *logfile
)
5301 fprintf(logfile
, "IN: %s\n", lookup_symbol(dcbase
->pc_first
));
5302 target_disas(logfile
, cpu
, dcbase
->pc_first
, dcbase
->tb
->size
);
5305 static const TranslatorOps sparc_tr_ops
= {
5306 .init_disas_context
= sparc_tr_init_disas_context
,
5307 .tb_start
= sparc_tr_tb_start
,
5308 .insn_start
= sparc_tr_insn_start
,
5309 .translate_insn
= sparc_tr_translate_insn
,
5310 .tb_stop
= sparc_tr_tb_stop
,
5311 .disas_log
= sparc_tr_disas_log
,
5314 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int *max_insns
,
5315 vaddr pc
, void *host_pc
)
5317 DisasContext dc
= {};
5319 translator_loop(cs
, tb
, max_insns
, pc
, host_pc
, &sparc_tr_ops
, &dc
.base
);
5322 void sparc_tcg_init(void)
5324 static const char gregnames
[32][4] = {
5325 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5326 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5327 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5328 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5330 static const char fregnames
[32][4] = {
5331 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5332 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5333 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5334 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5337 static const struct { TCGv
*ptr
; int off
; const char *name
; } rtl
[] = {
5338 #ifdef TARGET_SPARC64
5339 { &cpu_gsr
, offsetof(CPUSPARCState
, gsr
), "gsr" },
5340 { &cpu_xcc_Z
, offsetof(CPUSPARCState
, xcc_Z
), "xcc_Z" },
5341 { &cpu_xcc_C
, offsetof(CPUSPARCState
, xcc_C
), "xcc_C" },
5343 { &cpu_cc_N
, offsetof(CPUSPARCState
, cc_N
), "cc_N" },
5344 { &cpu_cc_V
, offsetof(CPUSPARCState
, cc_V
), "cc_V" },
5345 { &cpu_icc_Z
, offsetof(CPUSPARCState
, icc_Z
), "icc_Z" },
5346 { &cpu_icc_C
, offsetof(CPUSPARCState
, icc_C
), "icc_C" },
5347 { &cpu_cond
, offsetof(CPUSPARCState
, cond
), "cond" },
5348 { &cpu_pc
, offsetof(CPUSPARCState
, pc
), "pc" },
5349 { &cpu_npc
, offsetof(CPUSPARCState
, npc
), "npc" },
5350 { &cpu_y
, offsetof(CPUSPARCState
, y
), "y" },
5351 { &cpu_tbr
, offsetof(CPUSPARCState
, tbr
), "tbr" },
5356 cpu_regwptr
= tcg_global_mem_new_ptr(tcg_env
,
5357 offsetof(CPUSPARCState
, regwptr
),
5360 for (i
= 0; i
< ARRAY_SIZE(rtl
); ++i
) {
5361 *rtl
[i
].ptr
= tcg_global_mem_new(tcg_env
, rtl
[i
].off
, rtl
[i
].name
);
5365 for (i
= 1; i
< 8; ++i
) {
5366 cpu_regs
[i
] = tcg_global_mem_new(tcg_env
,
5367 offsetof(CPUSPARCState
, gregs
[i
]),
5371 for (i
= 8; i
< 32; ++i
) {
5372 cpu_regs
[i
] = tcg_global_mem_new(cpu_regwptr
,
5373 (i
- 8) * sizeof(target_ulong
),
5377 for (i
= 0; i
< TARGET_DPREGS
; i
++) {
5378 cpu_fpr
[i
] = tcg_global_mem_new_i64(tcg_env
,
5379 offsetof(CPUSPARCState
, fpr
[i
]),
5383 #ifdef TARGET_SPARC64
5384 cpu_fprs
= tcg_global_mem_new_i32(tcg_env
,
5385 offsetof(CPUSPARCState
, fprs
), "fprs");
5389 void sparc_restore_state_to_opc(CPUState
*cs
,
5390 const TranslationBlock
*tb
,
5391 const uint64_t *data
)
5393 SPARCCPU
*cpu
= SPARC_CPU(cs
);
5394 CPUSPARCState
*env
= &cpu
->env
;
5395 target_ulong pc
= data
[0];
5396 target_ulong npc
= data
[1];
5399 if (npc
== DYNAMIC_PC
) {
5400 /* dynamic NPC: already stored */
5401 } else if (npc
& JUMP_PC
) {
5402 /* jump PC: use 'cond' and the jump targets of the translation */
5404 env
->npc
= npc
& ~3;