cpu: Move icount_decr field from CPU_COMMON to CPUState

Signed-off-by: Andreas Färber <afaerber@suse.de>
This commit is contained in:
Andreas Färber 2013-08-26 05:51:49 +02:00
parent efee734004
commit 28ecfd7a62
7 changed files with 40 additions and 38 deletions

View File

@ -649,7 +649,7 @@ int cpu_exec(CPUArchState *env)
/* Instruction counter expired. */ /* Instruction counter expired. */
int insns_left; int insns_left;
tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
insns_left = env->icount_decr.u32; insns_left = cpu->icount_decr.u32;
if (cpu->icount_extra && insns_left >= 0) { if (cpu->icount_extra && insns_left >= 0) {
/* Refill decrementer and continue execution. */ /* Refill decrementer and continue execution. */
cpu->icount_extra += insns_left; cpu->icount_extra += insns_left;
@ -659,7 +659,7 @@ int cpu_exec(CPUArchState *env)
insns_left = cpu->icount_extra; insns_left = cpu->icount_extra;
} }
cpu->icount_extra -= insns_left; cpu->icount_extra -= insns_left;
env->icount_decr.u16.low = insns_left; cpu->icount_decr.u16.low = insns_left;
} else { } else {
if (insns_left > 0) { if (insns_left > 0) {
/* Execute remaining instructions. */ /* Execute remaining instructions. */

13
cpus.c
View File

@ -139,11 +139,10 @@ static int64_t cpu_get_icount_locked(void)
icount = qemu_icount; icount = qemu_icount;
if (cpu) { if (cpu) {
CPUArchState *env = cpu->env_ptr;
if (!cpu_can_do_io(cpu)) { if (!cpu_can_do_io(cpu)) {
fprintf(stderr, "Bad clock read\n"); fprintf(stderr, "Bad clock read\n");
} }
icount -= (env->icount_decr.u16.low + cpu->icount_extra); icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
} }
return qemu_icount_bias + (icount << icount_time_shift); return qemu_icount_bias + (icount << icount_time_shift);
} }
@ -1249,8 +1248,8 @@ static int tcg_cpu_exec(CPUArchState *env)
int64_t count; int64_t count;
int64_t deadline; int64_t deadline;
int decr; int decr;
qemu_icount -= (env->icount_decr.u16.low + cpu->icount_extra); qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
env->icount_decr.u16.low = 0; cpu->icount_decr.u16.low = 0;
cpu->icount_extra = 0; cpu->icount_extra = 0;
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
@ -1267,7 +1266,7 @@ static int tcg_cpu_exec(CPUArchState *env)
qemu_icount += count; qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count; decr = (count > 0xffff) ? 0xffff : count;
count -= decr; count -= decr;
env->icount_decr.u16.low = decr; cpu->icount_decr.u16.low = decr;
cpu->icount_extra = count; cpu->icount_extra = count;
} }
ret = cpu_exec(env); ret = cpu_exec(env);
@ -1277,8 +1276,8 @@ static int tcg_cpu_exec(CPUArchState *env)
if (use_icount) { if (use_icount) {
/* Fold pending instructions back into the /* Fold pending instructions back into the
instruction counter, and clear the interrupt flag. */ instruction counter, and clear the interrupt flag. */
qemu_icount -= (env->icount_decr.u16.low + cpu->icount_extra); qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
env->icount_decr.u32 = 0; cpu->icount_decr.u32 = 0;
cpu->icount_extra = 0; cpu->icount_extra = 0;
} }
return ret; return ret;

View File

@ -118,18 +118,6 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
#endif #endif
#ifdef HOST_WORDS_BIGENDIAN
typedef struct icount_decr_u16 {
uint16_t high;
uint16_t low;
} icount_decr_u16;
#else
typedef struct icount_decr_u16 {
uint16_t low;
uint16_t high;
} icount_decr_u16;
#endif
typedef struct CPUBreakpoint { typedef struct CPUBreakpoint {
target_ulong pc; target_ulong pc;
int flags; /* BP_* */ int flags; /* BP_* */
@ -149,14 +137,6 @@ typedef struct CPUWatchpoint {
CPU_COMMON_TLB \ CPU_COMMON_TLB \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
\ \
/* Number of cycles left, with interrupt flag in high bit. \
This allows a single read-compare-cbranch-write sequence to test \
for both decrementer underflow and exceptions. */ \
union { \
uint32_t u32; \
icount_decr_u16 u16; \
} icount_decr; \
\
/* from this point: preserved by CPU reset */ \ /* from this point: preserved by CPU reset */ \
/* ice debug support */ \ /* ice debug support */ \
QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \

View File

@ -26,13 +26,15 @@ static inline void gen_tb_start(void)
icount_label = gen_new_label(); icount_label = gen_new_label();
count = tcg_temp_local_new_i32(); count = tcg_temp_local_new_i32();
tcg_gen_ld_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u32)); tcg_gen_ld_i32(count, cpu_env,
-ENV_OFFSET + offsetof(CPUState, icount_decr.u32));
/* This is a horrid hack to allow fixing up the value later. */ /* This is a horrid hack to allow fixing up the value later. */
icount_arg = tcg_ctx.gen_opparam_ptr + 1; icount_arg = tcg_ctx.gen_opparam_ptr + 1;
tcg_gen_subi_i32(count, count, 0xdeadbeef); tcg_gen_subi_i32(count, count, 0xdeadbeef);
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
tcg_gen_st16_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u16.low)); tcg_gen_st16_i32(count, cpu_env,
-ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low));
tcg_temp_free_i32(count); tcg_temp_free_i32(count);
} }

