#include "cpummu030.h"
#include "ar.h"
#include "ppc/ppcd.h"
+#include "uae/ppc.h"
int debugger_active;
static uaecptr skipaddr_start, skipaddr_end;
return mem_banks[addr >> 16]->xlateaddr (addr);
}
-static void memory_map_dump_2 (int log)
+#if 0
+#define UAE_MEMORY_REGIONS_MAX 64
+#define UAE_MEMORY_REGION_NAME_LENGTH 64
+
+#define UAE_MEMORY_REGION_RAM (1 << 0)
+#define UAE_MEMORY_REGION_ALIAS (1 << 1)
+#define UAE_MEMORY_REGION_MIRROR (1 << 2)
+
+typedef struct UaeMemoryRegion {
+ uaecptr start;
+ int size;
+ TCHAR name[UAE_MEMORY_REGION_NAME_LENGTH];
+ TCHAR rom_name[UAE_MEMORY_REGION_NAME_LENGTH];
+ uaecptr alias;
+ int flags;
+} UaeMemoryRegion;
+
+typedef struct UaeMemoryMap {
+ UaeMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
+ int num_regions;
+} UaeMemoryMap;
+#endif
+
+static void memory_map_dump_3(UaeMemoryMap *map, int log)
{
bool imold;
int i, j, max;
addrbank *a1 = mem_banks[0];
TCHAR txt[256];
+ map->num_regions = 0;
imold = currprefs.illegal_mem;
currprefs.illegal_mem = false;
max = currprefs.address_space_24 ? 256 : 65536;
int k, mirrored, mirrored2, size, size_out;
TCHAR size_ext;
uae_u8 *caddr;
- const TCHAR *name;
TCHAR tmp[MAX_DPATH];
- name = a1->name;
- if (name == NULL)
+ const TCHAR *name = a1->name;
+ if (name == NULL) {
name = _T("<none>");
+ }
k = j;
caddr = dump_xlate (k << 16);
size_out /= 1024;
size_ext = 'M';
}
+#if 1
_stprintf (txt, _T("%08X %7d%c/%d = %7d%c %s"), j << 16, size_out, size_ext,
mirrored, mirrored ? size_out / mirrored : size_out, size_ext, name);
-
+#endif
tmp[0] = 0;
if (a1->flags == ABFLAG_ROM && mirrored) {
TCHAR *p = txt + _tcslen (txt);
_tcscat (tmp, _T("\n"));
}
}
+
+ int region_size = ((i - j) << 16) / mirrored2;
+ for (int m = 0; m < mirrored2; m++) {
+ UaeMemoryRegion *r = &map->regions[map->num_regions];
+ r->start = (j << 16) + region_size * m;
+ r->size = region_size;
+ r->flags = 0;
+ r->memory = NULL;
+ if (mirrored > 0) {
+ r->flags |= UAE_MEMORY_REGION_RAM;
+ r->memory = caddr;
+ }
+ /* just to make it easier to spot in debugger */
+ r->alias = 0xffffffff;
+ if (m >= 0) {
+ r->alias = j << 16;
+ r->flags |= UAE_MEMORY_REGION_ALIAS | UAE_MEMORY_REGION_MIRROR;
+ }
+ _stprintf(r->name, _T("%s"), name);
+ _stprintf(r->rom_name, _T("%s"), tmp);
+ map->num_regions += 1;
+ }
+
+#if 1
_tcscat (txt, _T("\n"));
if (log)
write_log (txt);
else
console_out (tmp);
}
+#endif
j = i;
a1 = a2;
}
}
currprefs.illegal_mem = imold;
}
-void memory_map_dump (void)
+
+void uae_memory_map(UaeMemoryMap *map)
{
- memory_map_dump_2 (1);
+ memory_map_dump_3(map, 0);
+}
+
+static void memory_map_dump_2 (int log)
+{
+ UaeMemoryMap map;
+ memory_map_dump_3(&map, log);
+#if 0
+ for (int i = 0; i < map.num_regions; i++) {
+ TCHAR txt[256];
+ UaeMemoryRegion *r = &map.regions[i];
+ int size = r->size / 1024;
+ TCHAR size_ext = 'K';
+ int mirrored = 1;
+ int size_out = 0;
+ _stprintf (txt, _T("%08X %7u%c/%d = %7u%c %s\n"), r->start, size, size_ext,
+ r->flags & UAE_MEMORY_REGION_RAM, size, size_ext, r->name);
+ if (log)
+ write_log (_T("%s"), txt);
+ else
+ console_out (txt);
+ if (r->rom_name[0]) {
+ if (log)
+ write_log (_T("%s"), r->rom_name);
+ else
+ console_out (r->rom_name);
+ }
+ }
+#endif
+}
+
+void memory_map_dump (void)
+ {
+ memory_map_dump_2 (1);
}
STATIC_INLINE uaecptr BPTR2APTR (uaecptr addr)
get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1),
get_long_debug(list + 16 + 6), rom_vector,
get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1));
- if (1 || (type & 0x10)) {
+ if ((type & 0x10)) {
uae_u8 diagarea[32];
uae_u16 nameoffset;
uaecptr rom = addr + rom_vector;
}
wasactive = ismouseactive ();
+#ifdef WITH_PPC
+ uae_ppc_pause(1);
+#endif
inputdevice_unacquire ();
pause_sound ();
setmouseactive (0);
}
resume_sound ();
inputdevice_acquire (TRUE);
+#ifdef WITH_PPC
+ uae_ppc_pause(0);
+#endif
setmouseactive (wasactive ? 2 : 0);
}
#include <dlfcn.h>
#endif
-UAE_DLHANDLE uae_dlopen(const TCHAR *path) {
-#ifdef _WIN32
- UAE_DLHANDLE result = LoadLibrary(path);
+UAE_DLHANDLE uae_dlopen(const TCHAR *path)
+{
+ UAE_DLHANDLE result;
+#ifdef WINUAE
+ extern HMODULE WIN32_LoadLibrary(const TCHAR *name);
+ result = WIN32_LoadLibrary(path);
+#elif _WIN32
+ result = LoadLibrary(path);
#else
- UAE_DLHANDLE result = dlopen(path, RTLD_NOW);
+ result = dlopen(path, RTLD_NOW);
const char *error = dlerror();
if (error != NULL) {
write_log("uae_dlopen failed: %s\n", error);
extern uae_s32 getz2size (struct uae_prefs *p);
extern ULONG getz2endaddr (void);
+#define UAE_MEMORY_REGIONS_MAX 64
+#define UAE_MEMORY_REGION_NAME_LENGTH 64
+
+#define UAE_MEMORY_REGION_RAM (1 << 0)
+#define UAE_MEMORY_REGION_ALIAS (1 << 1)
+#define UAE_MEMORY_REGION_MIRROR (1 << 2)
+
+/* Get a list of memory regions in the Amiga address space */
+
+typedef struct UaeMemoryRegion {
+ uaecptr start;
+ int size;
+ TCHAR name[UAE_MEMORY_REGION_NAME_LENGTH];
+ TCHAR rom_name[UAE_MEMORY_REGION_NAME_LENGTH];
+ uaecptr alias;
+ int flags;
+ uae_u8 *memory;
+} UaeMemoryRegion;
+
+typedef struct UaeMemoryMap {
+ UaeMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
+ int num_regions;
+} UaeMemoryMap;
+
+void uae_memory_map(UaeMemoryMap *map);
+
#endif /* MEMORY_H */
+++ /dev/null
-#ifndef UAE_PPC_H
-#define UAE_PPC_H
-
-/*
- * This file only consists of default includes, so it can safely be included
- * in other projects (PearPC, QEmu) without pulling in lots of headers.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-
-/* PPC_EXTERN_C is defined (on the UAE side) when compiling with QEmu CPU. */
-#ifndef PPC_EXTERN_C
-/*
- * If it is not defined, we are either compiling "on the QEmu side (C)", or
- * the file is used with the PearPC implementation. In both cases,
- * PPC_EXTERN_C should expand to nothing.
- */
-#define PPC_EXTERN_C
-#endif
-
-/* UAE PPC functions */
-
-void uae_ppc_doze(void);
-void uae_ppc_sync (void);
-void uae_ppc_crash(void);
-
-void uae_ppc_cpu_reboot(void);
-void uae_ppc_cpu_stop(void);
-bool uae_ppc_poll_queue(void);
-void uae_ppc_interrupt(bool active);
-void uae_ppc_cpu_lock(void);
-bool uae_ppc_cpu_unlock(void);
-void uae_ppc_to_main_thread(void);
-void uae_ppc_emulate(void);
-void uae_ppc_reset(bool hardreset);
-void uae_ppc_hsync_handler(void);
-void uae_ppc_wakeup(void);
-
-#define PPC_STATE_STOP 0
-#define PPC_STATE_ACTIVE 1
-#define PPC_STATE_SLEEP 2
-#define PPC_STATE_CRASH 3
-
-extern volatile int ppc_state;
-
-#ifdef __cplusplus
-bool uae_ppc_direct_physical_memory_handle(uint32_t addr, uint8_t *&ptr);
-#endif
-
-PPC_EXTERN_C bool uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size);
-PPC_EXTERN_C bool uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size);
-
-bool uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data);
-bool uae_ppc_io_mem_write64(uint32_t addr, uint64_t data);
-
-extern int ppc_cycle_count;
-
-/* PPC CPU implementation */
-
-PPC_EXTERN_C bool ppc_cpu_init(uint32_t pvr);
-PPC_EXTERN_C void ppc_cpu_free(void);
-
-PPC_EXTERN_C void ppc_cpu_stop(void);
-
-PPC_EXTERN_C void ppc_cpu_atomic_raise_ext_exception(void);
-PPC_EXTERN_C void ppc_cpu_atomic_cancel_ext_exception(void);
-
-PPC_EXTERN_C void ppc_cpu_map_memory(uint32_t addr, uint32_t size, void *memory, const char *name);
-
-PPC_EXTERN_C void ppc_cpu_set_pc(int cpu, uint32_t value);
-PPC_EXTERN_C void ppc_cpu_run_continuous(void);
-PPC_EXTERN_C void ppc_cpu_run_single(int count);
-
-PPC_EXTERN_C uint64_t ppc_cpu_get_dec(void);
-PPC_EXTERN_C void ppc_cpu_do_dec(int value);
-
-#if 0
-uint32 ppc_cpu_get_gpr(int cpu, int i);
-void ppc_cpu_set_gpr(int cpu, int i, uint32 newvalue);
-void ppc_cpu_set_msr(int cpu, uint32 newvalue);
-uint32 ppc_cpu_get_pc(int cpu);
-uint32 ppc_cpu_get_pvr(int cpu);
-#endif
-
-#endif // UAE_PPC_H
void uae_ppc_interrupt(bool active);
void uae_ppc_cpu_lock(void);
bool uae_ppc_cpu_unlock(void);
-void uae_ppc_to_main_thread(void);
+bool uae_ppc_to_main_thread(void);
void uae_ppc_emulate(void);
void uae_ppc_reset(bool hardreset);
void uae_ppc_hsync_handler(void);
void uae_ppc_wakeup(void);
+/**
+ * Pauses the PPC emulation (for some implementations). Currently triggers
+ * a simple pause implementation intended only for debugging.
+ * @param pause Whether to pause (1) or not (0).
+ */
+void uae_ppc_pause(int pause);
#ifdef __cplusplus
bool uae_ppc_direct_physical_memory_handle(uint32_t addr, uint8_t *&ptr);
/* Prototypes for PPC CPU implementation, used by PearPC and QEmu */
+typedef struct PPCMemoryRegion {
+ uint32_t start;
+ uint32_t size;
+ void *memory;
+ const char *name;
+ uint32_t alias;
+} PPCMemoryRegion;
+
bool PPCCALL ppc_cpu_init(uint32_t pvr);
void PPCCALL ppc_cpu_free(void);
void PPCCALL ppc_cpu_stop(void);
void PPCCALL ppc_cpu_atomic_raise_ext_exception(void);
void PPCCALL ppc_cpu_atomic_cancel_ext_exception(void);
-void PPCCALL ppc_cpu_map_memory(uint32_t addr, uint32_t size, void *memory, const char *name);
+void PPCCALL ppc_cpu_map_memory(PPCMemoryRegion *regions, int count);
void PPCCALL ppc_cpu_set_pc(int cpu, uint32_t value);
void PPCCALL ppc_cpu_run_continuous(void);
void PPCCALL ppc_cpu_run_single(int count);
uint64_t PPCCALL ppc_cpu_get_dec(void);
void PPCCALL ppc_cpu_do_dec(int value);
+void PPCCALL ppc_cpu_pause(int pause);
/* Other PPC defines */
static bool haltloop(void)
{
#ifdef WITH_PPC
+ bool ppc_main_thread = false;
// m68k stopped? Move PPC emulator to main thread.
if (regs.halted < 0) {
- uae_ppc_to_main_thread();
+ ppc_main_thread = uae_ppc_to_main_thread();
}
#endif
do_copper();
#ifdef WITH_PPC
- if (regs.halted < 0)
+ if (ppc_main_thread && regs.halted < 0)
uae_ppc_emulate();
else
uae_ppc_poll_check();
#endif
#define PPC_SYNC_WRITE 0
-#define PPC_ACCESS_LOG 2
+#define PPC_ACCESS_LOG 0
#define TRACE(format, ...) write_log(_T("PPC: ---------------- ") format, ## __VA_ARGS__)
static volatile int ppc_cpu_lock_state;
static bool ppc_main_thread;
static bool ppc_init_done;
+static int ppc_implementation;
#define CSPPC_PVR 0x00090204
#define BLIZZPPC_PVR 0x00070101
static void PPCCALL dummy_ppc_cpu_stop(void) { }
static void PPCCALL dummy_ppc_cpu_atomic_raise_ext_exception(void) { }
static void PPCCALL dummy_ppc_cpu_atomic_cancel_ext_exception(void) { }
-static void PPCCALL dummy_ppc_cpu_map_memory(uint32_t addr, uint32_t size, void *memory, const char *name) { }
+static void PPCCALL dummy_ppc_cpu_map_memory(PPCMemoryRegion *regions, int count) { }
static void PPCCALL dummy_ppc_cpu_set_pc(int cpu, uint32_t value) { }
static void PPCCALL dummy_ppc_cpu_run_continuous(void) { }
static void PPCCALL dummy_ppc_cpu_run_single(int count) { }
static uint64_t PPCCALL dummy_ppc_cpu_get_dec(void) { return 0; }
static void PPCCALL dummy_ppc_cpu_do_dec(int value) { }
+static void PPCCALL dummy_ppc_cpu_pause(int pause)
+{
+}
+
/* Functions typedefs for PPC implementation */
typedef bool (PPCCALL *ppc_cpu_init_function)(uint32_t pvr);
typedef void (PPCCALL *ppc_cpu_stop_function)(void);
typedef void (PPCCALL *ppc_cpu_atomic_raise_ext_exception_function)(void);
typedef void (PPCCALL *ppc_cpu_atomic_cancel_ext_exception_function)(void);
-typedef void (PPCCALL *ppc_cpu_map_memory_function)(uint32_t addr, uint32_t size, void *memory, const char *name);
+typedef void (PPCCALL *ppc_cpu_map_memory_function)(PPCMemoryRegion *regions, int count);
typedef void (PPCCALL *ppc_cpu_set_pc_function)(int cpu, uint32_t value);
typedef void (PPCCALL *ppc_cpu_run_continuous_function)(void);
typedef void (PPCCALL *ppc_cpu_run_single_function)(int count);
typedef uint64_t (PPCCALL *ppc_cpu_get_dec_function)(void);
typedef void (PPCCALL *ppc_cpu_do_dec_function)(int value);
+typedef void (PPCCALL *ppc_cpu_pause_function)(int pause);
/* Function pointers to active PPC implementation */
static ppc_cpu_run_single_function g_ppc_cpu_run_single;
static ppc_cpu_get_dec_function g_ppc_cpu_get_dec;
static ppc_cpu_do_dec_function g_ppc_cpu_do_dec;
+static ppc_cpu_pause_function g_ppc_cpu_pause;
static void load_dummy_implementation()
{
g_ppc_cpu_run_single = dummy_ppc_cpu_run_single;
g_ppc_cpu_get_dec = dummy_ppc_cpu_get_dec;
g_ppc_cpu_do_dec = dummy_ppc_cpu_do_dec;
+ g_ppc_cpu_pause = dummy_ppc_cpu_pause;
}
#ifdef WITH_QEMU_CPU
g_ppc_cpu_run_single = (ppc_cpu_run_single_function) uae_dlsym(handle, "ppc_cpu_run_single");
g_ppc_cpu_get_dec = (ppc_cpu_get_dec_function) uae_dlsym(handle, "ppc_cpu_get_dec");
g_ppc_cpu_do_dec = (ppc_cpu_do_dec_function) uae_dlsym(handle, "ppc_cpu_do_dec");
+ g_ppc_cpu_pause = (ppc_cpu_pause_function) uae_dlsym(handle, "ppc_cpu_pause");
#if 0
/* register callback functions */
static void load_ppc_implementation()
{
int impl = currprefs.ppc_implementation;
-#ifdef WITH_PEARPC_CPU
- if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_PEARPC) {
- if (load_pearpc_implementation()) {
+#ifdef WITH_QEMU_CPU
+ if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_QEMU) {
+ if (load_qemu_implementation()) {
+ ppc_implementation = PPC_IMPLEMENTATION_QEMU;
return;
}
}
#endif
-#ifdef WITH_QEMU_CPU
- if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_QEMU) {
- if (load_qemu_implementation()) {
+#ifdef WITH_PEARPC_CPU
+ if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_PEARPC) {
+ if (load_pearpc_implementation()) {
+ ppc_implementation = PPC_IMPLEMENTATION_PEARPC;
return;
}
}
#endif
load_dummy_implementation();
+ ppc_implementation = 0;
}
static void initialize()
* to allow all memory access to go via callbacks).
*/
- // FIXME: hack, replace with automatic / dynamic mapping
-#if 1
- g_ppc_cpu_map_memory(0x00000000, 2048 KB, NULL, "Chip memory");
- g_ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA");
- g_ppc_cpu_map_memory(0x00F00000, 256 KB, get_real_address(0x00F00000), "CPUBoard F00000");
- g_ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO");
- g_ppc_cpu_map_memory(0x00DF0000, 64 KB, NULL, "Custom chipset");
- g_ppc_cpu_map_memory(0x08000000, 16 MB, get_real_address(0x08000000), "RAMSEY memory (high)");
- g_ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM");
-#else
- g_ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA");
- g_ppc_cpu_map_memory(0x00F00000, 256 KB, NULL, "CPUBoard F00000");
- g_ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO");
- g_ppc_cpu_map_memory(0x08000000, 16 MB, NULL, "RAMSEY memory (high)");
- g_ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM");
-#endif
+ PPCMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
+ UaeMemoryMap map;
+ uae_memory_map(&map);
+
+ for (int i = 0; i < map.num_regions; i++) {
+ UaeMemoryRegion *r = &map.regions[i];
+ regions[i].start = r->start;
+ regions[i].size = r->size;
+ regions[i].name = ua(r->name);
+ regions[i].alias = r->alias;
+ regions[i].memory = r->memory;
+ }
+ g_ppc_cpu_map_memory(regions, map.num_regions);
+ for (int i = 0; i < map.num_regions; i++) {
+ free((void*)regions[i].name);
+ }
}
static void uae_ppc_cpu_reset(void)
return NULL;
}
-void uae_ppc_to_main_thread(void)
+bool uae_ppc_to_main_thread(void)
{
TRACE(_T("uae_ppc_to_main_thread\n"));
+
+ // QEMU: not yet supported
+ if (ppc_implementation == PPC_IMPLEMENTATION_QEMU)
+ return false;
+
if (ppc_thread_running) {
write_log(_T("PPC: transferring PPC emulation to main thread.\n"));
uae_ppc_cpu_stop();
}
ppc_state = PPC_STATE_ACTIVE;
ppc_main_thread = true;
+ return true;
}
void uae_ppc_emulate(void)
{
- TRACE(_T("uae_ppc_emulate\n"));
+ //TRACE(_T("uae_ppc_emulate\n"));
if (ppc_state == PPC_STATE_ACTIVE || ppc_state == PPC_STATE_SLEEP)
g_ppc_cpu_run_single(10);
}
void uae_ppc_wakeup(void)
{
- TRACE(_T("uae_ppc_wakeup\n"));
+ //TRACE(_T("uae_ppc_wakeup\n"));
if (ppc_state == PPC_STATE_SLEEP)
ppc_state = PPC_STATE_ACTIVE;
}
void uae_ppc_interrupt(bool active)
{
- TRACE(_T("uae_ppc_interrupt\n"));
+ //TRACE(_T("uae_ppc_interrupt\n"));
if (active) {
g_ppc_cpu_atomic_raise_ext_exception();
uae_ppc_wakeup();
g_ppc_cpu_do_dec(ppc_cycle_count);
}
}
+
+void uae_ppc_pause(int pause)
+{
+ if (g_ppc_cpu_pause) {
+ g_ppc_cpu_pause(pause);
+ }
+}