From: j_mayer Date: Sun, 30 Sep 2007 00:38:38 +0000 (+0000) Subject: Implement the PowerPC alternate time-base, following the 2.04 specification. X-Git-Tag: 0.10.0-0maemo1~3065 X-Git-Url: http://vcs.maemo.org/git/?a=commitdiff_plain;h=a062e36c58738321295e1031bebb1b89a0cdf01a;p=qemu Implement the PowerPC alternate time-base, following the 2.04 specification. Share most code with the time-base management routines. Remove time-base write routines from user-mode emulation environments. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3277 c046a42c-6fe2-441c-8c8c-71466251a162 --- diff --git a/darwin-user/main.c b/darwin-user/main.c index affd874..45495ed 100644 --- a/darwin-user/main.c +++ b/darwin-user/main.c @@ -124,24 +124,14 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) return cpu_ppc_get_tb(env) >> 32; } -static void cpu_ppc_store_tb (CPUState *env, uint64_t value) +uint32_t cpu_ppc_load_atbl (CPUState *env) { - /* TO FIX */ -} - -void cpu_ppc_store_tbu (CPUState *env, uint32_t value) -{ - cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); -} - -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) -{ - cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value); + return cpu_ppc_get_tb(env) & 0xFFFFFFFF; } -void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) +uint32_t cpu_ppc_load_atbu (CPUState *env) { - cpu_ppc_store_tbu( env, value ); + return cpu_ppc_get_tb(env) >> 32; } uint32_t cpu_ppc601_load_rtcu (CPUState *env) diff --git a/hw/ppc.c b/hw/ppc.c index 20ee532..270097b 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -408,6 +408,7 @@ void ppc405_irq_init (CPUState *env) struct ppc_tb_t { /* Time base management */ int64_t tb_offset; /* Compensation */ + int64_t atb_offset; /* Compensation */ uint32_t tb_freq; /* TB frequency */ /* Decrementer management */ uint64_t decr_next; /* Tick for next decr interrupt */ @@ -422,7 +423,7 @@ struct ppc_tb_t { void *opaque; }; -static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env) +static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, int64_t tb_offset) { /* TB time in tb periods */ return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, @@ -434,19 +435,10 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) ppc_tb_t *tb_env = env->tb_env; uint64_t tb; - tb = cpu_ppc_get_tb(tb_env); -#ifdef PPC_DEBUG_TB - { - static int last_time; - int now; - now = time(NULL); - if (last_time != now) { - last_time = now; - if (loglevel != 0) { - fprintf(logfile, "%s: tb=0x%016lx %d %08lx\n", - __func__, tb, now, tb_env->tb_offset); - } - } + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); +#if defined(PPC_DEBUG_TB) + if (loglevel != 0) { + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); } #endif @@ -458,7 +450,7 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) ppc_tb_t *tb_env = env->tb_env; uint64_t tb; - tb = cpu_ppc_get_tb(tb_env); + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); #if defined(PPC_DEBUG_TB) if (loglevel != 0) { fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); @@ -468,32 +460,89 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) return tb >> 32; } -static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value) +static inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, int64_t *tb_offsetp, + uint64_t value) { - tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq) + *tb_offsetp = muldiv64(value, ticks_per_sec, tb_env->tb_freq) - qemu_get_clock(vm_clock); #ifdef PPC_DEBUG_TB if (loglevel != 0) { fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, - tb_env->tb_offset); + *tb_offsetp); } #endif } +void cpu_ppc_store_tbl (CPUState *env, uint32_t value) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); + tb &= 0xFFFFFFFF00000000ULL; + cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, tb | (uint64_t)value); +} + void cpu_ppc_store_tbu (CPUState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; - cpu_ppc_store_tb(tb_env, - ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); + tb &= 0x00000000FFFFFFFFULL; + cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, + ((uint64_t)value << 32) | tb); } -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) +uint32_t cpu_ppc_load_atbl (CPUState *env) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); +#if defined(PPC_DEBUG_TB) + if (loglevel != 0) { + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); + } +#endif + + return tb & 0xFFFFFFFF; +} + +uint32_t cpu_ppc_load_atbu (CPUState *env) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); +#if defined(PPC_DEBUG_TB) + if (loglevel != 0) { + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); + } +#endif + + return tb >> 32; +} + +void cpu_ppc_store_atbl (CPUState *env, uint32_t value) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); + tb &= 0xFFFFFFFF00000000ULL; + cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, tb | (uint64_t)value); +} + +void cpu_ppc_store_atbu (CPUState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; - cpu_ppc_store_tb(tb_env, - ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value); + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); + tb &= 0x00000000FFFFFFFFULL; + cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, + ((uint64_t)value << 32) | tb); } static inline uint32_t _cpu_ppc_load_decr (CPUState *env, uint64_t *next) diff --git a/linux-user/main.c b/linux-user/main.c index fb424ad..a06a706 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -664,7 +664,6 @@ void cpu_loop (CPUSPARCState *env) #endif #ifdef TARGET_PPC - static inline uint64_t cpu_ppc_get_tb (CPUState *env) { /* TO FIX */ @@ -681,32 +680,19 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) return cpu_ppc_get_tb(env) >> 32; } -static void cpu_ppc_store_tb (CPUState *env, uint64_t value) -{ - /* TO FIX */ -} - -void cpu_ppc_store_tbu (CPUState *env, uint32_t value) +uint32_t cpu_ppc_load_atbl (CPUState *env) { - cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); + return cpu_ppc_get_tb(env) & 0xFFFFFFFF; } -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) +uint32_t cpu_ppc_load_atbu (CPUState *env) { - cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value); + return cpu_ppc_get_tb(env) >> 32; } -void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) -__attribute__ (( alias ("cpu_ppc_store_tbu") )); - uint32_t cpu_ppc601_load_rtcu (CPUState *env) __attribute__ (( alias ("cpu_ppc_load_tbu") )); -void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value) -{ - cpu_ppc_store_tbl(env, value & 0x3FFFFF80); -} - uint32_t cpu_ppc601_load_rtcl (CPUState *env) { return cpu_ppc_load_tbl(env) & 0x3FFFFF80; diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 21c3061..e4d1216 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -625,6 +625,10 @@ uint32_t cpu_ppc_load_tbl (CPUPPCState *env); uint32_t cpu_ppc_load_tbu (CPUPPCState *env); void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value); void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value); +uint32_t cpu_ppc_load_atbl (CPUPPCState *env); +uint32_t cpu_ppc_load_atbu (CPUPPCState *env); +void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value); +void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value); uint32_t cpu_ppc_load_decr (CPUPPCState *env); void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); #if defined(TARGET_PPC64H) @@ -798,8 +802,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); #define SPR_BOOKE_SPEFSCR (0x200) #define SPR_E500_BBEAR (0x201) #define SPR_E500_BBTAR (0x202) -#define SPR_BOOKE_ATBL (0x20E) -#define SPR_BOOKE_ATBU (0x20F) +#define SPR_ATBL (0x20E) +#define SPR_ATBU (0x20F) #define SPR_IBAT0U (0x210) #define SPR_BOOKE_IVOR32 (0x210) #define SPR_IBAT0L (0x211) diff --git a/target-ppc/op.c b/target-ppc/op.c index 976eb53..4622534 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -423,6 +423,18 @@ void OPPROTO op_load_tbu (void) RETURN(); } +void OPPROTO op_load_atbl (void) +{ + T0 = cpu_ppc_load_atbl(env); + RETURN(); +} + +void OPPROTO op_load_atbu (void) +{ + T0 = cpu_ppc_load_atbu(env); + RETURN(); +} + #if !defined(CONFIG_USER_ONLY) void OPPROTO op_store_tbl (void) { @@ -436,6 +448,18 @@ void OPPROTO op_store_tbu (void) RETURN(); } +void OPPROTO op_store_atbl (void) +{ + cpu_ppc_store_atbl(env, T0); + RETURN(); +} + +void OPPROTO op_store_atbu (void) +{ + cpu_ppc_store_atbu(env, T0); + RETURN(); +} + void OPPROTO op_load_decr (void) { T0 = cpu_ppc_load_decr(env); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 53a6abf..285e351 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -162,6 +162,18 @@ static void spr_read_tbu (void *opaque, int sprn) gen_op_load_tbu(); } +__attribute__ (( unused )) +static void spr_read_atbl (void *opaque, int sprn) +{ + gen_op_load_atbl(); +} + +__attribute__ (( unused )) +static void spr_read_atbu (void *opaque, int sprn) +{ + gen_op_load_atbu(); +} + #if !defined(CONFIG_USER_ONLY) static void spr_write_tbl (void *opaque, int sprn) { @@ -172,6 +184,18 @@ static void spr_write_tbu (void *opaque, int sprn) { gen_op_store_tbu(); } + +__attribute__ (( unused )) +static void spr_write_atbl (void *opaque, int sprn) +{ + gen_op_store_atbl(); +} + +__attribute__ (( unused )) +static void spr_write_atbu (void *opaque, int sprn) +{ + gen_op_store_atbu(); +} #endif #if !defined(CONFIG_USER_ONLY)