View File

@ -138,6 +138,18 @@ typedef struct CPUClass {
const char *gdb_core_xml_file; const char *gdb_core_xml_file;
} CPUClass; } CPUClass;
#ifdef HOST_WORDS_BIGENDIAN
typedef struct icount_decr_u16 {
uint16_t high;
uint16_t low;
} icount_decr_u16;
#else
typedef struct icount_decr_u16 {
uint16_t low;
uint16_t high;
} icount_decr_u16;
#endif
struct KVMState; struct KVMState;
struct kvm_run; struct kvm_run;
@ -158,6 +170,9 @@ struct kvm_run;
* CPU and return to its top level loop. * CPU and return to its top level loop.
* @singlestep_enabled: Flags for single-stepping. * @singlestep_enabled: Flags for single-stepping.
* @icount_extra: Instructions until next timer event. * @icount_extra: Instructions until next timer event.
* @icount_decr: Number of cycles left, with interrupt flag in high bit.
* This allows a single read-compare-cbranch-write sequence to test
* for both decrementer underflow and exceptions.
* @can_do_io: Nonzero if memory-mapped IO is safe. * @can_do_io: Nonzero if memory-mapped IO is safe.
* @env_ptr: Pointer to subclass-specific CPUArchState field. * @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB. * @current_tb: Currently executing TB.
@ -223,6 +238,10 @@ struct CPUState {
/* TODO Move common fields from CPUArchState here. */ /* TODO Move common fields from CPUArchState here. */
int cpu_index; /* used by alpha TCG */ int cpu_index; /* used by alpha TCG */
uint32_t halted; /* used by alpha, cris, ppc TCG */ uint32_t halted; /* used by alpha, cris, ppc TCG */
union {
uint32_t u32;
icount_decr_u16 u16;
} icount_decr;
uint32_t can_do_io; uint32_t can_do_io;
}; };

View File

@ -242,6 +242,7 @@ static void cpu_common_reset(CPUState *cpu)
cpu->mem_io_pc = 0; cpu->mem_io_pc = 0;
cpu->mem_io_vaddr = 0; cpu->mem_io_vaddr = 0;
cpu->icount_extra = 0; cpu->icount_extra = 0;
cpu->icount_decr.u32 = 0;
cpu->can_do_io = 0; cpu->can_do_io = 0;
} }

View File

@ -217,7 +217,7 @@ static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env,
if (use_icount) { if (use_icount) {
/* Reset the cycle counter to the start of the block. */ /* Reset the cycle counter to the start of the block. */
env->icount_decr.u16.low += tb->icount; cpu->icount_decr.u16.low += tb->icount;
/* Clear the IO flag. */ /* Clear the IO flag. */
cpu->can_do_io = 0; cpu->can_do_io = 0;
} }
@ -242,7 +242,7 @@ static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env,
while (s->gen_opc_instr_start[j] == 0) { while (s->gen_opc_instr_start[j] == 0) {
j--; j--;
} }
env->icount_decr.u16.low -= s->gen_opc_icount[j]; cpu->icount_decr.u16.low -= s->gen_opc_icount[j];
restore_state_to_opc(env, tb, j); restore_state_to_opc(env, tb, j);
@ -1409,7 +1409,7 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
} }
if (use_icount) { if (use_icount) {
env->icount_decr.u16.high = 0xffff; cpu->icount_decr.u16.high = 0xffff;
if (!cpu_can_do_io(cpu) if (!cpu_can_do_io(cpu)
&& (mask & ~old_mask) != 0) { && (mask & ~old_mask) != 0) {
cpu_abort(env, "Raised interrupt while not in I/O function"); cpu_abort(env, "Raised interrupt while not in I/O function");
@ -1425,6 +1425,7 @@ CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
must be at the end of the TB */ must be at the end of the TB */
void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr) void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
{ {
CPUState *cpu = ENV_GET_CPU(env);
TranslationBlock *tb; TranslationBlock *tb;
uint32_t n, cflags; uint32_t n, cflags;
target_ulong pc, cs_base; target_ulong pc, cs_base;
@ -1435,11 +1436,11 @@ void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
(void *)retaddr); (void *)retaddr);
} }
n = env->icount_decr.u16.low + tb->icount; n = cpu->icount_decr.u16.low + tb->icount;
cpu_restore_state_from_tb(tb, env, retaddr); cpu_restore_state_from_tb(tb, env, retaddr);
/* Calculate how many instructions had been executed before the fault /* Calculate how many instructions had been executed before the fault
occurred. */ occurred. */
n = n - env->icount_decr.u16.low; n = n - cpu->icount_decr.u16.low;
/* Generate a new TB ending on the I/O insn. */ /* Generate a new TB ending on the I/O insn. */
n++; n++;
/* On MIPS and SH, delay slot instructions can only be restarted if /* On MIPS and SH, delay slot instructions can only be restarted if
@ -1449,14 +1450,14 @@ void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
#if defined(TARGET_MIPS) #if defined(TARGET_MIPS)
if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
env->active_tc.PC -= 4; env->active_tc.PC -= 4;
env->icount_decr.u16.low++; cpu->icount_decr.u16.low++;
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
} }
#elif defined(TARGET_SH4) #elif defined(TARGET_SH4)
if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
&& n > 1) { && n > 1) {
env->pc -= 2; env->pc -= 2;
env->icount_decr.u16.low++; cpu->icount_decr.u16.low++;
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
} }
#endif #endif