Compile qemu-timer only once
Arrange various declarations so that also non-CPU code can access them, adjust users. Move CPU specific code to cpus.c. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
		
							parent
							
								
									5c4532ee78
								
							
						
					
					
						commit
						29e922b61f
					
				| 
						 | 
				
			
			@ -105,6 +105,7 @@ common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
 | 
			
		|||
common-obj-$(CONFIG_COCOA) += cocoa.o
 | 
			
		||||
common-obj-$(CONFIG_IOTHREAD) += qemu-thread.o
 | 
			
		||||
common-obj-y += notify.o
 | 
			
		||||
common-obj-y += qemu-timer.o
 | 
			
		||||
 | 
			
		||||
slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
 | 
			
		||||
slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,7 +162,6 @@ endif #CONFIG_BSD_USER
 | 
			
		|||
ifdef CONFIG_SOFTMMU
 | 
			
		||||
 | 
			
		||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o
 | 
			
		||||
obj-y += qemu-timer.o
 | 
			
		||||
# virtio has to be here due to weird dependency between PCI and virtio-net.
 | 
			
		||||
# need to fix this properly
 | 
			
		||||
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										147
									
								
								cpu-all.h
								
								
								
								
							
							
						
						
									
										147
									
								
								cpu-all.h
								
								
								
								
							| 
						 | 
				
			
			@ -771,10 +771,6 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
 | 
			
		|||
extern CPUState *first_cpu;
 | 
			
		||||
extern CPUState *cpu_single_env;
 | 
			
		||||
 | 
			
		||||
int64_t qemu_icount_round(int64_t count);
 | 
			
		||||
extern int64_t qemu_icount;
 | 
			
		||||
extern int use_icount;
 | 
			
		||||
 | 
			
		||||
#define CPU_INTERRUPT_HARD   0x02 /* hardware interrupt pending */
 | 
			
		||||
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
 | 
			
		||||
#define CPU_INTERRUPT_TIMER  0x08 /* internal timer exception pending */
 | 
			
		||||
| 
						 | 
				
			
			@ -921,149 +917,6 @@ void dump_exec_info(FILE *f,
 | 
			
		|||
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
 | 
			
		||||
                        uint8_t *buf, int len, int is_write);
 | 
			
		||||
 | 
			
		||||
/*******************************************/
 | 
			
		||||
/* host CPU ticks (if available) */
 | 
			
		||||
 | 
			
		||||
#if defined(_ARCH_PPC)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t retval;
 | 
			
		||||
#ifdef _ARCH_PPC64
 | 
			
		||||
    /* This reads timebase in one 64bit go and includes Cell workaround from:
 | 
			
		||||
       http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
 | 
			
		||||
     */
 | 
			
		||||
    __asm__ __volatile__ (
 | 
			
		||||
        "mftb    %0\n\t"
 | 
			
		||||
        "cmpwi   %0,0\n\t"
 | 
			
		||||
        "beq-    $-8"
 | 
			
		||||
        : "=r" (retval));
 | 
			
		||||
#else
 | 
			
		||||
    /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
 | 
			
		||||
    unsigned long junk;
 | 
			
		||||
    __asm__ __volatile__ (
 | 
			
		||||
        "mftbu   %1\n\t"
 | 
			
		||||
        "mftb    %L0\n\t"
 | 
			
		||||
        "mftbu   %0\n\t"
 | 
			
		||||
        "cmpw    %0,%1\n\t"
 | 
			
		||||
        "bne     $-16"
 | 
			
		||||
        : "=r" (retval), "=r" (junk));
 | 
			
		||||
#endif
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__i386__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile ("rdtsc" : "=A" (val));
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__x86_64__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t low,high;
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
 | 
			
		||||
    val = high;
 | 
			
		||||
    val <<= 32;
 | 
			
		||||
    val |= low;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__hppa__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int val;
 | 
			
		||||
    asm volatile ("mfctl %%cr16, %0" : "=r"(val));
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__ia64)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
	int64_t val;
 | 
			
		||||
	asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__s390__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks (void)
 | 
			
		||||
{
 | 
			
		||||
#if     defined(_LP64)
 | 
			
		||||
        uint64_t        rval;
 | 
			
		||||
        asm volatile("rd %%tick,%0" : "=r"(rval));
 | 
			
		||||
        return rval;
 | 
			
		||||
#else
 | 
			
		||||
        union {
 | 
			
		||||
                uint64_t i64;
 | 
			
		||||
                struct {
 | 
			
		||||
                        uint32_t high;
 | 
			
		||||
                        uint32_t low;
 | 
			
		||||
                }       i32;
 | 
			
		||||
        } rval;
 | 
			
		||||
        asm volatile("rd %%tick,%1; srlx %1,32,%0"
 | 
			
		||||
                : "=r"(rval.i32.high), "=r"(rval.i32.low));
 | 
			
		||||
        return rval.i64;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__mips__) && \
 | 
			
		||||
      ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
 | 
			
		||||
