From 76a66253e5e48f1744f689041c1c21cedcaff630 Mon Sep 17 00:00:00 2001 From: j_mayer Date: Wed, 7 Mar 2007 08:32:30 +0000 Subject: Great PowerPC emulation code resynchronisation and improvments: - Add status file to make regression tracking easier - Move all micro-operations helpers definitions into a separate header: should never be seen outside of op.c - Update copyrights - Add new / missing PowerPC CPU definitions - Add definitions for PowerPC BookE - Add support for PowerPC 6xx/7xx software driven TLBs Allow use of PowerPC 603 as an example - Add preliminary code for POWER, POWER2, PowerPC 403, 405, 440, 601, 602 and BookE support - Avoid compiling priviledged only resources support for user-mode emulation - Remove unused helpers / micro-ops / dead code - Add instructions usage statistics dump: useful to figure which instructions need strong optimizations. - Micro-operation fixes: * add missing RETURN in some micro-ops * fix prototypes * use softfloat routines for all floating-point operations * fix tlbie instruction * move some huge micro-operations into helpers - emulation fixes: * fix inverted opcodes for fcmpo / fcmpu * condition register update is always to be done after the whole instruction has completed * add missing NIP updates when calling helpers that may generate an exception - optimizations and improvments: * optimize very often used instructions (li, mr, rlwixx...) * remove specific micro-ops for rarely used instructions * add routines for addresses computations to avoid bugs due to multiple different implementations * fix TB linking: do not reset T0 at the end of every TB. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2473 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ppc.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 22 deletions(-) (limited to 'hw') diff --git a/hw/ppc.c b/hw/ppc.c index b0865c1646..c910cb9f72 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -1,7 +1,7 @@ /* * QEMU generic PPC hardware System Emulator * - * Copyright (c) 2003-2004 Jocelyn Mayer + * Copyright (c) 2003-2007 Jocelyn Mayer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env) { /* TB time in tb periods */ return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, - tb_env->tb_freq, ticks_per_sec); + tb_env->tb_freq, ticks_per_sec); } uint32_t cpu_ppc_load_tbl (CPUState *env) @@ -52,14 +52,14 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) tb = cpu_ppc_get_tb(tb_env); #ifdef DEBUG_TB { - static int last_time; - int now; - now = time(NULL); - if (last_time != now) { - last_time = now; - printf("%s: tb=0x%016lx %d %08lx\n", - __func__, tb, now, tb_env->tb_offset); - } + static int last_time; + int now; + now = time(NULL); + if (last_time != now) { + last_time = now; + printf("%s: tb=0x%016lx %d %08lx\n", + __func__, tb, now, tb_env->tb_offset); + } } #endif @@ -75,6 +75,7 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) #ifdef DEBUG_TB printf("%s: tb=0x%016lx\n", __func__, tb); #endif + return tb >> 32; } @@ -117,6 +118,7 @@ uint32_t cpu_ppc_load_decr (CPUState *env) #if defined(DEBUG_TB) printf("%s: 0x%08x\n", __func__, decr); #endif + return decr; } @@ -146,7 +148,7 @@ static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr, if (is_excp) next += tb_env->decr_next - now; if (next == now) - next++; + next++; tb_env->decr_next = next; /* Adjust timer */ qemu_mod_timer(tb_env->decr_timer, next); @@ -154,7 +156,7 @@ static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr, * raise an exception. */ if ((value & 0x80000000) && !(decr & 0x80000000)) - cpu_ppc_decr_excp(env); + cpu_ppc_decr_excp(env); } void cpu_ppc_store_decr (CPUState *env, uint32_t value) @@ -177,20 +179,64 @@ ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq) return NULL; env->tb_env = tb_env; if (tb_env->tb_freq == 0 || 1) { - tb_env->tb_freq = freq; - /* Create new timer */ - tb_env->decr_timer = + tb_env->tb_freq = freq; + /* Create new timer */ + tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env); - /* There is a bug in 2.4 kernels: - * if a decrementer exception is pending when it enables msr_ee, - * it's not ready to handle it... - */ - _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); + /* There is a bug in Linux 2.4 kernels: + * if a decrementer exception is pending when it enables msr_ee, + * it's not ready to handle it... + */ + _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); } return tb_env; } +/* Specific helpers for POWER & PowerPC 601 RTC */ +ppc_tb_t *cpu_ppc601_rtc_init (CPUState *env) +{ + return cpu_ppc_tb_init(env, 7812500); +} + +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; +} + +/* Embedded PowerPC timers */ +target_ulong load_40x_pit (CPUState *env) +{ + /* XXX: TODO */ + return 0; +} + +void store_40x_pit (CPUState *env, target_ulong val) +{ + /* XXX: TODO */ +} + +void store_booke_tcr (CPUState *env, target_ulong val) +{ + /* XXX: TODO */ +} + +void store_booke_tsr (CPUState *env, target_ulong val) +{ + /* XXX: TODO */ +} + #if 0 /*****************************************************************************/ /* Handle system reset (for now, just stop emulation) */ @@ -264,6 +310,7 @@ uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr) tmp |= m48t59_read(nvram, addr + 1) << 16; tmp |= m48t59_read(nvram, addr + 2) << 8; tmp |= m48t59_read(nvram, addr + 3); + return tmp; } @@ -316,10 +363,10 @@ uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count) odd = count & 1; count &= ~1; for (i = 0; i != count; i++) { - crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); + crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); } if (odd) { - crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); + crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); } return crc; -- cgit v1.2.1