diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-07 08:32:30 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-07 08:32:30 +0000 |
commit | 76a66253e5e48f1744f689041c1c21cedcaff630 (patch) | |
tree | c1003bd73ab8e2cbfe4a05c5b3f497bc2573fa4e /hw/ppc.c | |
parent | 1c7b3754f68382941a1921e578ead25d97d116fb (diff) |
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
Diffstat (limited to 'hw/ppc.c')
-rw-r--r-- | hw/ppc.c | 91 |
1 files changed, 69 insertions, 22 deletions
@@ -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; |