/*
 | 
			
		||||
 * binutils wants to use rdhwr only on mips32r2
 | 
			
		||||
 * but as linux kernel emulate it, it's fine
 | 
			
		||||
 * to use it.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#define MIPS_RDHWR(rd, value) {                 \
 | 
			
		||||
    __asm__ __volatile__ (                      \
 | 
			
		||||
                          ".set   push\n\t"     \
 | 
			
		||||
                          ".set mips32r2\n\t"   \
 | 
			
		||||
                          "rdhwr  %0, "rd"\n\t" \
 | 
			
		||||
                          ".set   pop"          \
 | 
			
		||||
                          : "=r" (value));      \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
 | 
			
		||||
    uint32_t count;
 | 
			
		||||
    static uint32_t cyc_per_count = 0;
 | 
			
		||||
 | 
			
		||||
    if (!cyc_per_count)
 | 
			
		||||
        MIPS_RDHWR("$3", cyc_per_count);
 | 
			
		||||
 | 
			
		||||
    MIPS_RDHWR("$2", count);
 | 
			
		||||
    return (int64_t)(count * cyc_per_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
/* The host CPU doesn't have an easily accessible cycle counter.
 | 
			
		||||
   Just return a monotonically increasing value.  This will be
 | 
			
		||||
   totally wrong, but hopefully better than nothing.  */
 | 
			
		||||
