2 * Alpha emulation cpu translation for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "disas/disas.h"
22 #include "qemu/host-utils.h"
24 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
29 #include "trace-tcg.h"
32 #undef ALPHA_DEBUG_DISAS
33 #define CONFIG_SOFTFLOAT_INLINE
35 #ifdef ALPHA_DEBUG_DISAS
36 # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
38 # define LOG_DISAS(...) do { } while (0)
41 typedef struct DisasContext DisasContext
;
43 struct TranslationBlock
*tb
;
47 /* Current rounding mode for this TB. */
49 /* Current flush-to-zero setting for this TB. */
52 /* implver value for this CPU. */
55 /* Temporaries for $31 and $f31 as source and destination. */
58 /* Temporary for immediate constants. */
61 bool singlestep_enabled
;
64 /* Return values from translate_one, indicating the state of the TB.
65 Note that zero indicates that we are not exiting the TB. */
70 /* We have emitted one or more goto_tb. No fixup required. */
73 /* We are not using a goto_tb (for whatever reason), but have updated
74 the PC (for whatever reason), so there's no need to do it again on
78 /* We are exiting the TB, but have neither emitted a goto_tb, nor
79 updated the PC for the next instruction to be executed. */
82 /* We are ending the TB with a noreturn function call, e.g. longjmp.
83 No following code will be executed. */
87 /* global register indexes */
88 static TCGv_ptr cpu_env
;
89 static TCGv cpu_ir
[31];
90 static TCGv cpu_fir
[31];
92 static TCGv cpu_lock_addr
;
93 static TCGv cpu_lock_st_addr
;
94 static TCGv cpu_lock_value
;
96 #include "exec/gen-icount.h"
98 void alpha_translate_init(void)
100 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
102 typedef struct { TCGv
*var
; const char *name
; int ofs
; } GlobalVar
;
103 static const GlobalVar vars
[] = {
106 DEF_VAR(lock_st_addr
),
112 /* Use the symbolic register names that match the disassembler. */
113 static const char greg_names
[31][4] = {
114 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
115 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
116 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
117 "t10", "t11", "ra", "t12", "at", "gp", "sp"
119 static const char freg_names
[31][4] = {
120 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
121 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
122 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
123 "f24", "f25", "f26", "f27", "f28", "f29", "f30"
126 static bool done_init
= 0;
134 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
136 for (i
= 0; i
< 31; i
++) {
137 cpu_ir
[i
] = tcg_global_mem_new_i64(TCG_AREG0
,
138 offsetof(CPUAlphaState
, ir
[i
]),
142 for (i
= 0; i
< 31; i
++) {
143 cpu_fir
[i
] = tcg_global_mem_new_i64(TCG_AREG0
,
144 offsetof(CPUAlphaState
, fir
[i
]),
148 for (i
= 0; i
< ARRAY_SIZE(vars
); ++i
) {
149 const GlobalVar
*v
= &vars
[i
];
150 *v
->var
= tcg_global_mem_new_i64(TCG_AREG0
, v
->ofs
, v
->name
);
154 static TCGv
load_zero(DisasContext
*ctx
)
156 if (TCGV_IS_UNUSED_I64(ctx
->zero
)) {
157 ctx
->zero
= tcg_const_i64(0);
162 static TCGv
dest_sink(DisasContext
*ctx
)
164 if (TCGV_IS_UNUSED_I64(ctx
->sink
)) {
165 ctx
->sink
= tcg_temp_new();
170 static TCGv
load_gpr(DisasContext
*ctx
, unsigned reg
)
172 if (likely(reg
< 31)) {
175 return load_zero(ctx
);
179 static TCGv
load_gpr_lit(DisasContext
*ctx
, unsigned reg
,
180 uint8_t lit
, bool islit
)
183 ctx
->lit
= tcg_const_i64(lit
);
185 } else if (likely(reg
< 31)) {
188 return load_zero(ctx
);
192 static TCGv
dest_gpr(DisasContext
*ctx
, unsigned reg
)
194 if (likely(reg
< 31)) {
197 return dest_sink(ctx
);
201 static TCGv
load_fpr(DisasContext
*ctx
, unsigned reg
)
203 if (likely(reg
< 31)) {
206 return load_zero(ctx
);
210 static TCGv
dest_fpr(DisasContext
*ctx
, unsigned reg
)
212 if (likely(reg
< 31)) {
215 return dest_sink(ctx
);
219 static void gen_excp_1(int exception
, int error_code
)
223 tmp1
= tcg_const_i32(exception
);
224 tmp2
= tcg_const_i32(error_code
);
225 gen_helper_excp(cpu_env
, tmp1
, tmp2
);
226 tcg_temp_free_i32(tmp2
);
227 tcg_temp_free_i32(tmp1
);
230 static ExitStatus
gen_excp(DisasContext
*ctx
, int exception
, int error_code
)
232 tcg_gen_movi_i64(cpu_pc
, ctx
->pc
);
233 gen_excp_1(exception
, error_code
);
234 return EXIT_NORETURN
;
237 static inline ExitStatus
gen_invalid(DisasContext
*ctx
)
239 return gen_excp(ctx
, EXCP_OPCDEC
, 0);
242 static inline void gen_qemu_ldf(TCGv t0
, TCGv t1
, int flags
)
244 TCGv_i32 tmp32
= tcg_temp_new_i32();
245 tcg_gen_qemu_ld_i32(tmp32
, t1
, flags
, MO_LEUL
);
246 gen_helper_memory_to_f(t0
, tmp32
);
247 tcg_temp_free_i32(tmp32
);
250 static inline void gen_qemu_ldg(TCGv t0
, TCGv t1
, int flags
)
252 TCGv tmp
= tcg_temp_new();
253 tcg_gen_qemu_ld_i64(tmp
, t1
, flags
, MO_LEQ
);
254 gen_helper_memory_to_g(t0
, tmp
);
258 static inline void gen_qemu_lds(TCGv t0
, TCGv t1
, int flags
)
260 TCGv_i32 tmp32
= tcg_temp_new_i32();
261 tcg_gen_qemu_ld_i32(tmp32
, t1
, flags
, MO_LEUL
);
262 gen_helper_memory_to_s(t0
, tmp32
);
263 tcg_temp_free_i32(tmp32
);
266 static inline void gen_qemu_ldl_l(TCGv t0
, TCGv t1
, int flags
)
268 tcg_gen_qemu_ld_i64(t0
, t1
, flags
, MO_LESL
);
269 tcg_gen_mov_i64(cpu_lock_addr
, t1
);
270 tcg_gen_mov_i64(cpu_lock_value
, t0
);
273 static inline void gen_qemu_ldq_l(TCGv t0
, TCGv t1
, int flags
)
275 tcg_gen_qemu_ld_i64(t0
, t1
, flags
, MO_LEQ
);
276 tcg_gen_mov_i64(cpu_lock_addr
, t1
);
277 tcg_gen_mov_i64(cpu_lock_value
, t0
);
280 static inline void gen_load_mem(DisasContext
*ctx
,
281 void (*tcg_gen_qemu_load
)(TCGv t0
, TCGv t1
,
283 int ra
, int rb
, int32_t disp16
, bool fp
,
288 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
289 prefetches, which we can treat as nops. No worries about
290 missed exceptions here. */
291 if (unlikely(ra
== 31)) {
295 tmp
= tcg_temp_new();
296 addr
= load_gpr(ctx
, rb
);
299 tcg_gen_addi_i64(tmp
, addr
, disp16
);
303 tcg_gen_andi_i64(tmp
, addr
, ~0x7);
307 va
= (fp
? cpu_fir
[ra
] : cpu_ir
[ra
]);
308 tcg_gen_qemu_load(va
, addr
, ctx
->mem_idx
);
313 static inline void gen_qemu_stf(TCGv t0
, TCGv t1
, int flags
)
315 TCGv_i32 tmp32
= tcg_temp_new_i32();
316 gen_helper_f_to_memory(tmp32
, t0
);
317 tcg_gen_qemu_st_i32(tmp32
, t1
, flags
, MO_LEUL
);
318 tcg_temp_free_i32(tmp32
);
321 static inline void gen_qemu_stg(TCGv t0
, TCGv t1
, int flags
)
323 TCGv tmp
= tcg_temp_new();
324 gen_helper_g_to_memory(tmp
, t0
);
325 tcg_gen_qemu_st_i64(tmp
, t1
, flags
, MO_LEQ
);
329 static inline void gen_qemu_sts(TCGv t0
, TCGv t1
, int flags
)
331 TCGv_i32 tmp32
= tcg_temp_new_i32();
332 gen_helper_s_to_memory(tmp32
, t0
);
333 tcg_gen_qemu_st_i32(tmp32
, t1
, flags
, MO_LEUL
);
334 tcg_temp_free_i32(tmp32
);
337 static inline void gen_store_mem(DisasContext
*ctx
,
338 void (*tcg_gen_qemu_store
)(TCGv t0
, TCGv t1
,
340 int ra
, int rb
, int32_t disp16
, bool fp
,
345 tmp
= tcg_temp_new();
346 addr
= load_gpr(ctx
, rb
);
349 tcg_gen_addi_i64(tmp
, addr
, disp16
);
353 tcg_gen_andi_i64(tmp
, addr
, ~0x7);
357 va
= (fp
? load_fpr(ctx
, ra
) : load_gpr(ctx
, ra
));
358 tcg_gen_qemu_store(va
, addr
, ctx
->mem_idx
);
363 static ExitStatus
gen_store_conditional(DisasContext
*ctx
, int ra
, int rb
,
364 int32_t disp16
, int quad
)
369 /* ??? Don't bother storing anything. The user can't tell
370 the difference, since the zero register always reads zero. */
374 #if defined(CONFIG_USER_ONLY)
375 addr
= cpu_lock_st_addr
;
377 addr
= tcg_temp_local_new();
380 tcg_gen_addi_i64(addr
, load_gpr(ctx
, rb
), disp16
);
382 #if defined(CONFIG_USER_ONLY)
383 /* ??? This is handled via a complicated version of compare-and-swap
384 in the cpu_loop. Hopefully one day we'll have a real CAS opcode
385 in TCG so that this isn't necessary. */
386 return gen_excp(ctx
, quad
? EXCP_STQ_C
: EXCP_STL_C
, ra
);
388 /* ??? In system mode we are never multi-threaded, so CAS can be
389 implemented via a non-atomic load-compare-store sequence. */
391 TCGLabel
*lab_fail
, *lab_done
;
394 lab_fail
= gen_new_label();
395 lab_done
= gen_new_label();
396 tcg_gen_brcond_i64(TCG_COND_NE
, addr
, cpu_lock_addr
, lab_fail
);
398 val
= tcg_temp_new();
399 tcg_gen_qemu_ld_i64(val
, addr
, ctx
->mem_idx
, quad
? MO_LEQ
: MO_LESL
);
400 tcg_gen_brcond_i64(TCG_COND_NE
, val
, cpu_lock_value
, lab_fail
);
402 tcg_gen_qemu_st_i64(cpu_ir
[ra
], addr
, ctx
->mem_idx
,
403 quad
? MO_LEQ
: MO_LEUL
);
404 tcg_gen_movi_i64(cpu_ir
[ra
], 1);
405 tcg_gen_br(lab_done
);
407 gen_set_label(lab_fail
);
408 tcg_gen_movi_i64(cpu_ir
[ra
], 0);
410 gen_set_label(lab_done
);
411 tcg_gen_movi_i64(cpu_lock_addr
, -1);
419 static bool in_superpage(DisasContext
*ctx
, int64_t addr
)
421 return ((ctx
->tb
->flags
& TB_FLAGS_USER_MODE
) == 0
423 && ((addr
>> 41) & 3) == 2
424 && addr
>> TARGET_VIRT_ADDR_SPACE_BITS
== addr
>> 63);
427 static bool use_goto_tb(DisasContext
*ctx
, uint64_t dest
)
429 /* Suppress goto_tb in the case of single-steping and IO. */
430 if ((ctx
->tb
->cflags
& CF_LAST_IO
)
431 || ctx
->singlestep_enabled
|| singlestep
) {
434 /* If the destination is in the superpage, the page perms can't change. */
435 if (in_superpage(ctx
, dest
)) {
438 /* Check for the dest on the same page as the start of the TB. */
439 return ((ctx
->tb
->pc
^ dest
) & TARGET_PAGE_MASK
) == 0;
442 static ExitStatus
gen_bdirect(DisasContext
*ctx
, int ra
, int32_t disp
)
444 uint64_t dest
= ctx
->pc
+ (disp
<< 2);
447 tcg_gen_movi_i64(cpu_ir
[ra
], ctx
->pc
);
450 /* Notice branch-to-next; used to initialize RA with the PC. */
453 } else if (use_goto_tb(ctx
, dest
)) {
455 tcg_gen_movi_i64(cpu_pc
, dest
);
456 tcg_gen_exit_tb((uintptr_t)ctx
->tb
);
459 tcg_gen_movi_i64(cpu_pc
, dest
);
460 return EXIT_PC_UPDATED
;
464 static ExitStatus
gen_bcond_internal(DisasContext
*ctx
, TCGCond cond
,
465 TCGv cmp
, int32_t disp
)
467 uint64_t dest
= ctx
->pc
+ (disp
<< 2);
468 TCGLabel
*lab_true
= gen_new_label();
470 if (use_goto_tb(ctx
, dest
)) {
471 tcg_gen_brcondi_i64(cond
, cmp
, 0, lab_true
);
474 tcg_gen_movi_i64(cpu_pc
, ctx
->pc
);
475 tcg_gen_exit_tb((uintptr_t)ctx
->tb
);
477 gen_set_label(lab_true
);
479 tcg_gen_movi_i64(cpu_pc
, dest
);
480 tcg_gen_exit_tb((uintptr_t)ctx
->tb
+ 1);
484 TCGv_i64 z
= tcg_const_i64(0);
485 TCGv_i64 d
= tcg_const_i64(dest
);
486 TCGv_i64 p
= tcg_const_i64(ctx
->pc
);
488 tcg_gen_movcond_i64(cond
, cpu_pc
, cmp
, z
, d
, p
);
490 tcg_temp_free_i64(z
);
491 tcg_temp_free_i64(d
);
492 tcg_temp_free_i64(p
);
493 return EXIT_PC_UPDATED
;
497 static ExitStatus
gen_bcond(DisasContext
*ctx
, TCGCond cond
, int ra
,
498 int32_t disp
, int mask
)
503 cmp_tmp
= tcg_temp_new();
504 tcg_gen_andi_i64(cmp_tmp
, load_gpr(ctx
, ra
), 1);
506 cmp_tmp
= load_gpr(ctx
, ra
);
509 return gen_bcond_internal(ctx
, cond
, cmp_tmp
, disp
);
512 /* Fold -0.0 for comparison with COND. */
514 static void gen_fold_mzero(TCGCond cond
, TCGv dest
, TCGv src
)
516 uint64_t mzero
= 1ull << 63;
521 /* For <= or >, the -0.0 value directly compares the way we want. */
522 tcg_gen_mov_i64(dest
, src
);
527 /* For == or !=, we can simply mask off the sign bit and compare. */
528 tcg_gen_andi_i64(dest
, src
, mzero
- 1);
533 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
534 tcg_gen_setcondi_i64(TCG_COND_NE
, dest
, src
, mzero
);
535 tcg_gen_neg_i64(dest
, dest
);
536 tcg_gen_and_i64(dest
, dest
, src
);
544 static ExitStatus
gen_fbcond(DisasContext
*ctx
, TCGCond cond
, int ra
,
547 TCGv cmp_tmp
= tcg_temp_new();
548 gen_fold_mzero(cond
, cmp_tmp
, load_fpr(ctx
, ra
));
549 return gen_bcond_internal(ctx
, cond
, cmp_tmp
, disp
);
552 static void gen_fcmov(DisasContext
*ctx
, TCGCond cond
, int ra
, int rb
, int rc
)
557 vb
= load_fpr(ctx
, rb
);
559 gen_fold_mzero(cond
, va
, load_fpr(ctx
, ra
));
561 tcg_gen_movcond_i64(cond
, dest_fpr(ctx
, rc
), va
, z
, vb
, load_fpr(ctx
, rc
));
566 #define QUAL_RM_N 0x080 /* Round mode nearest even */
567 #define QUAL_RM_C 0x000 /* Round mode chopped */
568 #define QUAL_RM_M 0x040 /* Round mode minus infinity */
569 #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
570 #define QUAL_RM_MASK 0x0c0
572 #define QUAL_U 0x100 /* Underflow enable (fp output) */
573 #define QUAL_V 0x100 /* Overflow enable (int output) */
574 #define QUAL_S 0x400 /* Software completion enable */
575 #define QUAL_I 0x200 /* Inexact detection enable */
577 static void gen_qual_roundmode(DisasContext
*ctx
, int fn11
)
581 fn11
&= QUAL_RM_MASK
;
582 if (fn11
== ctx
->tb_rm
) {
587 tmp
= tcg_temp_new_i32();
590 tcg_gen_movi_i32(tmp
, float_round_nearest_even
);
593 tcg_gen_movi_i32(tmp
, float_round_to_zero
);
596 tcg_gen_movi_i32(tmp
, float_round_down
);
599 tcg_gen_ld8u_i32(tmp
, cpu_env
,
600 offsetof(CPUAlphaState
, fpcr_dyn_round
));
604 #if defined(CONFIG_SOFTFLOAT_INLINE)
605 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
606 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
607 sets the one field. */
608 tcg_gen_st8_i32(tmp
, cpu_env
,
609 offsetof(CPUAlphaState
, fp_status
.float_rounding_mode
));
611 gen_helper_setroundmode(tmp
);
614 tcg_temp_free_i32(tmp
);
617 static void gen_qual_flushzero(DisasContext
*ctx
, int fn11
)
622 if (fn11
== ctx
->tb_ftz
) {
627 tmp
= tcg_temp_new_i32();
629 /* Underflow is enabled, use the FPCR setting. */
630 tcg_gen_ld8u_i32(tmp
, cpu_env
,
631 offsetof(CPUAlphaState
, fpcr_flush_to_zero
));
633 /* Underflow is disabled, force flush-to-zero. */
634 tcg_gen_movi_i32(tmp
, 1);
637 #if defined(CONFIG_SOFTFLOAT_INLINE)
638 tcg_gen_st8_i32(tmp
, cpu_env
,
639 offsetof(CPUAlphaState
, fp_status
.flush_to_zero
));
641 gen_helper_setflushzero(tmp
);
644 tcg_temp_free_i32(tmp
);
647 static TCGv
gen_ieee_input(DisasContext
*ctx
, int reg
, int fn11
, int is_cmp
)
651 if (unlikely(reg
== 31)) {
652 val
= load_zero(ctx
);
655 if ((fn11
& QUAL_S
) == 0) {
657 gen_helper_ieee_input_cmp(cpu_env
, val
);
659 gen_helper_ieee_input(cpu_env
, val
);
666 static void gen_fp_exc_clear(void)
668 #if defined(CONFIG_SOFTFLOAT_INLINE)
669 TCGv_i32 zero
= tcg_const_i32(0);
670 tcg_gen_st8_i32(zero
, cpu_env
,
671 offsetof(CPUAlphaState
, fp_status
.float_exception_flags
));
672 tcg_temp_free_i32(zero
);
674 gen_helper_fp_exc_clear(cpu_env
);
678 static void gen_fp_exc_raise_ignore(int rc
, int fn11
, int ignore
)
680 /* ??? We ought to be able to do something with imprecise exceptions.
681 E.g. notice we're still in the trap shadow of something within the
682 TB and do not generate the code to signal the exception; end the TB
683 when an exception is forced to arrive, either by consumption of a
684 register value or TRAPB or EXCB. */
685 TCGv_i32 exc
= tcg_temp_new_i32();
688 #if defined(CONFIG_SOFTFLOAT_INLINE)
689 tcg_gen_ld8u_i32(exc
, cpu_env
,
690 offsetof(CPUAlphaState
, fp_status
.float_exception_flags
));
692 gen_helper_fp_exc_get(exc
, cpu_env
);
696 tcg_gen_andi_i32(exc
, exc
, ~ignore
);
699 /* ??? Pass in the regno of the destination so that the helper can
700 set EXC_MASK, which contains a bitmask of destination registers
701 that have caused arithmetic traps. A simple userspace emulation
702 does not require this. We do need it for a guest kernel's entArith,
703 or if we were to do something clever with imprecise exceptions. */
704 reg
= tcg_const_i32(rc
+ 32);
707 gen_helper_fp_exc_raise_s(cpu_env
, exc
, reg
);
709 gen_helper_fp_exc_raise(cpu_env
, exc
, reg
);
712 tcg_temp_free_i32(reg
);
713 tcg_temp_free_i32(exc
);
716 static inline void gen_fp_exc_raise(int rc
, int fn11
)
718 gen_fp_exc_raise_ignore(rc
, fn11
, fn11
& QUAL_I
? 0 : float_flag_inexact
);
721 static void gen_fcvtlq(TCGv vc
, TCGv vb
)
723 TCGv tmp
= tcg_temp_new();
725 /* The arithmetic right shift here, plus the sign-extended mask below
726 yields a sign-extended result without an explicit ext32s_i64. */
727 tcg_gen_sari_i64(tmp
, vb
, 32);
728 tcg_gen_shri_i64(vc
, vb
, 29);
729 tcg_gen_andi_i64(tmp
, tmp
, (int32_t)0xc0000000);
730 tcg_gen_andi_i64(vc
, vc
, 0x3fffffff);
731 tcg_gen_or_i64(vc
, vc
, tmp
);
736 static void gen_fcvtql(TCGv vc
, TCGv vb
)
738 TCGv tmp
= tcg_temp_new();
740 tcg_gen_andi_i64(tmp
, vb
, (int32_t)0xc0000000);
741 tcg_gen_andi_i64(vc
, vb
, 0x3FFFFFFF);
742 tcg_gen_shli_i64(tmp
, tmp
, 32);
743 tcg_gen_shli_i64(vc
, vc
, 29);
744 tcg_gen_or_i64(vc
, vc
, tmp
);
749 static void gen_ieee_arith2(DisasContext
*ctx
,
750 void (*helper
)(TCGv
, TCGv_ptr
, TCGv
),
751 int rb
, int rc
, int fn11
)
755 gen_qual_roundmode(ctx
, fn11
);
756 gen_qual_flushzero(ctx
, fn11
);
759 vb
= gen_ieee_input(ctx
, rb
, fn11
, 0);
760 helper(dest_fpr(ctx
, rc
), cpu_env
, vb
);
762 gen_fp_exc_raise(rc
, fn11
);
765 #define IEEE_ARITH2(name) \
766 static inline void glue(gen_f, name)(DisasContext *ctx, \
767 int rb, int rc, int fn11) \
769 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
776 static void gen_fcvttq(DisasContext
*ctx
, int rb
, int rc
, int fn11
)
781 /* No need to set flushzero, since we have an integer output. */
783 vb
= gen_ieee_input(ctx
, rb
, fn11
, 0);
784 vc
= dest_fpr(ctx
, rc
);
786 /* Almost all integer conversions use cropped rounding, and most
787 also do not have integer overflow enabled. Special case that. */
790 gen_helper_cvttq_c(vc
, cpu_env
, vb
);
792 case QUAL_V
| QUAL_RM_C
:
793 case QUAL_S
| QUAL_V
| QUAL_RM_C
:
794 ignore
= float_flag_inexact
;
796 case QUAL_S
| QUAL_V
| QUAL_I
| QUAL_RM_C
:
797 gen_helper_cvttq_svic(vc
, cpu_env
, vb
);
800 gen_qual_roundmode(ctx
, fn11
);
801 gen_helper_cvttq(vc
, cpu_env
, vb
);
802 ignore
|= (fn11
& QUAL_V
? 0 : float_flag_overflow
);
803 ignore
|= (fn11
& QUAL_I
? 0 : float_flag_inexact
);
807 gen_fp_exc_raise_ignore(rc
, fn11
, ignore
);
810 static void gen_ieee_intcvt(DisasContext
*ctx
,
811 void (*helper
)(TCGv
, TCGv_ptr
, TCGv
),
812 int rb
, int rc
, int fn11
)
816 gen_qual_roundmode(ctx
, fn11
);
817 vb
= load_fpr(ctx
, rb
);
818 vc
= dest_fpr(ctx
, rc
);
820 /* The only exception that can be raised by integer conversion
821 is inexact. Thus we only need to worry about exceptions when
822 inexact handling is requested. */
825 helper(vc
, cpu_env
, vb
);
826 gen_fp_exc_raise(rc
, fn11
);
828 helper(vc
, cpu_env
, vb
);
832 #define IEEE_INTCVT(name) \
833 static inline void glue(gen_f, name)(DisasContext *ctx, \
834 int rb, int rc, int fn11) \
836 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
841 static void gen_cpy_mask(TCGv vc
, TCGv va
, TCGv vb
, bool inv_a
, uint64_t mask
)
843 TCGv vmask
= tcg_const_i64(mask
);
844 TCGv tmp
= tcg_temp_new_i64();
847 tcg_gen_andc_i64(tmp
, vmask
, va
);
849 tcg_gen_and_i64(tmp
, va
, vmask
);
852 tcg_gen_andc_i64(vc
, vb
, vmask
);
853 tcg_gen_or_i64(vc
, vc
, tmp
);
855 tcg_temp_free(vmask
);
859 static void gen_ieee_arith3(DisasContext
*ctx
,
860 void (*helper
)(TCGv
, TCGv_ptr
, TCGv
, TCGv
),
861 int ra
, int rb
, int rc
, int fn11
)
865 gen_qual_roundmode(ctx
, fn11
);
866 gen_qual_flushzero(ctx
, fn11
);
869 va
= gen_ieee_input(ctx
, ra
, fn11
, 0);
870 vb
= gen_ieee_input(ctx
, rb
, fn11
, 0);
871 vc
= dest_fpr(ctx
, rc
);
872 helper(vc
, cpu_env
, va
, vb
);
874 gen_fp_exc_raise(rc
, fn11
);
877 #define IEEE_ARITH3(name) \
878 static inline void glue(gen_f, name)(DisasContext *ctx, \
879 int ra, int rb, int rc, int fn11) \
881 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
892 static void gen_ieee_compare(DisasContext
*ctx
,
893 void (*helper
)(TCGv
, TCGv_ptr
, TCGv
, TCGv
),
894 int ra
, int rb
, int rc
, int fn11
)
900 va
= gen_ieee_input(ctx
, ra
, fn11
, 1);
901 vb
= gen_ieee_input(ctx
, rb
, fn11
, 1);
902 vc
= dest_fpr(ctx
, rc
);
903 helper(vc
, cpu_env
, va
, vb
);
905 gen_fp_exc_raise(rc
, fn11
);
908 #define IEEE_CMP3(name) \
909 static inline void glue(gen_f, name)(DisasContext *ctx, \
910 int ra, int rb, int rc, int fn11) \
912 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
919 static inline uint64_t zapnot_mask(uint8_t lit
)
924 for (i
= 0; i
< 8; ++i
) {
925 if ((lit
>> i
) & 1) {
926 mask
|= 0xffull
<< (i
* 8);
932 /* Implement zapnot with an immediate operand, which expands to some
933 form of immediate AND. This is a basic building block in the
934 definition of many of the other byte manipulation instructions. */
935 static void gen_zapnoti(TCGv dest
, TCGv src
, uint8_t lit
)
939 tcg_gen_movi_i64(dest
, 0);
942 tcg_gen_ext8u_i64(dest
, src
);
945 tcg_gen_ext16u_i64(dest
, src
);
948 tcg_gen_ext32u_i64(dest
, src
);
951 tcg_gen_mov_i64(dest
, src
);
954 tcg_gen_andi_i64(dest
, src
, zapnot_mask(lit
));
959 /* EXTWH, EXTLH, EXTQH */
960 static void gen_ext_h(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
961 uint8_t lit
, uint8_t byte_mask
)
964 tcg_gen_shli_i64(vc
, va
, (64 - lit
* 8) & 0x3f);
966 TCGv tmp
= tcg_temp_new();
967 tcg_gen_shli_i64(tmp
, load_gpr(ctx
, rb
), 3);
968 tcg_gen_neg_i64(tmp
, tmp
);
969 tcg_gen_andi_i64(tmp
, tmp
, 0x3f);
970 tcg_gen_shl_i64(vc
, va
, tmp
);
973 gen_zapnoti(vc
, vc
, byte_mask
);
976 /* EXTBL, EXTWL, EXTLL, EXTQL */
977 static void gen_ext_l(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
978 uint8_t lit
, uint8_t byte_mask
)
981 tcg_gen_shri_i64(vc
, va
, (lit
& 7) * 8);
983 TCGv tmp
= tcg_temp_new();
984 tcg_gen_andi_i64(tmp
, load_gpr(ctx
, rb
), 7);
985 tcg_gen_shli_i64(tmp
, tmp
, 3);
986 tcg_gen_shr_i64(vc
, va
, tmp
);
989 gen_zapnoti(vc
, vc
, byte_mask
);
992 /* INSWH, INSLH, INSQH */
993 static void gen_ins_h(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
994 uint8_t lit
, uint8_t byte_mask
)
996 TCGv tmp
= tcg_temp_new();
998 /* The instruction description has us left-shift the byte mask and extract
999 bits <15:8> and apply that zap at the end. This is equivalent to simply
1000 performing the zap first and shifting afterward. */
1001 gen_zapnoti(tmp
, va
, byte_mask
);
1005 if (unlikely(lit
== 0)) {
1006 tcg_gen_movi_i64(vc
, 0);
1008 tcg_gen_shri_i64(vc
, tmp
, 64 - lit
* 8);
1011 TCGv shift
= tcg_temp_new();
1013 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
1014 portably by splitting the shift into two parts: shift_count-1 and 1.
1015 Arrange for the -1 by using ones-complement instead of
1016 twos-complement in the negation: ~(B * 8) & 63. */
1018 tcg_gen_shli_i64(shift
, load_gpr(ctx
, rb
), 3);
1019 tcg_gen_not_i64(shift
, shift
);
1020 tcg_gen_andi_i64(shift
, shift
, 0x3f);
1022 tcg_gen_shr_i64(vc
, tmp
, shift
);
1023 tcg_gen_shri_i64(vc
, vc
, 1);
1024 tcg_temp_free(shift
);
1029 /* INSBL, INSWL, INSLL, INSQL */
1030 static void gen_ins_l(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
1031 uint8_t lit
, uint8_t byte_mask
)
1033 TCGv tmp
= tcg_temp_new();
1035 /* The instruction description has us left-shift the byte mask
1036 the same number of byte slots as the data and apply the zap
1037 at the end. This is equivalent to simply performing the zap
1038 first and shifting afterward. */
1039 gen_zapnoti(tmp
, va
, byte_mask
);
1042 tcg_gen_shli_i64(vc
, tmp
, (lit
& 7) * 8);
1044 TCGv shift
= tcg_temp_new();
1045 tcg_gen_andi_i64(shift
, load_gpr(ctx
, rb
), 7);
1046 tcg_gen_shli_i64(shift
, shift
, 3);
1047 tcg_gen_shl_i64(vc
, tmp
, shift
);
1048 tcg_temp_free(shift
);
1053 /* MSKWH, MSKLH, MSKQH */
1054 static void gen_msk_h(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
1055 uint8_t lit
, uint8_t byte_mask
)
1058 gen_zapnoti(vc
, va
, ~((byte_mask
<< (lit
& 7)) >> 8));
1060 TCGv shift
= tcg_temp_new();
1061 TCGv mask
= tcg_temp_new();
1063 /* The instruction description is as above, where the byte_mask
1064 is shifted left, and then we extract bits <15:8>. This can be
1065 emulated with a right-shift on the expanded byte mask. This
1066 requires extra care because for an input <2:0> == 0 we need a
1067 shift of 64 bits in order to generate a zero. This is done by
1068 splitting the shift into two parts, the variable shift - 1
1069 followed by a constant 1 shift. The code we expand below is
1070 equivalent to ~(B * 8) & 63. */
1072 tcg_gen_shli_i64(shift
, load_gpr(ctx
, rb
), 3);
1073 tcg_gen_not_i64(shift
, shift
);
1074 tcg_gen_andi_i64(shift
, shift
, 0x3f);
1075 tcg_gen_movi_i64(mask
, zapnot_mask (byte_mask
));
1076 tcg_gen_shr_i64(mask
, mask
, shift
);
1077 tcg_gen_shri_i64(mask
, mask
, 1);
1079 tcg_gen_andc_i64(vc
, va
, mask
);
1081 tcg_temp_free(mask
);
1082 tcg_temp_free(shift
);
1086 /* MSKBL, MSKWL, MSKLL, MSKQL */
1087 static void gen_msk_l(DisasContext
*ctx
, TCGv vc
, TCGv va
, int rb
, bool islit
,
1088 uint8_t lit
, uint8_t byte_mask
)
1091 gen_zapnoti(vc
, va
, ~(byte_mask
<< (lit
& 7)));
1093 TCGv shift
= tcg_temp_new();
1094 TCGv mask
= tcg_temp_new();
1096 tcg_gen_andi_i64(shift
, load_gpr(ctx
, rb
), 7);
1097 tcg_gen_shli_i64(shift
, shift
, 3);
1098 tcg_gen_movi_i64(mask
, zapnot_mask(byte_mask
));
1099 tcg_gen_shl_i64(mask
, mask
, shift
);
1101 tcg_gen_andc_i64(vc
, va
, mask
);
1103 tcg_temp_free(mask
);
1104 tcg_temp_free(shift
);
1108 static void gen_rx(int ra
, int set
)
1113 tcg_gen_ld8u_i64(cpu_ir
[ra
], cpu_env
, offsetof(CPUAlphaState
, intr_flag
));
1116 tmp
= tcg_const_i32(set
);
1117 tcg_gen_st8_i32(tmp
, cpu_env
, offsetof(CPUAlphaState
, intr_flag
));
1118 tcg_temp_free_i32(tmp
);
1121 static ExitStatus
gen_call_pal(DisasContext
*ctx
, int palcode
)
1123 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1124 to internal cpu registers. */
1126 /* Unprivileged PAL call */
1127 if (palcode
>= 0x80 && palcode
< 0xC0) {
1131 /* No-op inside QEMU. */
1135 tcg_gen_ld_i64(cpu_ir
[IR_V0
], cpu_env
,
1136 offsetof(CPUAlphaState
, unique
));
1140 tcg_gen_st_i64(cpu_ir
[IR_A0
], cpu_env
,
1141 offsetof(CPUAlphaState
, unique
));
1150 #ifndef CONFIG_USER_ONLY
1151 /* Privileged PAL code */
1152 if (palcode
< 0x40 && (ctx
->tb
->flags
& TB_FLAGS_USER_MODE
) == 0) {
1156 /* No-op inside QEMU. */
1160 /* No-op inside QEMU. */
1164 tcg_gen_st_i64(cpu_ir
[IR_A0
], cpu_env
,
1165 offsetof(CPUAlphaState
, vptptr
));
1169 tcg_gen_st_i64(cpu_ir
[IR_A0
], cpu_env
,
1170 offsetof(CPUAlphaState
, sysval
));
1174 tcg_gen_ld_i64(cpu_ir
[IR_V0
], cpu_env
,
1175 offsetof(CPUAlphaState
, sysval
));
1182 /* Note that we already know we're in kernel mode, so we know
1183 that PS only contains the 3 IPL bits. */
1184 tcg_gen_ld8u_i64(cpu_ir
[IR_V0
], cpu_env
,
1185 offsetof(CPUAlphaState
, ps
));
1187 /* But make sure and store only the 3 IPL bits from the user. */
1188 tmp
= tcg_temp_new();
1189 tcg_gen_andi_i64(tmp
, cpu_ir
[IR_A0
], PS_INT_MASK
);
1190 tcg_gen_st8_i64(tmp
, cpu_env
, offsetof(CPUAlphaState
, ps
));
1197 tcg_gen_ld8u_i64(cpu_ir
[IR_V0
], cpu_env
,
1198 offsetof(CPUAlphaState
, ps
));
1202 tcg_gen_st_i64(cpu_ir
[IR_A0
], cpu_env
,
1203 offsetof(CPUAlphaState
, usp
));
1207 tcg_gen_ld_i64(cpu_ir
[IR_V0
], cpu_env
,
1208 offsetof(CPUAlphaState
, usp
));
1212 tcg_gen_ld32s_i64(cpu_ir
[IR_V0
], cpu_env
,
1213 -offsetof(AlphaCPU
, env
) + offsetof(CPUState
, cpu_index
));
1223 return gen_invalid(ctx
);
1226 #ifdef CONFIG_USER_ONLY
1227 return gen_excp(ctx
, EXCP_CALL_PAL
, palcode
);
1230 TCGv pc
= tcg_const_i64(ctx
->pc
);
1231 TCGv entry
= tcg_const_i64(palcode
& 0x80
1232 ? 0x2000 + (palcode
- 0x80) * 64
1233 : 0x1000 + palcode
* 64);
1235 gen_helper_call_pal(cpu_env
, pc
, entry
);
1237 tcg_temp_free(entry
);
1240 /* Since the destination is running in PALmode, we don't really
1241 need the page permissions check. We'll see the existence of
1242 the page when we create the TB, and we'll flush all TBs if
1243 we change the PAL base register. */
1244 if (!ctx
->singlestep_enabled
&& !(ctx
->tb
->cflags
& CF_LAST_IO
)) {
1246 tcg_gen_exit_tb((uintptr_t)ctx
->tb
);
1247 return EXIT_GOTO_TB
;
1250 return EXIT_PC_UPDATED
;
1255 #ifndef CONFIG_USER_ONLY
1257 #define PR_BYTE 0x100000
1258 #define PR_LONG 0x200000
1260 static int cpu_pr_data(int pr
)
1263 case 0: return offsetof(CPUAlphaState
, ps
) | PR_BYTE
;
1264 case 1: return offsetof(CPUAlphaState
, fen
) | PR_BYTE
;
1265 case 2: return offsetof(CPUAlphaState
, pcc_ofs
) | PR_LONG
;
1266 case 3: return offsetof(CPUAlphaState
, trap_arg0
);
1267 case 4: return offsetof(CPUAlphaState
, trap_arg1
);
1268 case 5: return offsetof(CPUAlphaState
, trap_arg2
);
1269 case 6: return offsetof(CPUAlphaState
, exc_addr
);
1270 case 7: return offsetof(CPUAlphaState
, palbr
);
1271 case 8: return offsetof(CPUAlphaState
, ptbr
);
1272 case 9: return offsetof(CPUAlphaState
, vptptr
);
1273 case 10: return offsetof(CPUAlphaState
, unique
);
1274 case 11: return offsetof(CPUAlphaState
, sysval
);
1275 case 12: return offsetof(CPUAlphaState
, usp
);
1278 return offsetof(CPUAlphaState
, shadow
[pr
- 32]);
1280 return offsetof(CPUAlphaState
, scratch
[pr
- 40]);
1283 return offsetof(CPUAlphaState
, alarm_expire
);
1288 static ExitStatus
gen_mfpr(DisasContext
*ctx
, TCGv va
, int regno
)
1290 int data
= cpu_pr_data(regno
);
1292 /* Special help for VMTIME and WALLTIME. */
1293 if (regno
== 250 || regno
== 249) {
1294 void (*helper
)(TCGv
) = gen_helper_get_walltime
;
1296 helper
= gen_helper_get_vmtime
;
1298 if (ctx
->tb
->cflags
& CF_USE_ICOUNT
) {
1302 return EXIT_PC_STALE
;
1309 /* The basic registers are data only, and unknown registers
1310 are read-zero, write-ignore. */
1312 tcg_gen_movi_i64(va
, 0);
1313 } else if (data
& PR_BYTE
) {
1314 tcg_gen_ld8u_i64(va
, cpu_env
, data
& ~PR_BYTE
);
1315 } else if (data
& PR_LONG
) {
1316 tcg_gen_ld32s_i64(va
, cpu_env
, data
& ~PR_LONG
);
1318 tcg_gen_ld_i64(va
, cpu_env
, data
);
1323 static ExitStatus
gen_mtpr(DisasContext
*ctx
, TCGv vb
, int regno
)
1331 gen_helper_tbia(cpu_env
);
1336 gen_helper_tbis(cpu_env
, vb
);
1341 tmp
= tcg_const_i64(1);
1342 tcg_gen_st32_i64(tmp
, cpu_env
, -offsetof(AlphaCPU
, env
) +
1343 offsetof(CPUState
, halted
));
1344 return gen_excp(ctx
, EXCP_HLT
, 0);
1348 gen_helper_halt(vb
);
1349 return EXIT_PC_STALE
;
1353 gen_helper_set_alarm(cpu_env
, vb
);
1358 tcg_gen_st_i64(vb
, cpu_env
, offsetof(CPUAlphaState
, palbr
));
1359 /* Changing the PAL base register implies un-chaining all of the TBs
1360 that ended with a CALL_PAL. Since the base register usually only
1361 changes during boot, flushing everything works well. */
1362 gen_helper_tb_flush(cpu_env
);
1363 return EXIT_PC_STALE
;
1366 /* The basic registers are data only, and unknown registers
1367 are read-zero, write-ignore. */
1368 data
= cpu_pr_data(regno
);
1370 if (data
& PR_BYTE
) {
1371 tcg_gen_st8_i64(vb
, cpu_env
, data
& ~PR_BYTE
);
1372 } else if (data
& PR_LONG
) {
1373 tcg_gen_st32_i64(vb
, cpu_env
, data
& ~PR_LONG
);
1375 tcg_gen_st_i64(vb
, cpu_env
, data
);
1383 #endif /* !USER_ONLY*/
1385 #define REQUIRE_TB_FLAG(FLAG) \
1387 if ((ctx->tb->flags & (FLAG)) == 0) { \
1392 #define REQUIRE_REG_31(WHICH) \
1394 if (WHICH != 31) { \
1399 static ExitStatus
translate_one(DisasContext
*ctx
, uint32_t insn
)
1401 int32_t disp21
, disp16
, disp12
__attribute__((unused
));
1403 uint8_t opc
, ra
, rb
, rc
, fpfn
, fn7
, lit
;
1405 TCGv va
, vb
, vc
, tmp
;
1409 /* Decode all instruction fields */
1410 opc
= extract32(insn
, 26, 6);
1411 ra
= extract32(insn
, 21, 5);
1412 rb
= extract32(insn
, 16, 5);
1413 rc
= extract32(insn
, 0, 5);
1414 islit
= extract32(insn
, 12, 1);
1415 lit
= extract32(insn
, 13, 8);
1417 disp21
= sextract32(insn
, 0, 21);
1418 disp16
= sextract32(insn
, 0, 16);
1419 disp12
= sextract32(insn
, 0, 12);
1421 fn11
= extract32(insn
, 5, 11);
1422 fpfn
= extract32(insn
, 5, 6);
1423 fn7
= extract32(insn
, 5, 7);
1425 if (rb
== 31 && !islit
) {
1434 ret
= gen_call_pal(ctx
, insn
& 0x03ffffff);
1460 disp16
= (uint32_t)disp16
<< 16;
1464 va
= dest_gpr(ctx
, ra
);
1465 /* It's worth special-casing immediate loads. */
1467 tcg_gen_movi_i64(va
, disp16
);
1469 tcg_gen_addi_i64(va
, load_gpr(ctx
, rb
), disp16
);
1475 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
1476 gen_load_mem(ctx
, &tcg_gen_qemu_ld8u
, ra
, rb
, disp16
, 0, 0);
1480 gen_load_mem(ctx
, &tcg_gen_qemu_ld64
, ra
, rb
, disp16
, 0, 1);
1484 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
1485 gen_load_mem(ctx
, &tcg_gen_qemu_ld16u
, ra
, rb
, disp16
, 0, 0);
1489 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
1490 gen_store_mem(ctx
, &tcg_gen_qemu_st16
, ra
, rb
, disp16
, 0, 0);
1494 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
1495 gen_store_mem(ctx
, &tcg_gen_qemu_st8
, ra
, rb
, disp16
, 0, 0);
1499 gen_store_mem(ctx
, &tcg_gen_qemu_st64
, ra
, rb
, disp16
, 0, 1);
1503 vc
= dest_gpr(ctx
, rc
);
1504 vb
= load_gpr_lit(ctx
, rb
, lit
, islit
);
1508 /* Special case ADDL as SEXTL. */
1509 tcg_gen_ext32s_i64(vc
, vb
);
1513 /* Special case SUBQ as NEGQ. */
1514 tcg_gen_neg_i64(vc
, vb
);
1519 va
= load_gpr(ctx
, ra
);
1523 tcg_gen_add_i64(vc
, va
, vb
);
1524 tcg_gen_ext32s_i64(vc
, vc
);
1528 tmp
= tcg_temp_new();
1529 tcg_gen_shli_i64(tmp
, va
, 2);
1530 tcg_gen_add_i64(tmp
, tmp
, vb
);
1531 tcg_gen_ext32s_i64(vc
, tmp
);
1536 tcg_gen_sub_i64(vc
, va
, vb
);
1537 tcg_gen_ext32s_i64(vc
, vc
);
1541 tmp
= tcg_temp_new();
1542 tcg_gen_shli_i64(tmp
, va
, 2);
1543 tcg_gen_sub_i64(tmp
, tmp
, vb
);
1544 tcg_gen_ext32s_i64(vc
, tmp
);
1549 gen_helper_cmpbge(vc
, va
, vb
);
1553 tmp
= tcg_temp_new();
1554 tcg_gen_shli_i64(tmp
, va
, 3);
1555 tcg_gen_add_i64(tmp
, tmp
, vb
);
1556 tcg_gen_ext32s_i64(vc
, tmp
);
1561 tmp
= tcg_temp_new();
1562 tcg_gen_shli_i64(tmp
, va
, 3);
1563 tcg_gen_sub_i64(tmp
, tmp
, vb
);
1564 tcg_gen_ext32s_i64(vc
, tmp
);
1569 tcg_gen_setcond_i64(TCG_COND_LTU
, vc
, va
, vb
);
1573 tcg_gen_add_i64(vc
, va
, vb
);
1577 tmp
= tcg_temp_new();
1578 tcg_gen_shli_i64(tmp
, va
, 2);
1579 tcg_gen_add_i64(vc
, tmp
, vb
);
1584 tcg_gen_sub_i64(vc
, va
, vb
);
1588 tmp
= tcg_temp_new();
1589 tcg_gen_shli_i64(tmp
, va
, 2);
1590 tcg_gen_sub_i64(vc
, tmp
, vb
);
1595 tcg_gen_setcond_i64(TCG_COND_EQ
, vc
, va
, vb
);
1599 tmp
= tcg_temp_new();
1600 tcg_gen_shli_i64(tmp
, va
, 3);
1601 tcg_gen_add_i64(vc
, tmp
, vb
);
1606 tmp
= tcg_temp_new();
1607 tcg_gen_shli_i64(tmp
, va
, 3);
1608 tcg_gen_sub_i64(vc
, tmp
, vb
);
1613 tcg_gen_setcond_i64(TCG_COND_LEU
, vc
, va
, vb
);
1617 gen_helper_addlv(vc
, cpu_env
, va
, vb
);
1621 gen_helper_sublv(vc
, cpu_env
, va
, vb
);
1625 tcg_gen_setcond_i64(TCG_COND_LT
, vc
, va
, vb
);
1629 gen_helper_addqv(vc
, cpu_env
, va
, vb
);
1633 gen_helper_subqv(vc
, cpu_env
, va
, vb
);
1637 tcg_gen_setcond_i64(TCG_COND_LE
, vc
, va
, vb
);
1647 /* Special case BIS as NOP. */
1651 /* Special case BIS as MOV. */
1652 vc
= dest_gpr(ctx
, rc
);
1654 tcg_gen_movi_i64(vc
, lit
);
1656 tcg_gen_mov_i64(vc
, load_gpr(ctx
, rb
));
1662 vc
= dest_gpr(ctx
, rc
);
1663 vb
= load_gpr_lit(ctx
, rb
, lit
, islit
);
1665 if (fn7
== 0x28 && ra
== 31) {
1666 /* Special case ORNOT as NOT. */
1667 tcg_gen_not_i64(vc
, vb
);
1671 va
= load_gpr(ctx
, ra
);
1675 tcg_gen_and_i64(vc
, va
, vb
);
1679 tcg_gen_andc_i64(vc
, va
, vb
);
1683 tmp
= tcg_temp_new();
1684 tcg_gen_andi_i64(tmp
, va
, 1);
1685 tcg_gen_movcond_i64(TCG_COND_NE
, vc
, tmp
, load_zero(ctx
),
1686 vb
, load_gpr(ctx
, rc
));
1691 tmp
= tcg_temp_new();
1692 tcg_gen_andi_i64(tmp
, va
, 1);
1693 tcg_gen_movcond_i64(TCG_COND_EQ
, vc
, tmp
, load_zero(ctx
),
1694 vb
, load_gpr(ctx
, rc
));
1699 tcg_gen_or_i64(vc
, va
, vb
);
1703 tcg_gen_movcond_i64(TCG_COND_EQ
, vc
, va
, load_zero(ctx
),
1704 vb
, load_gpr(ctx
, rc
));
1708 tcg_gen_movcond_i64(TCG_COND_NE
, vc
, va
, load_zero(ctx
),
1709 vb
, load_gpr(ctx
, rc
));
1713 tcg_gen_orc_i64(vc
, va
, vb
);
1717 tcg_gen_xor_i64(vc
, va
, vb
);
1721 tcg_gen_movcond_i64(TCG_COND_LT
, vc
, va
, load_zero(ctx
),
1722 vb
, load_gpr(ctx
, rc
));
1726 tcg_gen_movcond_i64(TCG_COND_GE
, vc
, va
, load_zero(ctx
),
1727 vb
, load_gpr(ctx
, rc
));
1731 tcg_gen_eqv_i64(vc
, va
, vb
);
1737 uint64_t amask
= ctx
->tb
->flags
>> TB_FLAGS_AMASK_SHIFT
;
1738 tcg_gen_andi_i64(vc
, vb
, ~amask
);
1743 tcg_gen_movcond_i64(TCG_COND_LE
, vc
, va
, load_zero(ctx
),
1744 vb
, load_gpr(ctx
, rc
));
1748 tcg_gen_movcond_i64(TCG_COND_GT
, vc
, va
, load_zero(ctx
),
1749 vb
, load_gpr(ctx
, rc
));
1754 tcg_gen_movi_i64(vc
, ctx
->implver
);
1762 vc
= dest_gpr(ctx
, rc
);
1763 va
= load_gpr(ctx
, ra
);
1767 gen_msk_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x01);
1771 gen_ext_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x01);
1775 gen_ins_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x01);
1779 gen_msk_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1783 gen_ext_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1787 gen_ins_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1791 gen_msk_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1795 gen_ext_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1799 gen_ins_l(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1804 gen_zapnoti(vc
, va
, ~lit
);
1806 gen_helper_zap(vc
, va
, load_gpr(ctx
, rb
));
1812 gen_zapnoti(vc
, va
, lit
);
1814 gen_helper_zapnot(vc
, va
, load_gpr(ctx
, rb
));
1819 gen_msk_l(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1824 tcg_gen_shri_i64(vc
, va
, lit
& 0x3f);
1826 tmp
= tcg_temp_new();
1827 vb
= load_gpr(ctx
, rb
);
1828 tcg_gen_andi_i64(tmp
, vb
, 0x3f);
1829 tcg_gen_shr_i64(vc
, va
, tmp
);
1835 gen_ext_l(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1840 tcg_gen_shli_i64(vc
, va
, lit
& 0x3f);
1842 tmp
= tcg_temp_new();
1843 vb
= load_gpr(ctx
, rb
);
1844 tcg_gen_andi_i64(tmp
, vb
, 0x3f);
1845 tcg_gen_shl_i64(vc
, va
, tmp
);
1851 gen_ins_l(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1856 tcg_gen_sari_i64(vc
, va
, lit
& 0x3f);
1858 tmp
= tcg_temp_new();
1859 vb
= load_gpr(ctx
, rb
);
1860 tcg_gen_andi_i64(tmp
, vb
, 0x3f);
1861 tcg_gen_sar_i64(vc
, va
, tmp
);
1867 gen_msk_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1871 gen_ins_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1875 gen_ext_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x03);
1879 gen_msk_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1883 gen_ins_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1887 gen_ext_h(ctx
, vc
, va
, rb
, islit
, lit
, 0x0f);
1891 gen_msk_h(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1895 gen_ins_h(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1899 gen_ext_h(ctx
, vc
, va
, rb
, islit
, lit
, 0xff);
1907 vc
= dest_gpr(ctx
, rc
);
1908 vb
= load_gpr_lit(ctx
, rb
, lit
, islit
);
1909 va
= load_gpr(ctx
, ra
);
1913 tcg_gen_mul_i64(vc
, va
, vb
);
1914 tcg_gen_ext32s_i64(vc
, vc
);
1918 tcg_gen_mul_i64(vc
, va
, vb
);
1922 tmp
= tcg_temp_new();
1923 tcg_gen_mulu2_i64(tmp
, vc
, va
, vb
);
1928 gen_helper_mullv(vc
, cpu_env
, va
, vb
);
1932 gen_helper_mulqv(vc
, cpu_env
, va
, vb
);
1940 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX
);
1941 vc
= dest_fpr(ctx
, rc
);
1942 switch (fpfn
) { /* fn11 & 0x3F */
1946 t32
= tcg_temp_new_i32();
1947 va
= load_gpr(ctx
, ra
);
1948 tcg_gen_trunc_i64_i32(t32
, va
);
1949 gen_helper_memory_to_s(vc
, t32
);
1950 tcg_temp_free_i32(t32
);
1955 vb
= load_fpr(ctx
, rb
);
1956 gen_helper_sqrtf(vc
, cpu_env
, vb
);
1961 gen_fsqrts(ctx
, rb
, rc
, fn11
);
1966 t32
= tcg_temp_new_i32();
1967 va
= load_gpr(ctx
, ra
);
1968 tcg_gen_trunc_i64_i32(t32
, va
);
1969 gen_helper_memory_to_f(vc
, t32
);
1970 tcg_temp_free_i32(t32
);
1975 va
= load_gpr(ctx
, ra
);
1976 tcg_gen_mov_i64(vc
, va
);
1981 vb
= load_fpr(ctx
, rb
);
1982 gen_helper_sqrtg(vc
, cpu_env
, vb
);
1987 gen_fsqrtt(ctx
, rb
, rc
, fn11
);
1995 /* VAX floating point */
1996 /* XXX: rounding mode and trap are ignored (!) */
1997 vc
= dest_fpr(ctx
, rc
);
1998 vb
= load_fpr(ctx
, rb
);
1999 va
= load_fpr(ctx
, ra
);
2000 switch (fpfn
) { /* fn11 & 0x3F */
2003 gen_helper_addf(vc
, cpu_env
, va
, vb
);
2007 gen_helper_subf(vc
, cpu_env
, va
, vb
);
2011 gen_helper_mulf(vc
, cpu_env
, va
, vb
);
2015 gen_helper_divf(vc
, cpu_env
, va
, vb
);
2023 gen_helper_addg(vc
, cpu_env
, va
, vb
);
2027 gen_helper_subg(vc
, cpu_env
, va
, vb
);
2031 gen_helper_mulg(vc
, cpu_env
, va
, vb
);
2035 gen_helper_divg(vc
, cpu_env
, va
, vb
);
2039 gen_helper_cmpgeq(vc
, cpu_env
, va
, vb
);
2043 gen_helper_cmpglt(vc
, cpu_env
, va
, vb
);
2047 gen_helper_cmpgle(vc
, cpu_env
, va
, vb
);
2052 gen_helper_cvtgf(vc
, cpu_env
, vb
);
2061 gen_helper_cvtgq(vc
, cpu_env
, vb
);
2066 gen_helper_cvtqf(vc
, cpu_env
, vb
);
2071 gen_helper_cvtqg(vc
, cpu_env
, vb
);
2079 /* IEEE floating-point */
2080 switch (fpfn
) { /* fn11 & 0x3F */
2083 gen_fadds(ctx
, ra
, rb
, rc
, fn11
);
2087 gen_fsubs(ctx
, ra
, rb
, rc
, fn11
);
2091 gen_fmuls(ctx
, ra
, rb
, rc
, fn11
);
2095 gen_fdivs(ctx
, ra
, rb
, rc
, fn11
);
2099 gen_faddt(ctx
, ra
, rb
, rc
, fn11
);
2103 gen_fsubt(ctx
, ra
, rb
, rc
, fn11
);
2107 gen_fmult(ctx
, ra
, rb
, rc
, fn11
);
2111 gen_fdivt(ctx
, ra
, rb
, rc
, fn11
);
2115 gen_fcmptun(ctx
, ra
, rb
, rc
, fn11
);
2119 gen_fcmpteq(ctx
, ra
, rb
, rc
, fn11
);
2123 gen_fcmptlt(ctx
, ra
, rb
, rc
, fn11
);
2127 gen_fcmptle(ctx
, ra
, rb
, rc
, fn11
);
2131 if (fn11
== 0x2AC || fn11
== 0x6AC) {
2133 gen_fcvtst(ctx
, rb
, rc
, fn11
);
2136 gen_fcvtts(ctx
, rb
, rc
, fn11
);
2142 gen_fcvttq(ctx
, rb
, rc
, fn11
);
2147 gen_fcvtqs(ctx
, rb
, rc
, fn11
);
2152 gen_fcvtqt(ctx
, rb
, rc
, fn11
);
2164 vc
= dest_fpr(ctx
, rc
);
2165 vb
= load_fpr(ctx
, rb
);
2171 /* Special case CPYS as FNOP. */
2173 vc
= dest_fpr(ctx
, rc
);
2174 va
= load_fpr(ctx
, ra
);
2176 /* Special case CPYS as FMOV. */
2177 tcg_gen_mov_i64(vc
, va
);
2179 vb
= load_fpr(ctx
, rb
);
2180 gen_cpy_mask(vc
, va
, vb
, 0, 0x8000000000000000ULL
);
2186 vc
= dest_fpr(ctx
, rc
);
2187 vb
= load_fpr(ctx
, rb
);
2188 va
= load_fpr(ctx
, ra
);
2189 gen_cpy_mask(vc
, va
, vb
, 1, 0x8000000000000000ULL
);
2193 vc
= dest_fpr(ctx
, rc
);
2194 vb
= load_fpr(ctx
, rb
);
2195 va
= load_fpr(ctx
, ra
);
2196 gen_cpy_mask(vc
, va
, vb
, 0, 0xFFF0000000000000ULL
);
2200 va
= load_fpr(ctx
, ra
);
2201 gen_helper_store_fpcr(cpu_env
, va
);
2205 va
= dest_fpr(ctx
, ra
);
2206 gen_helper_load_fpcr(va
, cpu_env
);
2210 gen_fcmov(ctx
, TCG_COND_EQ
, ra
, rb
, rc
);
2214 gen_fcmov(ctx
, TCG_COND_NE
, ra
, rb
, rc
);
2218 gen_fcmov(ctx
, TCG_COND_LT
, ra
, rb
, rc
);
2222 gen_fcmov(ctx
, TCG_COND_GE
, ra
, rb
, rc
);
2226 gen_fcmov(ctx
, TCG_COND_LE
, ra
, rb
, rc
);
2230 gen_fcmov(ctx
, TCG_COND_GT
, ra
, rb
, rc
);
2235 vc
= dest_fpr(ctx
, rc
);
2236 vb
= load_fpr(ctx
, rb
);
2244 /* ??? I'm pretty sure there's nothing that /sv needs to do that
2245 /v doesn't do. The only thing I can think is that /sv is a
2246 valid instruction merely for completeness in the ISA. */
2247 vc
= dest_fpr(ctx
, rc
);
2248 vb
= load_fpr(ctx
, rb
);
2249 gen_helper_fcvtql_v_input(cpu_env
, vb
);
2258 switch ((uint16_t)disp16
) {
2285 va
= dest_gpr(ctx
, ra
);
2286 if (ctx
->tb
->cflags
& CF_USE_ICOUNT
) {
2288 gen_helper_load_pcc(va
, cpu_env
);
2290 ret
= EXIT_PC_STALE
;
2292 gen_helper_load_pcc(va
, cpu_env
);
2316 /* HW_MFPR (PALcode) */
2317 #ifndef CONFIG_USER_ONLY
2318 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE
);
2319 va
= dest_gpr(ctx
, ra
);
2320 ret
= gen_mfpr(ctx
, va
, insn
& 0xffff);
2327 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2328 prediction stack action, which of course we don't implement. */
2329 vb
= load_gpr(ctx
, rb
);
2330 tcg_gen_andi_i64(cpu_pc
, vb
, ~3);
2332 tcg_gen_movi_i64(cpu_ir
[ra
], ctx
->pc
);
2334 ret
= EXIT_PC_UPDATED
;
2338 /* HW_LD (PALcode) */
2339 #ifndef CONFIG_USER_ONLY
2340 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE
);
2342 TCGv addr
= tcg_temp_new();
2343 vb
= load_gpr(ctx
, rb
);
2344 va
= dest_gpr(ctx
, ra
);
2346 tcg_gen_addi_i64(addr
, vb
, disp12
);
2347 switch ((insn
>> 12) & 0xF) {
2349 /* Longword physical access (hw_ldl/p) */
2350 gen_helper_ldl_phys(va
, cpu_env
, addr
);
2353 /* Quadword physical access (hw_ldq/p) */
2354 gen_helper_ldq_phys(va
, cpu_env
, addr
);
2357 /* Longword physical access with lock (hw_ldl_l/p) */
2358 gen_helper_ldl_l_phys(va
, cpu_env
, addr
);
2361 /* Quadword physical access with lock (hw_ldq_l/p) */
2362 gen_helper_ldq_l_phys(va
, cpu_env
, addr
);
2365 /* Longword virtual PTE fetch (hw_ldl/v) */
2368 /* Quadword virtual PTE fetch (hw_ldq/v) */
2372 /* Incpu_ir[ra]id */
2375 /* Incpu_ir[ra]id */
2378 /* Longword virtual access (hw_ldl) */
2381 /* Quadword virtual access (hw_ldq) */
2384 /* Longword virtual access with protection check (hw_ldl/w) */
2385 tcg_gen_qemu_ld_i64(va
, addr
, MMU_KERNEL_IDX
, MO_LESL
);
2388 /* Quadword virtual access with protection check (hw_ldq/w) */
2389 tcg_gen_qemu_ld_i64(va
, addr
, MMU_KERNEL_IDX
, MO_LEQ
);
2392 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2395 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2398 /* Longword virtual access with alternate access mode and
2399 protection checks (hw_ldl/wa) */
2400 tcg_gen_qemu_ld_i64(va
, addr
, MMU_USER_IDX
, MO_LESL
);
2403 /* Quadword virtual access with alternate access mode and
2404 protection checks (hw_ldq/wa) */
2405 tcg_gen_qemu_ld_i64(va
, addr
, MMU_USER_IDX
, MO_LEQ
);
2408 tcg_temp_free(addr
);
2416 vc
= dest_gpr(ctx
, rc
);
2419 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX
);
2421 va
= load_fpr(ctx
, ra
);
2422 tcg_gen_mov_i64(vc
, va
);
2424 } else if (fn7
== 0x78) {
2426 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX
);
2428 t32
= tcg_temp_new_i32();
2429 va
= load_fpr(ctx
, ra
);
2430 gen_helper_s_to_memory(t32
, va
);
2431 tcg_gen_ext_i32_i64(vc
, t32
);
2432 tcg_temp_free_i32(t32
);
2436 vb
= load_gpr_lit(ctx
, rb
, lit
, islit
);
2440 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
2442 tcg_gen_ext8s_i64(vc
, vb
);
2446 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX
);
2448 tcg_gen_ext16s_i64(vc
, vb
);
2452 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX
);
2454 gen_helper_ctpop(vc
, vb
);
2458 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2459 va
= load_gpr(ctx
, ra
);
2460 gen_helper_perr(vc
, va
, vb
);
2464 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX
);
2466 gen_helper_ctlz(vc
, vb
);
2470 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX
);
2472 gen_helper_cttz(vc
, vb
);
2476 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2478 gen_helper_unpkbw(vc
, vb
);
2482 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2484 gen_helper_unpkbl(vc
, vb
);
2488 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2490 gen_helper_pkwb(vc
, vb
);
2494 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2496 gen_helper_pklb(vc
, vb
);
2500 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2501 va
= load_gpr(ctx
, ra
);
2502 gen_helper_minsb8(vc
, va
, vb
);
2506 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2507 va
= load_gpr(ctx
, ra
);
2508 gen_helper_minsw4(vc
, va
, vb
);
2512 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2513 va
= load_gpr(ctx
, ra
);
2514 gen_helper_minub8(vc
, va
, vb
);
2518 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2519 va
= load_gpr(ctx
, ra
);
2520 gen_helper_minuw4(vc
, va
, vb
);
2524 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2525 va
= load_gpr(ctx
, ra
);
2526 gen_helper_maxub8(vc
, va
, vb
);
2530 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2531 va
= load_gpr(ctx
, ra
);
2532 gen_helper_maxuw4(vc
, va
, vb
);
2536 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2537 va
= load_gpr(ctx
, ra
);
2538 gen_helper_maxsb8(vc
, va
, vb
);
2542 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI
);
2543 va
= load_gpr(ctx
, ra
);
2544 gen_helper_maxsw4(vc
, va
, vb
);
2552 /* HW_MTPR (PALcode) */
2553 #ifndef CONFIG_USER_ONLY
2554 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE
);
2555 vb
= load_gpr(ctx
, rb
);
2556 ret
= gen_mtpr(ctx
, vb
, insn
& 0xffff);
2563 /* HW_RET (PALcode) */
2564 #ifndef CONFIG_USER_ONLY
2565 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE
);
2567 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2568 address from EXC_ADDR. This turns out to be useful for our
2569 emulation PALcode, so continue to accept it. */
2570 tmp
= tcg_temp_new();
2571 tcg_gen_ld_i64(tmp
, cpu_env
, offsetof(CPUAlphaState
, exc_addr
));
2572 gen_helper_hw_ret(cpu_env
, tmp
);
2575 gen_helper_hw_ret(cpu_env
, load_gpr(ctx
, rb
));
2577 ret
= EXIT_PC_UPDATED
;
2584 /* HW_ST (PALcode) */
2585 #ifndef CONFIG_USER_ONLY
2586 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE
);
2588 TCGv addr
= tcg_temp_new();
2589 va
= load_gpr(ctx
, ra
);
2590 vb
= load_gpr(ctx
, rb
);
2592 tcg_gen_addi_i64(addr
, vb
, disp12
);
2593 switch ((insn
>> 12) & 0xF) {
2595 /* Longword physical access */
2596 gen_helper_stl_phys(cpu_env
, addr
, va
);
2599 /* Quadword physical access */
2600 gen_helper_stq_phys(cpu_env
, addr
, va
);
2603 /* Longword physical access with lock */
2604 gen_helper_stl_c_phys(dest_gpr(ctx
, ra
), cpu_env
, addr
, va
);
2607 /* Quadword physical access with lock */
2608 gen_helper_stq_c_phys(dest_gpr(ctx
, ra
), cpu_env
, addr
, va
);
2611 /* Longword virtual access */
2614 /* Quadword virtual access */
2635 /* Longword virtual access with alternate access mode */
2638 /* Quadword virtual access with alternate access mode */
2647 tcg_temp_free(addr
);
2655 gen_load_mem(ctx
, &gen_qemu_ldf
, ra
, rb
, disp16
, 1, 0);
2659 gen_load_mem(ctx
, &gen_qemu_ldg
, ra
, rb
, disp16
, 1, 0);
2663 gen_load_mem(ctx
, &gen_qemu_lds
, ra
, rb
, disp16
, 1, 0);
2667 gen_load_mem(ctx
, &tcg_gen_qemu_ld64
, ra
, rb
, disp16
, 1, 0);
2671 gen_store_mem(ctx
, &gen_qemu_stf
, ra
, rb
, disp16
, 1, 0);
2675 gen_store_mem(ctx
, &gen_qemu_stg
, ra
, rb
, disp16
, 1, 0);
2679 gen_store_mem(ctx
, &gen_qemu_sts
, ra
, rb
, disp16
, 1, 0);
2683 gen_store_mem(ctx
, &tcg_gen_qemu_st64
, ra
, rb
, disp16
, 1, 0);
2687 gen_load_mem(ctx
, &tcg_gen_qemu_ld32s
, ra
, rb
, disp16
, 0, 0);
2691 gen_load_mem(ctx
, &tcg_gen_qemu_ld64
, ra
, rb
, disp16
, 0, 0);
2695 gen_load_mem(ctx
, &gen_qemu_ldl_l
, ra
, rb
, disp16
, 0, 0);
2699 gen_load_mem(ctx
, &gen_qemu_ldq_l
, ra
, rb
, disp16
, 0, 0);
2703 gen_store_mem(ctx
, &tcg_gen_qemu_st32
, ra
, rb
, disp16
, 0, 0);
2707 gen_store_mem(ctx
, &tcg_gen_qemu_st64
, ra
, rb
, disp16
, 0, 0);
2711 ret
= gen_store_conditional(ctx
, ra
, rb
, disp16
, 0);
2715 ret
= gen_store_conditional(ctx
, ra
, rb
, disp16
, 1);
2719 ret
= gen_bdirect(ctx
, ra
, disp21
);
2721 case 0x31: /* FBEQ */
2722 ret
= gen_fbcond(ctx
, TCG_COND_EQ
, ra
, disp21
);
2724 case 0x32: /* FBLT */
2725 ret
= gen_fbcond(ctx
, TCG_COND_LT
, ra
, disp21
);
2727 case 0x33: /* FBLE */
2728 ret
= gen_fbcond(ctx
, TCG_COND_LE
, ra
, disp21
);
2732 ret
= gen_bdirect(ctx
, ra
, disp21
);
2734 case 0x35: /* FBNE */
2735 ret
= gen_fbcond(ctx
, TCG_COND_NE
, ra
, disp21
);
2737 case 0x36: /* FBGE */
2738 ret
= gen_fbcond(ctx
, TCG_COND_GE
, ra
, disp21
);
2740 case 0x37: /* FBGT */
2741 ret
= gen_fbcond(ctx
, TCG_COND_GT
, ra
, disp21
);
2745 ret
= gen_bcond(ctx
, TCG_COND_EQ
, ra
, disp21
, 1);
2749 ret
= gen_bcond(ctx
, TCG_COND_EQ
, ra
, disp21
, 0);
2753 ret
= gen_bcond(ctx
, TCG_COND_LT
, ra
, disp21
, 0);
2757 ret
= gen_bcond(ctx
, TCG_COND_LE
, ra
, disp21
, 0);
2761 ret
= gen_bcond(ctx
, TCG_COND_NE
, ra
, disp21
, 1);
2765 ret
= gen_bcond(ctx
, TCG_COND_NE
, ra
, disp21
, 0);
2769 ret
= gen_bcond(ctx
, TCG_COND_GE
, ra
, disp21
, 0);
2773 ret
= gen_bcond(ctx
, TCG_COND_GT
, ra
, disp21
, 0);
2776 ret
= gen_invalid(ctx
);
2783 static inline void gen_intermediate_code_internal(AlphaCPU
*cpu
,
2784 TranslationBlock
*tb
,
2787 CPUState
*cs
= CPU(cpu
);
2788 CPUAlphaState
*env
= &cpu
->env
;
2789 DisasContext ctx
, *ctxp
= &ctx
;
2790 target_ulong pc_start
;
2791 target_ulong pc_mask
;
2803 ctx
.mem_idx
= cpu_mmu_index(env
);
2804 ctx
.implver
= env
->implver
;
2805 ctx
.singlestep_enabled
= cs
->singlestep_enabled
;
2807 /* ??? Every TB begins with unset rounding mode, to be initialized on
2808 the first fp insn of the TB. Alternately we could define a proper
2809 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2810 to reset the FP_STATUS to that default at the end of any TB that
2811 changes the default. We could even (gasp) dynamiclly figure out
2812 what default would be most efficient given the running program. */
2814 /* Similarly for flush-to-zero. */
2818 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
2819 if (max_insns
== 0) {
2820 max_insns
= CF_COUNT_MASK
;
2823 if (in_superpage(&ctx
, pc_start
)) {
2824 pc_mask
= (1ULL << 41) - 1;
2826 pc_mask
= ~TARGET_PAGE_MASK
;
2831 if (unlikely(!QTAILQ_EMPTY(&cs
->breakpoints
))) {
2832 QTAILQ_FOREACH(bp
, &cs
->breakpoints
, entry
) {
2833 if (bp
->pc
== ctx
.pc
) {
2834 gen_excp(&ctx
, EXCP_DEBUG
, 0);
2840 j
= tcg_op_buf_count();
2844 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
2847 tcg_ctx
.gen_opc_pc
[lj
] = ctx
.pc
;
2848 tcg_ctx
.gen_opc_instr_start
[lj
] = 1;
2849 tcg_ctx
.gen_opc_icount
[lj
] = num_insns
;
2851 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
)) {
2854 insn
= cpu_ldl_code(env
, ctx
.pc
);
2857 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
2858 tcg_gen_debug_insn_start(ctx
.pc
);
2861 TCGV_UNUSED_I64(ctx
.zero
);
2862 TCGV_UNUSED_I64(ctx
.sink
);
2863 TCGV_UNUSED_I64(ctx
.lit
);
2866 ret
= translate_one(ctxp
, insn
);
2868 if (!TCGV_IS_UNUSED_I64(ctx
.sink
)) {
2869 tcg_gen_discard_i64(ctx
.sink
);
2870 tcg_temp_free(ctx
.sink
);
2872 if (!TCGV_IS_UNUSED_I64(ctx
.zero
)) {
2873 tcg_temp_free(ctx
.zero
);
2875 if (!TCGV_IS_UNUSED_I64(ctx
.lit
)) {
2876 tcg_temp_free(ctx
.lit
);
2879 /* If we reach a page boundary, are single stepping,
2880 or exhaust instruction count, stop generation. */
2882 && ((ctx
.pc
& pc_mask
) == 0
2883 || tcg_op_buf_full()
2884 || num_insns
>= max_insns
2886 || ctx
.singlestep_enabled
)) {
2887 ret
= EXIT_PC_STALE
;
2889 } while (ret
== NO_EXIT
);
2891 if (tb
->cflags
& CF_LAST_IO
) {
2900 tcg_gen_movi_i64(cpu_pc
, ctx
.pc
);
2902 case EXIT_PC_UPDATED
:
2903 if (ctx
.singlestep_enabled
) {
2904 gen_excp_1(EXCP_DEBUG
, 0);
2913 gen_tb_end(tb
, num_insns
);
2916 j
= tcg_op_buf_count();
2919 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
2922 tb
->size
= ctx
.pc
- pc_start
;
2923 tb
->icount
= num_insns
;
2927 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
2928 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
2929 log_target_disas(env
, pc_start
, ctx
.pc
- pc_start
, 1);
2935 void gen_intermediate_code (CPUAlphaState
*env
, struct TranslationBlock
*tb
)
2937 gen_intermediate_code_internal(alpha_env_get_cpu(env
), tb
, false);
2940 void gen_intermediate_code_pc (CPUAlphaState
*env
, struct TranslationBlock
*tb
)
2942 gen_intermediate_code_internal(alpha_env_get_cpu(env
), tb
, true);
2945 void restore_state_to_opc(CPUAlphaState
*env
, TranslationBlock
*tb
, int pc_pos
)
2947 env
->pc
= tcg_ctx
.gen_opc_pc
[pc_pos
];