]>
Commit | Line | Data |
---|---|---|
cb9c377f | 1 | #ifndef GEN_ICOUNT_H |
175de524 | 2 | #define GEN_ICOUNT_H |
cb9c377f | 3 | |
1de7afc9 | 4 | #include "qemu/timer.h" |
29e922b6 | 5 | |
bf20dc07 | 6 | /* Helpers for instruction counting code generation. */ |
dd5d6fe9 | 7 | |
15fa08f8 | 8 | static TCGOp *icount_start_insn; |
dd5d6fe9 | 9 | |
ba3e7926 PD |
10 | static inline void gen_io_start(void) |
11 | { | |
12 | TCGv_i32 tmp = tcg_const_i32(1); | |
13 | tcg_gen_st_i32(tmp, cpu_env, | |
14 | offsetof(ArchCPU, parent_obj.can_do_io) - | |
15 | offsetof(ArchCPU, env)); | |
16 | tcg_temp_free_i32(tmp); | |
17 | } | |
18 | ||
9e9b10c6 PD |
19 | /* |
20 | * cpu->can_do_io is cleared automatically at the beginning of | |
21 | * each translation block. The cost is minimal and only paid | |
22 | * for -icount, plus it would be very easy to forget doing it | |
23 | * in the translator. Therefore, backends only need to call | |
24 | * gen_io_start. | |
25 | */ | |
ba3e7926 PD |
26 | static inline void gen_io_end(void) |
27 | { | |
28 | TCGv_i32 tmp = tcg_const_i32(0); | |
29 | tcg_gen_st_i32(tmp, cpu_env, | |
30 | offsetof(ArchCPU, parent_obj.can_do_io) - | |
31 | offsetof(ArchCPU, env)); | |
32 | tcg_temp_free_i32(tmp); | |
33 | } | |
34 | ||
cd42d5b2 | 35 | static inline void gen_tb_start(TranslationBlock *tb) |
dd5d6fe9 | 36 | { |
1aab16c2 | 37 | TCGv_i32 count, imm; |
378df4b2 | 38 | |
26689780 | 39 | tcg_ctx->exitreq_label = gen_new_label(); |
c5a49c63 | 40 | if (tb_cflags(tb) & CF_USE_ICOUNT) { |
1aab16c2 PB |
41 | count = tcg_temp_local_new_i32(); |
42 | } else { | |
43 | count = tcg_temp_new_i32(); | |
c45cb8bb | 44 | } |
dd5d6fe9 | 45 | |
1c2adb95 | 46 | tcg_gen_ld_i32(count, cpu_env, |
5e140196 RH |
47 | offsetof(ArchCPU, neg.icount_decr.u32) - |
48 | offsetof(ArchCPU, env)); | |
c45cb8bb | 49 | |
c5a49c63 | 50 | if (tb_cflags(tb) & CF_USE_ICOUNT) { |
1aab16c2 PB |
51 | imm = tcg_temp_new_i32(); |
52 | /* We emit a movi with a dummy immediate argument. Keep the insn index | |
53 | * of the movi so that we later (when we know the actual insn count) | |
54 | * can update the immediate argument with the actual insn count. */ | |
1aab16c2 | 55 | tcg_gen_movi_i32(imm, 0xdeadbeef); |
15fa08f8 | 56 | icount_start_insn = tcg_last_op(); |
1aab16c2 PB |
57 | |
58 | tcg_gen_sub_i32(count, count, imm); | |
59 | tcg_temp_free_i32(imm); | |
60 | } | |
61 | ||
26689780 | 62 | tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label); |
c45cb8bb | 63 | |
c5a49c63 | 64 | if (tb_cflags(tb) & CF_USE_ICOUNT) { |
1c2adb95 | 65 | tcg_gen_st16_i32(count, cpu_env, |
5e140196 RH |
66 | offsetof(ArchCPU, neg.icount_decr.u16.low) - |
67 | offsetof(ArchCPU, env)); | |
ba3e7926 | 68 | gen_io_end(); |
1aab16c2 | 69 | } |
dd5d6fe9 | 70 | |
a7812ae4 | 71 | tcg_temp_free_i32(count); |
dd5d6fe9 PB |
72 | } |
73 | ||
ae06cb46 | 74 | static inline void gen_tb_end(TranslationBlock *tb, int num_insns) |
dd5d6fe9 | 75 | { |
c5a49c63 | 76 | if (tb_cflags(tb) & CF_USE_ICOUNT) { |
25caa94c EI |
77 | /* Update the num_insn immediate parameter now that we know |
78 | * the actual insn count. */ | |
15fa08f8 | 79 | tcg_set_insn_param(icount_start_insn, 1, num_insns); |
dd5d6fe9 | 80 | } |
0a7df5da | 81 | |
26689780 | 82 | gen_set_label(tcg_ctx->exitreq_label); |
07ea28b4 | 83 | tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED); |
dd5d6fe9 PB |
84 | } |
85 | ||
cb9c377f | 86 | #endif |