static inline int64_t cpu_get_real_ticks (void)
 | 
			
		||||
{
 | 
			
		||||
    static int64_t ticks = 0;
 | 
			
		||||
    return ticks++;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* profiling */
 | 
			
		||||
#ifdef CONFIG_PROFILER
 | 
			
		||||
static inline int64_t profile_getclock(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								cpus.c
								
								
								
								
							
							
						
						
									
										16
									
								
								cpus.c
								
								
								
								
							| 
						 | 
				
			
			@ -771,3 +771,19 @@ void set_cpu_log(const char *optarg)
 | 
			
		|||
    }
 | 
			
		||||
    cpu_set_log(mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return the virtual CPU time, based on the instruction counter.  */
 | 
			
		||||
int64_t cpu_get_icount(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t icount;
 | 
			
		||||
    CPUState *env = cpu_single_env;;
 | 
			
		||||
 | 
			
		||||
    icount = qemu_icount;
 | 
			
		||||
    if (env) {
 | 
			
		||||
        if (!can_do_io(env)) {
 | 
			
		||||
            fprintf(stderr, "Bad clock read\n");
 | 
			
		||||
        }
 | 
			
		||||
        icount -= (env->icount_decr.u16.low + env->icount_extra);
 | 
			
		||||
    }
 | 
			
		||||
    return qemu_icount_bias + (icount << icount_time_shift);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								exec-all.h
								
								
								
								
							
							
						
						
									
										14
									
								
								exec-all.h
								
								
								
								
							| 
						 | 
				
			
			@ -337,20 +337,6 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
 | 
			
		|||
        + env1->tlb_table[mmu_idx][page_index].addend;
 | 
			
		||||
    return qemu_ram_addr_from_host(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Deterministic execution requires that IO only be performed on the last
 | 
			
		||||
   instruction of a TB so that interrupts take effect immediately.  */
 | 
			
		||||
static inline int can_do_io(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
    if (!use_icount)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    /* If not executing code then assume we are ok.  */
 | 
			
		||||
    if (!env->current_tb)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    return env->can_do_io != 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef void (CPUDebugExcpHandler)(CPUState *env);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								exec.c
								
								
								
								
							
							
						
						
									
										1
									
								
								exec.c
								
								
								
								
							| 
						 | 
				
			
			@ -38,6 +38,7 @@
 | 
			
		|||
#include "hw/hw.h"
 | 
			
		||||
#include "osdep.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
#include <qemu.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
#include "qemu-timer.h"
 | 
			
		||||
 | 
			
		||||
/* Helpers for instruction counting code generation.  */
 | 
			
		||||
 | 
			
		||||
static TCGArg *icount_arg;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@
 | 
			
		|||
/* For tb_lock */
 | 
			
		||||
#include "exec-all.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#include "envlist.h"
 | 
			
		||||
 | 
			
		||||
#define DEBUG_LOGFILE "/tmp/qemu.log"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,10 @@
 | 
			
		|||
 | 
			
		||||
#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUTimer QEMUTimer;
 | 
			
		||||
typedef struct QEMUFile QEMUFile;
 | 
			
		||||
typedef struct QEMUBH QEMUBH;
 | 
			
		||||
 | 
			
		||||
/* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that
 | 
			
		||||
   cannot include the following headers without conflicts. This condition has
 | 
			
		||||
   to be removed once dyngen is gone. */
 | 
			
		||||
| 
						 | 
				
			
			@ -96,8 +100,6 @@ static inline char *realpath(const char *path, char *resolved_path)
 | 
			
		|||
#endif /* !defined(NEED_CPU_H) */
 | 
			
		||||
 | 
			
		||||
/* bottom halves */
 | 
			
		||||
typedef struct QEMUBH QEMUBH;
 | 
			
		||||
 | 
			
		||||
typedef void QEMUBHFunc(void *opaque);
 | 
			
		||||
 | 
			
		||||
void async_context_push(void);
 | 
			
		||||
| 
						 | 
				
			
			@ -211,11 +213,9 @@ typedef struct CharDriverState CharDriverState;
 | 
			
		|||
typedef struct MACAddr MACAddr;
 | 
			
		||||
typedef struct VLANState VLANState;
 | 
			
		||||
typedef struct VLANClientState VLANClientState;
 | 
			
		||||
typedef struct QEMUFile QEMUFile;
 | 
			
		||||
typedef struct i2c_bus i2c_bus;
 | 
			
		||||
typedef struct i2c_slave i2c_slave;
 | 
			
		||||
typedef struct SMBusDevice SMBusDevice;
 | 
			
		||||
typedef struct QEMUTimer QEMUTimer;
 | 
			
		||||
typedef struct PCIHostState PCIHostState;
 | 
			
		||||
typedef struct PCIExpressHost PCIExpressHost;
 | 
			
		||||
typedef struct PCIBus PCIBus;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								qemu-timer.c
								
								
								
								
							
							
						
						
									
										20
									
								
								qemu-timer.c
								
								
								
								
							| 
						 | 
				
			
			@ -53,16 +53,14 @@
 | 
			
		|||
#include <mmsystem.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "cpu-defs.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#include "exec-all.h"
 | 
			
		||||
 | 
			
		||||
/* Conversion factor from emulated instructions to virtual clock ticks.  */
 | 
			
		||||
static int icount_time_shift;
 | 
			
		||||
int icount_time_shift;
 | 
			
		||||
/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
 | 
			
		||||
#define MAX_ICOUNT_SHIFT 10
 | 
			
		||||
/* Compensate for varying guest execution speed.  */
 | 
			
		||||
static int64_t qemu_icount_bias;
 | 
			
		||||
int64_t qemu_icount_bias;
 | 
			
		||||
static QEMUTimer *icount_rt_timer;
 | 
			
		||||
static QEMUTimer *icount_vm_timer;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -138,20 +136,6 @@ static int64_t get_clock(void)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Return the virtual CPU time, based on the instruction counter.  */
 | 
			
		||||
static int64_t cpu_get_icount(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t icount;
 | 
			
		||||
    CPUState *env = cpu_single_env;;
 | 
			
		||||
    icount = qemu_icount;
 | 
			
		||||
    if (env) {
 | 
			
		||||
        if (!can_do_io(env))
 | 
			
		||||
            fprintf(stderr, "Bad clock read\n");
 | 
			
		||||
        icount -= (env->icount_decr.u16.low + env->icount_extra);
 | 
			
		||||
    }
 | 
			
		||||
    return qemu_icount_bias + (icount << icount_time_shift);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***********************************************************/
 | 
			
		||||
/* guest cycle counter */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										167
									
								
								qemu-timer.h
								
								
								
								
							
							
						
						
									
										167
									
								
								qemu-timer.h
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
#ifndef QEMU_TIMER_H
 | 
			
		||||
#define QEMU_TIMER_H
 | 
			
		||||
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
 | 
			
		||||
/* timers */
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUClock QEMUClock;
 | 
			
		||||
| 
						 | 
				
			
			@ -69,4 +71,169 @@ void ptimer_stop(ptimer_state *s);
 | 
			
		|||
void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
 | 
			
		||||
void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
 | 
			
		||||
 | 
			
		||||
/* icount */
 | 
			
		||||
int64_t qemu_icount_round(int64_t count);
 | 
			
		||||
extern int64_t qemu_icount;
 | 
			
		||||
extern int use_icount;
 | 
			
		||||
extern int icount_time_shift;
 | 
			
		||||
extern int64_t qemu_icount_bias;
 | 
			
		||||
int64_t cpu_get_icount(void);
 | 
			
		||||
 | 
			
		||||
/*******************************************/
 | 
			
		||||
/* host CPU ticks (if available) */
 | 
			
		||||
 | 
			
		||||
#if defined(_ARCH_PPC)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t retval;
 | 
			
		||||
#ifdef _ARCH_PPC64
 | 
			
		||||
    /* This reads timebase in one 64bit go and includes Cell workaround from:
 | 
			
		||||
       http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
 | 
			
		||||
    */
 | 
			
		||||
    __asm__ __volatile__ ("mftb    %0\n\t"
 | 
			
		||||
                          "cmpwi   %0,0\n\t"
 | 
			
		||||
                          "beq-    $-8"
 | 
			
		||||
                          : "=r" (retval));
 | 
			
		||||
#else
 | 
			
		||||
    /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
 | 
			
		||||
    unsigned long junk;
 | 
			
		||||
    __asm__ __volatile__ ("mftbu   %1\n\t"
 | 
			
		||||
                          "mftb    %L0\n\t"
 | 
			
		||||
                          "mftbu   %0\n\t"
 | 
			
		||||
                          "cmpw    %0,%1\n\t"
 | 
			
		||||
                          "bne     $-16"
 | 
			
		||||
                          : "=r" (retval), "=r" (junk));
 | 
			
		||||
#endif
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__i386__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile ("rdtsc" : "=A" (val));
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__x86_64__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t low,high;
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
 | 
			
		||||
    val = high;
 | 
			
		||||
    val <<= 32;
 | 
			
		||||
    val |= low;
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__hppa__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int val;
 | 
			
		||||
    asm volatile ("mfctl %%cr16, %0" : "=r"(val));
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__ia64)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__s390__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    int64_t val;
 | 
			
		||||
    asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks (void)
 | 
			
		||||
{
 | 
			
		||||
#if defined(_LP64)
 | 
			
		||||
    uint64_t        rval;
 | 
			
		||||
    asm volatile("rd %%tick,%0" : "=r"(rval));
 | 
			
		||||
    return rval;
 | 
			
		||||
#else
 | 
			
		||||
    union {
 | 
			
		||||
        uint64_t i64;
 | 
			
		||||
        struct {
 | 
			
		||||
            uint32_t high;
 | 
			
		||||
            uint32_t low;
 | 
			
		||||
        }       i32;
 | 
			
		||||
    } rval;
 | 
			
		||||
    asm volatile("rd %%tick,%1; srlx %1,32,%0"
 | 
			
		||||
                 : "=r"(rval.i32.high), "=r"(rval.i32.low));
 | 
			
		||||
    return rval.i64;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__mips__) && \
 | 
			
		||||
    ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
 | 
			
		||||
/*
 | 
			
		||||
 * binutils wants to use rdhwr only on mips32r2
 | 
			
		||||
 * but as linux kernel emulate it, it's fine
 | 
			
		||||
 * to use it.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#define MIPS_RDHWR(rd, value) {                         \
 | 
			
		||||
        __asm__ __volatile__ (".set   push\n\t"         \
 | 
			
		||||
                              ".set mips32r2\n\t"       \
 | 
			
		||||
                              "rdhwr  %0, "rd"\n\t"     \
 | 
			
		||||
                              ".set   pop"              \
 | 
			
		||||
                              : "=r" (value));          \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
static inline int64_t cpu_get_real_ticks(void)
 | 
			
		||||
{
 | 
			
		||||
    /* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
 | 
			
		||||
    uint32_t count;
 | 
			
		||||
    static uint32_t cyc_per_count = 0;
 | 
			
		||||
 | 
			
		||||
    if (!cyc_per_count) {
 | 
			
		||||
        MIPS_RDHWR("$3", cyc_per_count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MIPS_RDHWR("$2", count);
 | 
			
		||||
    return (int64_t)(count * cyc_per_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
/* The host CPU doesn't have an easily accessible cycle counter.
 | 
			
		||||
   Just return a monotonically increasing value.  This will be
 | 
			
		||||
   totally wrong, but hopefully better than nothing.  */
 | 
			
		||||
static inline int64_t cpu_get_real_ticks (void)
 | 
			
		||||
{
 | 
			
		||||
    static int64_t ticks = 0;
 | 
			
		||||
    return ticks++;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NEED_CPU_H
 | 
			
		||||
/* Deterministic execution requires that IO only be performed on the last
 | 
			
		||||
   instruction of a TB so that interrupts take effect immediately.  */
 | 
			
		||||
static inline int can_do_io(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
    if (!use_icount)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    /* If not executing code then assume we are ok.  */
 | 
			
		||||
    if (!env->current_tb)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    return env->can_do_io != 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,8 @@
 | 
			
		|||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE (1 << SHIFT)
 | 
			
		||||
 | 
			
		||||
#if DATA_SIZE == 8
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@
 | 
			
		|||
#include "exec-all.h"
 | 
			
		||||
#include "disas.h"
 | 
			
		||||
#include "tcg.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
 | 
			
		||||
/* code generation context */
 | 
			
		||||
TCGContext tcg_ctx;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue