1#ifndef GEN_ICOUNT_H
2#define GEN_ICOUNT_H 1
3
4#include "qemu/timer.h"
5
6
7
8static TCGArg *icount_arg;
9static TCGLabel *icount_label;
10static TCGLabel *exitreq_label;
11
12static inline void gen_tb_start(TranslationBlock *tb)
13{
14 TCGv_i32 count, flag, imm;
15 int i;
16
17 exitreq_label = gen_new_label();
18 flag = tcg_temp_new_i32();
19 tcg_gen_ld_i32(flag, cpu_env,
20 offsetof(CPUState, tcg_exit_req) - ENV_OFFSET);
21 tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label);
22 tcg_temp_free_i32(flag);
23
24 if (!(tb->cflags & CF_USE_ICOUNT)) {
25 return;
26 }
27
28 icount_label = gen_new_label();
29 count = tcg_temp_local_new_i32();
30 tcg_gen_ld_i32(count, cpu_env,
31 -ENV_OFFSET + offsetof(CPUState, icount_decr.u32));
32
33 imm = tcg_temp_new_i32();
34 tcg_gen_movi_i32(imm, 0xdeadbeef);
35
36
37 i = tcg_ctx.gen_last_op_idx;
38 i = tcg_ctx.gen_op_buf[i].args;
39 icount_arg = &tcg_ctx.gen_opparam_buf[i + 1];
40
41 tcg_gen_sub_i32(count, count, imm);
42 tcg_temp_free_i32(imm);
43
44 tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
45 tcg_gen_st16_i32(count, cpu_env,
46 -ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low));
47 tcg_temp_free_i32(count);
48}
49
50static void gen_tb_end(TranslationBlock *tb, int num_insns)
51{
52 gen_set_label(exitreq_label);
53 tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_REQUESTED);
54
55 if (tb->cflags & CF_USE_ICOUNT) {
56 *icount_arg = num_insns;
57 gen_set_label(icount_label);
58 tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED);
59 }
60
61
62 tcg_ctx.gen_op_buf[tcg_ctx.gen_last_op_idx].next = -1;
63}
64
65static inline void gen_io_start(void)
66{
67 TCGv_i32 tmp = tcg_const_i32(1);
68 tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
69 tcg_temp_free_i32(tmp);
70}
71
72static inline void gen_io_end(void)
73{
74 TCGv_i32 tmp = tcg_const_i32(0);
75 tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
76 tcg_temp_free_i32(tmp);
77}
78
79#endif
80