cpu: Move icount_decr field from CPU_COMMON to CPUState
Signed-off-by: Andreas Färber <afaerber@suse.de>
This commit is contained in:
parent
efee734004
commit
28ecfd7a62
@ -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
13
cpus.c
@ -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;
|
||||||
|
@ -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; \
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user