diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f361ee5a..9cb32322 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,8 @@ file( GLOB core_files tubevc.h logging.c logging.h + utils.c + utils.h ) # 6502 Co Processor using 65tube Implementation @@ -178,6 +180,36 @@ file( GLOB shared_6809_files tuberom_6809.c ) +# OPC5LS +file( GLOB copro_opc5ls_files + copro-opc5ls.h + copro-opc5ls.c + opc5ls/opc5ls.h + opc5ls/opc5ls.c + opc5ls/tuberom.h + opc5ls/tuberom.c +) + +# OPC6 +file( GLOB copro_opc6_files + copro-opc6.h + copro-opc6.c + opc6/opc6.h + opc6/opc6.c + opc6/tuberom.h + opc6/tuberom.c +) + +# OPC7 +file( GLOB copro_opc7_files + copro-opc7.h + copro-opc7.c + opc7/opc7.h + opc7/opc7.c + opc7/tuberom.h + opc7/tuberom.c +) + # Null co processor file( GLOB copro_null_files copro-null.c @@ -245,6 +277,12 @@ file( GLOB debugger_files mc6809nc/mc6809_dis.h cpu80186/cpu80186_debug.c cpu80186/cpu80186_debug.h + opc5ls/opc5ls_debug.c + opc5ls/opc5ls_debug.h + opc6/opc6_debug.c + opc6/opc6_debug.h + opc7/opc7_debug.c + opc7/opc7_debug.h ) if( ${DEBUG} ) @@ -285,6 +323,9 @@ else() ${copro_6809sc_files} ${copro_6809nc_files} ${shared_6809_files} + ${copro_opc5ls_files} + ${copro_opc6_files} + ${copro_opc7_files} ${copro_null_files} ${copro_arm_files} ${debugger_files} @@ -305,6 +346,9 @@ else() ${copro_6809sc_files} ${copro_6809nc_files} ${shared_6809_files} + ${copro_opc5ls_files} + ${copro_opc6_files} + ${copro_opc7_files} ${copro_null_files} ${copro_arm_files} ) diff --git a/src/armc-start.S b/src/armc-start.S index d6903a68..448d4dc6 100644 --- a/src/armc-start.S +++ b/src/armc-start.S @@ -69,6 +69,7 @@ .global _clean_invalidate_dcache_mva .global _invalidate_dtlb .global _invalidate_dtlb_mva +.global _data_memory_barrier #ifdef HAS_MULTICORE .global _get_core @@ -384,6 +385,16 @@ _invalidate_dtlb_mva: mcr p15, 0, r0, c8, c6, 1 mov pc, lr +.section ".text._data_memory_barrier" +_data_memory_barrier: +#if defined(RPI2) || defined(RPI3) + dmb +#else + mov r0, #0 + mcr p15, 0, r0, c7, c10, 5 +#endif + mov pc, lr + #ifdef USE_MULTICORE _init_core: diff --git a/src/copro-80186.c b/src/copro-80186.c index bd48fe3f..54d70491 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -6,10 +6,15 @@ #include "cpu80186/cpu80186.h" #include "cpu80186/mem80186.h" #include "startup.h" +#include "utils.h" + +extern uint8_t Client86_v1_01[]; static void copro_80186_poweron_reset() { // Wipe memory Cleari80186Ram(); + // Patch the OSWORD &FA code to change FEE5 to FCE5 (8 changes expected) + check_elk_mode_and_patch(Client86_v1_01, 0xE69, 0x1FB, 8); } static void copro_80186_reset() { @@ -29,7 +34,7 @@ int copro_80186_tube_read(uint16_t addr) { return tube_parasite_read(addr); } -void copro_80186_tube_write(uint16_t addr, uint8_t data) { +void copro_80186_tube_write(uint16_t addr, uint8_t data) { tube_parasite_write(addr, data); } diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 247bfa05..e3d96441 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -23,6 +23,8 @@ #include "mame/arm_debug.h" #endif +#define TUBE_ROM_ARM tuberom_arm_v100 + #define RAM_MASK8 ((UINT32) 0x003fffff) #define ROM_MASK8 ((UINT32) 0x00003fff) #define RAM_MASK32 ((UINT32) 0x003ffffc) @@ -60,7 +62,7 @@ UINT8 copro_arm2_read8(int addr) { result = tube_parasite_read((addr >> 2) & 7); break; case 3: - result = *(UINT8*) (tuberom_arm_v100+(addr & ROM_MASK8)); + result = *(UINT8*) (TUBE_ROM_ARM+(addr & ROM_MASK8)); break; default: result = 0; @@ -98,7 +100,7 @@ UINT32 copro_arm2_read32(int addr) result = tube_parasite_read((addr >> 2) & 7); break; case 3: - result = *(UINT32*) (tuberom_arm_v100+(addr & ROM_MASK32)); + result = *(UINT32*) (TUBE_ROM_ARM+(addr & ROM_MASK32)); break; default: result = 0; @@ -180,9 +182,8 @@ static void copro_arm2_poweron_reset() { static void copro_arm2_reset() { // Log ARM performance counters tube_log_performance_counters(); - // Re-instate the Tube ROM on reset - memcpy(arm2_ram, tuberom_arm_v100, 0x4000); - //memcpy(arm2_rom, tuberom_arm_v100, 0x4000); + // Re-instate the reset vector on reset + memcpy(arm2_ram, TUBE_ROM_ARM, 0x4); // Reset the ARM device arm2_device_reset(); // Wait for rst become inactive before continuing to execute diff --git a/src/copro-armnative.c b/src/copro-armnative.c index 4a7ca02c..f858b62a 100644 --- a/src/copro-armnative.c +++ b/src/copro-armnative.c @@ -192,8 +192,8 @@ static void initEnv() { env->handler[ UPCALL_HANDLER].handler = defaultUpcallHandler; // Handlers where the handler is just data - env->handler[ MEMORY_LIMIT_HANDLER].handler = (EnvironmentHandler_type) (2 * 1024 * 1024); - env->handler[ APPLICATION_SPACE_HANDLER].handler = (EnvironmentHandler_type) (3 * 1024 * 1024); + env->handler[ MEMORY_LIMIT_HANDLER].handler = (EnvironmentHandler_type) (16 * 1024 * 1024); + env->handler[ APPLICATION_SPACE_HANDLER].handler = (EnvironmentHandler_type) (16 * 1024 * 1024); env->handler[CURRENTLY_ACTIVE_OBJECT_HANDLER].handler = (EnvironmentHandler_type) (0); } diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index e0a6cdcd..8c616741 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -59,7 +59,7 @@ int copro_lib6502_mem_read(M6502 *mpu, uint16_t addr, uint8_t data) { return data; } -int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data) { +int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data) { if ((addr & 0xfff8) == 0xfef8) { tube_parasite_write(addr, data); } else { @@ -74,7 +74,7 @@ static int copro_lib6502_tube_read(M6502 *mpu, uint16_t addr, uint8_t data) { return tube_parasite_read(addr); } -static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { +static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { tube_parasite_write(addr, data); return 0; } diff --git a/src/copro-opc5ls.c b/src/copro-opc5ls.c new file mode 100644 index 00000000..908c015f --- /dev/null +++ b/src/copro-opc5ls.c @@ -0,0 +1,107 @@ +/* + * OPC5LS Co Pro Emulation + * + * (c) 2017 David Banks + */ +#include +#include +#include +#include "tube-defs.h" +#include "tube-client.h" +#include "tube-ula.h" +#include "opc5ls/opc5ls.h" +#include "opc5ls/tuberom.h" +#include "copro-opc5ls.h" + +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "opc5ls/opc5ls_debug.h" +#endif + +static uint16_t *memory; + +void copro_opc5ls_write(uint16_t addr, uint16_t data) { +#ifdef INCLUDE_DEBUGGER + if (opc5ls_debug_enabled) { + debug_memwrite(&opc5ls_cpu_debug, addr, data, 2); + } +#endif + if ((addr & 0xFFF8) == 0xFEF8) { + tube_parasite_write(addr & 7, data); + DBG_PRINT("write: %d = %x\r\n", addr & 7, data); + } else { + memory[addr] = data; + } +} + +uint16_t copro_opc5ls_read(uint16_t addr) { + uint16_t data; + if ((addr & 0xFFF8) == 0xFEF8) { + data = tube_parasite_read(addr & 7); + DBG_PRINT("read: %d = %x\r\n", addr & 7, data); + } else { + data = memory[addr]; + } +#ifdef INCLUDE_DEBUGGER + if (opc5ls_debug_enabled) { + debug_memread(&opc5ls_cpu_debug, addr, data, 2); + } +#endif + return data; +} + +static void copro_opc5ls_poweron_reset() { + // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) + memory = (uint16_t *) copro_mem_reset(0x20000); + + // Initialize the CPU + opc5ls_init(memory, 0xfffc, 0xfffe); + + // Copy over client ROM + memcpy((void *) (memory + 0xF000), (void *)tuberom_opc5ls, sizeof(tuberom_opc5ls)); +} + +static void copro_opc5ls_reset() { + // Log ARM performance counters + tube_log_performance_counters(); + + // Reset the processor + opc5ls_reset(); + + // Wait for rst become inactive before continuing to execute + tube_wait_for_rst_release(); + + // Reset ARM performance counters + tube_reset_performance_counters(); +} + +void copro_opc5ls_emulator() +{ + unsigned int tube_irq_copy; + + // Remember the current copro so we can exit if it changes + int last_copro = copro; + + copro_opc5ls_poweron_reset(); + copro_opc5ls_reset(); + + while (1) { + opc5ls_execute(); + DBG_PRINT("tube_irq = %d\r\n", tube_irq); + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT); + if (tube_irq_copy) { + // Reset the processor on active edge of rst + if ( tube_irq_copy & RESET_BIT ) { + // Exit if the copro has changed + if (copro != last_copro) { + break; + } + copro_opc5ls_reset(); + } + // IRQ is level sensitive so check between every instruction + if ( tube_irq_copy & IRQ_BIT ) { + opc5ls_irq(); + } + } + } +} diff --git a/src/copro-opc5ls.h b/src/copro-opc5ls.h new file mode 100644 index 00000000..ffe53f0d --- /dev/null +++ b/src/copro-opc5ls.h @@ -0,0 +1,17 @@ +// copro-opc5ls.h +#ifndef COPRO_OPC5LS_H +#define COPRO_OPC5LS_H + +// #define DBG + +#ifdef DBG +#define DBG_PRINT(...) printf(__VA_ARGS__) +#else +#define DBG_PRINT(...) +#endif + +extern void copro_opc5ls_write(uint16_t addr, uint16_t data); +extern uint16_t copro_opc5ls_read(uint16_t addr); +extern void copro_opc5ls_emulator(); + +#endif diff --git a/src/copro-opc6.c b/src/copro-opc6.c new file mode 100644 index 00000000..e0d995fd --- /dev/null +++ b/src/copro-opc6.c @@ -0,0 +1,122 @@ +/* + * OPC6 Co Pro Emulation + * + * (c) 2017 David Banks + */ +#include +#include +#include +#include "tube-defs.h" +#include "tube-client.h" +#include "tube-ula.h" +#include "opc6/opc6.h" +#include "opc6/tuberom.h" +#include "copro-opc6.h" + +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "opc6/opc6_debug.h" +#endif + +static uint16_t *memory; + +void copro_opc6_write_mem(uint16_t addr, uint16_t data) { +#ifdef INCLUDE_DEBUGGER + if (opc6_debug_enabled) { + debug_memwrite(&opc6_cpu_debug, addr, data, 2); + } +#endif + memory[addr] = data; +} + +uint16_t copro_opc6_read_mem(uint16_t addr) { + uint16_t data = memory[addr]; +#ifdef INCLUDE_DEBUGGER + if (opc6_debug_enabled) { + debug_memread(&opc6_cpu_debug, addr, data, 2); + } +#endif + return data; +} + +void copro_opc6_write_io(uint16_t addr, uint16_t data) { +#ifdef INCLUDE_DEBUGGER + if (opc6_debug_enabled) { + debug_iowrite(&opc6_cpu_debug, addr, data, 2); + } +#endif + if ((addr & 0xFFF8) == 0xFEF8) { + tube_parasite_write(addr & 7, data); + DBG_PRINT("write: %d = %x\r\n", addr & 7, data); + } +} + +uint16_t copro_opc6_read_io(uint16_t addr) { + uint16_t data = 0; + if ((addr & 0xFFF8) == 0xFEF8) { + data = tube_parasite_read(addr & 7); + DBG_PRINT("read: %d = %x\r\n", addr & 7, data); + } +#ifdef INCLUDE_DEBUGGER + if (opc6_debug_enabled) { + debug_ioread(&opc6_cpu_debug, addr, data, 2); + } +#endif + return data; +} + +static void copro_opc6_poweron_reset() { + // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) + memory = (uint16_t *) copro_mem_reset(0x20000); + + // Initialize the CPU + opc6_init(memory, 0xfffc, 0xfffe, 0x0000); + + // Copy over client ROM + memcpy((void *) (memory + 0xF800), (void *)tuberom_opc6, sizeof(tuberom_opc6)); +} + +static void copro_opc6_reset() { + // Log ARM performance counters + tube_log_performance_counters(); + + // Reset the processor + opc6_reset(); + + // Wait for rst become inactive before continuing to execute + tube_wait_for_rst_release(); + + // Reset ARM performance counters + tube_reset_performance_counters(); +} + +void copro_opc6_emulator() +{ + unsigned int tube_irq_copy; + + // Remember the current copro so we can exit if it changes + int last_copro = copro; + + copro_opc6_poweron_reset(); + copro_opc6_reset(); + + while (1) { + opc6_execute(); + DBG_PRINT("tube_irq = %d\r\n", tube_irq); + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT); + if (tube_irq_copy) { + // Reset the processor on active edge of rst + if ( tube_irq_copy & RESET_BIT ) { + // Exit if the copro has changed + if (copro != last_copro) { + break; + } + copro_opc6_reset(); + } + // IRQ is level sensitive so check between every instruction + if ( tube_irq_copy & IRQ_BIT ) { + opc6_irq(0); + } + } + } +} diff --git a/src/copro-opc6.h b/src/copro-opc6.h new file mode 100644 index 00000000..df8cbc29 --- /dev/null +++ b/src/copro-opc6.h @@ -0,0 +1,19 @@ +// copro-opc6.h +#ifndef COPRO_OPC6_H +#define COPRO_OPC6_H + +// #define DBG + +#ifdef DBG +#define DBG_PRINT(...) printf(__VA_ARGS__) +#else +#define DBG_PRINT(...) +#endif + +extern void copro_opc6_write_mem(uint16_t addr, uint16_t data); +extern uint16_t copro_opc6_read_mem(uint16_t addr); +extern void copro_opc6_write_io(uint16_t addr, uint16_t data); +extern uint16_t copro_opc6_read_io(uint16_t addr); +extern void copro_opc6_emulator(); + +#endif diff --git a/src/copro-opc7.c b/src/copro-opc7.c new file mode 100644 index 00000000..5784a8fa --- /dev/null +++ b/src/copro-opc7.c @@ -0,0 +1,124 @@ +/* + * OPC7 Co Pro Emulation + * + * (c) 2017 Ed Spittles after David Banks + */ +#include +#include +#include +#include "tube-defs.h" +#include "tube-client.h" +#include "tube-ula.h" +#include "opc7/opc7.h" +#include "opc7/tuberom.h" +#include "copro-opc7.h" + +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "opc7/opc7_debug.h" +#endif + +static uint32_t *memory; + +void copro_opc7_write_mem(uint32_t addr, uint32_t data) { + addr &= 0xFFFFF; +#ifdef INCLUDE_DEBUGGER + if (opc7_debug_enabled) { + debug_memwrite(&opc7_cpu_debug, addr, data, 4); + } +#endif + memory[addr] = data; +} + +uint32_t copro_opc7_read_mem(uint32_t addr) { + addr &= 0xFFFFF; + uint32_t data = memory[addr]; +#ifdef INCLUDE_DEBUGGER + if (opc7_debug_enabled) { + debug_memread(&opc7_cpu_debug, addr, data, 4); + } +#endif + return data; +} + +void copro_opc7_write_io(uint32_t addr, uint32_t data) { +#ifdef INCLUDE_DEBUGGER + if (opc7_debug_enabled) { + debug_iowrite(&opc7_cpu_debug, addr, data, 2); + } +#endif + if ((addr & 0xFFF8) == 0xFEF8) { + tube_parasite_write(addr & 7, data); + DBG_PRINT("write: %d = %x\r\n", addr & 7, data); + } +} + +uint32_t copro_opc7_read_io(uint32_t addr) { + uint32_t data = 0; + if ((addr & 0xFFF8) == 0xFEF8) { + data = tube_parasite_read(addr & 7); + DBG_PRINT("read: %d = %x\r\n", addr & 7, data); + } +#ifdef INCLUDE_DEBUGGER + if (opc7_debug_enabled) { + debug_ioread(&opc7_cpu_debug, addr, data, 2); + } +#endif + return data; +} + +static void copro_opc7_poweron_reset() { + // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) + memory = (uint32_t *) copro_mem_reset(0x20000); + + // Initialize the CPU + opc7_init(memory, 0x0000, 0x0002, 0x0000); + + // Copy over client ROM + memcpy((void *) (memory + 0x0000), (void *)tuberom_opc7, sizeof(tuberom_opc7)); +} + +static void copro_opc7_reset() { + // Log ARM performance counters + tube_log_performance_counters(); + + // Reset the processor + opc7_reset(); + + // Wait for rst become inactive before continuing to execute + tube_wait_for_rst_release(); + + // Reset ARM performance counters + tube_reset_performance_counters(); +} + +void copro_opc7_emulator() +{ + unsigned int tube_irq_copy; + + // Remember the current copro so we can exit if it changes + int last_copro = copro; + + copro_opc7_poweron_reset(); + copro_opc7_reset(); + + while (1) { + opc7_execute(); + DBG_PRINT("tube_irq = %d\r\n", tube_irq); + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT); + if (tube_irq_copy) { + // Reset the processor on active edge of rst + if ( tube_irq_copy & RESET_BIT ) { + // Exit if the copro has changed + if (copro != last_copro) { + break; + } + copro_opc7_reset(); + } + // IRQ is level sensitive so check between every instruction + if ( tube_irq_copy & IRQ_BIT ) { + opc7_irq(0); + } + } + } +} diff --git a/src/copro-opc7.h b/src/copro-opc7.h new file mode 100644 index 00000000..1a7d9780 --- /dev/null +++ b/src/copro-opc7.h @@ -0,0 +1,19 @@ +// copro-opc7.h +#ifndef COPRO_OPC7_H +#define COPRO_OPC7_H + +// #define DBG + +#ifdef DBG +#define DBG_PRINT(...) printf(__VA_ARGS__) +#else +#define DBG_PRINT(...) +#endif + +extern void copro_opc7_write_mem(uint32_t addr, uint32_t data); +extern uint32_t copro_opc7_read_mem(uint32_t addr); +extern void copro_opc7_write_io(uint32_t addr, uint32_t data); +extern uint32_t copro_opc7_read_io(uint32_t addr); +extern void copro_opc7_emulator(); + +#endif diff --git a/src/copro-z80.c b/src/copro-z80.c index 555228df..93d8b9ea 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -11,6 +11,7 @@ #include "yaze/mem_mmu.h" #include "yaze/simz80.h" #include "tube-client.h" +#include "utils.h" #ifdef INCLUDE_DEBUGGER #include "cpu_debug.h" @@ -20,7 +21,7 @@ static int overlay_rom = 0; static unsigned char *copro_z80_ram; -static const unsigned char copro_z80_rom[0x1000] = { +static unsigned char copro_z80_rom[0x1000] = { 0xf3, 0x11, 0x00, 0xf0, 0x21, 0x00, 0x00, 0x01, 0x00, 0x10, 0xed, 0xb0, 0xc3, 0x80, 0xf2, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x41, 0x63, 0x6f, 0x72, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x31, 0x39, @@ -357,6 +358,9 @@ void copro_z80_emulator() // Remember the current copro so we can exit if it changes int last_copro = copro; + // Patch the OSWORD &FF code to change FEE5 to FCE5 (2 changes expected) + check_elk_mode_and_patch(copro_z80_rom, 0xD30, 0xAA, 2); + copro_z80_ram = copro_mem_reset(0x10000); copro_z80_reset(); diff --git a/src/cpu_debug.h b/src/cpu_debug.h index bac209ac..0d15f453 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -6,6 +6,10 @@ #include #include +#define WIDTH_8BITS 0 +#define WIDTH_16BITS 1 +#define WIDTH_32BITS 2 + typedef struct { const char *cpu_name; // Name/model of CPU. int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. @@ -21,6 +25,8 @@ typedef struct { void (*reg_parse)(int which, char *strval); // Parse a value into a register. uint32_t (*get_instr_addr)(); // Returns the base address of the currently executing instruction const char **trap_names; // Null terminated list of other reasons a CPU may trap to the debugger. + const int mem_width; // Width of value returned from memread(): 0=8-bit, 1=16-bit, 2=32-bit + const int io_width; // Width of value returned from ioread(): 0=8-bit, 1=16-bit, 2=32-bit } cpu_debug_t; extern void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 6b084c46..79ca7ef8 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -15,6 +15,9 @@ #include "../mc6809nc/mc6809_debug.h" #include "../mame/arm_debug.h" #include "../NS32016/32016_debug.h" +#include "../opc5ls/opc5ls_debug.h" +#include "../opc6/opc6_debug.h" +#include "../opc7/opc7_debug.h" #define USE_LINENOISE @@ -32,16 +35,16 @@ cpu_debug_t *cpu_debug_list[] = { &lib6502_cpu_debug, // 2 lib6502 &lib6502_cpu_debug, // 3 lib6502 &simz80_cpu_debug, // 4 Z80 - &simz80_cpu_debug, // 5 Z80 - &simz80_cpu_debug, // 6 Z80 - &simz80_cpu_debug, // 7 Z80 + &opc5ls_cpu_debug, // 5 OPC5LS + &opc6_cpu_debug, // 6 OPC6 + &opc7_cpu_debug, // 7 OPC7 &cpu80186_cpu_debug, // 8 80x86 &mc6809nc_cpu_debug, // 9 6809 - NULL, // 10 unused - NULL, // 11 unused + NULL, // 10 unused + NULL, // 11 unused (PDP11 future?) &arm2_cpu_debug, // 12 ARM2 &n32016_cpu_debug, // 13 32016 - NULL, // 14 unsed + NULL, // 14 unused NULL, // 15 Native ARM }; @@ -203,7 +206,6 @@ static uint32_t next_addr; // The current memory address (e.g. used when disassembling) static unsigned int memAddr = 0; -extern cpu_debug_t arm2_cpu_debug; cpu_debug_t *getCpu() { return cpu_debug_list[copro]; } @@ -236,6 +238,18 @@ static void iowrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { internal = 0; } +static char *format_hex(const int width, uint32_t i) { + static char result[10]; + if (width == WIDTH_32BITS) { + sprintf(result, "%08"PRIx32, i); + } else if (width == WIDTH_16BITS) { + sprintf(result, "%04"PRIx32, i); + } else { + sprintf(result, "%02"PRIx32, i); + } + return result; +} + /******************************************************** * Hooks from CPU Emulation ********************************************************/ @@ -267,7 +281,9 @@ static void cpu_continue() { static void disassemble_addr(uint32_t addr) { cpu_debug_t *cpu = getCpu(); + internal = 1; next_addr = cpu->disassemble(addr, strbuf, sizeof(strbuf)); + internal = 0; noprompt(); printf("%s\r\n", &strbuf[0]); prompt(); @@ -505,8 +521,10 @@ static void doCmdDis(char *params) { cpu_debug_t *cpu = getCpu(); int i; sscanf(params, "%x", &memAddr); - for (i = 0; i < 10; i++) { + for (i = 0; i < 10; i++) { + internal = 1; memAddr = cpu->disassemble(memAddr, strbuf, sizeof(strbuf)); + internal = 0; printf("%s\r\n", &strbuf[0]); } } @@ -519,7 +537,7 @@ static void doCmdFill(char *params) { unsigned int data; sscanf(params, "%x %x %x", &start, &end, &data); - printf("Wr: %x to %x = %02x\r\n", start, end, data); + printf("Wr: %x to %x = %s\r\n", start, end, format_hex(cpu->mem_width, data)); for (i = start; i <= end; i++) { memwrite(cpu, i, data); } @@ -558,7 +576,7 @@ static void doCmdMem(char *params) { } printf("%04x ", memAddr + i); for (j = 0; j < 16; j++) { - printf("%02x ", row[j]); + printf("%s ", format_hex(cpu->mem_width, row[j])); } printf(" "); for (j = 0; j < 16; j++) { @@ -579,7 +597,7 @@ static void doCmdRd(char *params) { unsigned int data; sscanf(params, "%x", &addr); data = memread(cpu, addr); - printf("Rd Mem: %x = %02x\r\n", addr, data); + printf("Rd Mem: %x = %s\r\n", addr, format_hex(cpu->mem_width, data)); } static void doCmdWr(char *params) { @@ -587,7 +605,7 @@ static void doCmdWr(char *params) { unsigned int addr; unsigned int data; sscanf(params, "%x %x", &addr, &data); - printf("Wr Mem: %x = %02x\r\n", addr, data); + printf("Wr Mem: %x = %s\r\n", addr, format_hex(cpu->mem_width, data)); memwrite(cpu, addr++, data); } @@ -597,7 +615,7 @@ static void doCmdIn(char *params) { unsigned int data; sscanf(params, "%x", &addr); data = ioread(cpu, addr); - printf("Rd IO: %x = %02x\r\n", addr, data); + printf("Rd IO: %x = %s\r\n", addr, format_hex(cpu->io_width, data)); } static void doCmdOut(char *params) { @@ -605,7 +623,7 @@ static void doCmdOut(char *params) { unsigned int addr; unsigned int data; sscanf(params, "%x %x", &addr, &data); - printf("Wr IO: %x = %02x\r\n", addr, data); + printf("Wr IO: %x = %s\r\n", addr, format_hex(cpu->io_width, data)); iowrite(cpu, addr++, data); } diff --git a/src/lib6502.c b/src/lib6502.c index 5c860070..5d174a75 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -103,7 +103,7 @@ byte tmpr; #define getMemory(ADDR) \ tmpr = ( readCallback[ADDR] \ - ? readCallback[ADDR](mpu, ADDR, 0) \ + ? readCallback[ADDR](mpu, ADDR, 0) \ : MEM(ADDR) ) ; \ if (lib6502_debug_enabled) { \ externalise(); \ @@ -152,7 +152,7 @@ byte tmpr; #define abs(ticks) \ tick(ticks); \ - ea= MEM(PC) + (MEM(PC + 1) << 8); \ + ea= MEM(PC) + (MEM(PC + 1) << 8); \ PC += 2; #define relative(ticks) \ @@ -178,14 +178,14 @@ byte tmpr; #define absx(ticks) \ tick(ticks); \ - ea= MEM(PC) + (MEM(PC + 1) << 8); \ + ea= MEM(PC) + (MEM(PC + 1) << 8); \ PC += 2; \ tickIf((ticks == 4) && ((ea >> 8) != ((ea + X) >> 8))); \ ea += X; #define absy(ticks) \ tick(ticks); \ - ea= MEM(PC) + (MEM(PC + 1) << 8); \ + ea= MEM(PC) + (MEM(PC + 1) << 8); \ PC += 2; \ tickIf((ticks == 4) && ((ea >> 8) != ((ea + Y) >> 8))); \ ea += Y @@ -224,7 +224,7 @@ byte tmpr; tick(ticks); \ { \ word tmp; \ - tmp= MEM(PC ) + (MEM(PC + 1) << 8) + X; \ + tmp= MEM(PC ) + (MEM(PC + 1) << 8) + X; \ ea = MEM(tmp) + (MEM(tmp + 1) << 8); \ } @@ -377,8 +377,8 @@ byte tmpr; fetch(); \ { \ byte B= getMemory(ea); \ - P= (P & ~flagZ) \ - | (((A & B) == 0) << 1); \ + P= (P & ~flagZ) \ + | (((A & B) == 0) << 1); \ } \ next(); @@ -413,7 +413,7 @@ byte tmpr; #define rmb6(ticks, adrmode) rmbN(ticks, adrmode, (1<<6)) #define rmb7(ticks, adrmode) rmbN(ticks, adrmode, (1<<7)) -#define rmbN(ticks, adrmode, mask) \ +#define rmbN(ticks, adrmode, mask) \ adrmode(ticks); \ fetch(); \ { \ @@ -432,7 +432,7 @@ byte tmpr; #define smb6(ticks, adrmode) smbN(ticks, adrmode, (1<<6)) #define smb7(ticks, adrmode) smbN(ticks, adrmode, (1<<7)) -#define smbN(ticks, adrmode, mask) \ +#define smbN(ticks, adrmode, mask) \ adrmode(ticks); \ fetch(); \ { \ @@ -682,9 +682,9 @@ byte tmpr; PC++; \ push(PC >> 8); \ push(PC & 0xff); \ - push(P | flagB | flagX); \ + push(P | flagB | flagX); \ P |= flagI; \ - P &= !flagD; \ + P &= ~flagD; \ { \ byte blo = getMemory(0xfffe); \ byte bhi = getMemory(0xffff); \ diff --git a/src/lib6502.h b/src/lib6502.h index 32185255..4226a700 100644 --- a/src/lib6502.h +++ b/src/lib6502.h @@ -5,14 +5,14 @@ #include #include -typedef struct _M6502 M6502; -typedef struct _M6502_Registers M6502_Registers; -typedef struct _M6502_Callbacks M6502_Callbacks; +typedef struct _M6502 M6502; +typedef struct _M6502_Registers M6502_Registers; +typedef struct _M6502_Callbacks M6502_Callbacks; typedef int (*M6502_Callback)(M6502 *mpu, uint16_t address, uint8_t data); -typedef M6502_Callback M6502_CallbackTable[0x10000]; -typedef uint8_t M6502_Memory[0x10000]; +typedef M6502_Callback M6502_CallbackTable[0x10000]; +typedef uint8_t M6502_Memory[0x10000]; // For testing for IRQ typedef int (*M6502_PollInterruptsCallback)(M6502 *mpu); @@ -25,12 +25,12 @@ enum { struct _M6502_Registers { - uint8_t a; /* accumulator */ - uint8_t x; /* X index register */ - uint8_t y; /* Y index register */ - uint8_t p; /* processor status register */ - uint8_t s; /* stack pointer */ - uint16_t pc; /* program counter */ + uint8_t a; /* accumulator */ + uint8_t x; /* X index register */ + uint8_t y; /* Y index register */ + uint8_t p; /* processor status register */ + uint8_t s; /* stack pointer */ + uint16_t pc; /* program counter */ }; struct _M6502_Callbacks @@ -43,9 +43,9 @@ struct _M6502_Callbacks struct _M6502 { M6502_Registers *registers; - uint8_t *memory; + uint8_t *memory; M6502_Callbacks *callbacks; - unsigned int flags; + unsigned int flags; }; enum { @@ -64,16 +64,16 @@ extern int M6502_disassemble(M6502 *mpu, uint16_t ip, char buffer[64]); extern void M6502_dump(M6502 *mpu, char buffer[64]); extern void M6502_delete(M6502 *mpu); -#define M6502_getVector(MPU, VEC) \ - ( ( ((MPU)->memory[M6502_##VEC##VectorLSB]) ) \ +#define M6502_getVector(MPU, VEC) \ + ( ( ((MPU)->memory[M6502_##VEC##VectorLSB]) ) \ | ((MPU)->memory[M6502_##VEC##VectorMSB] << 8) ) -#define M6502_setVector(MPU, VEC, ADDR) \ - ( ( ((MPU)->memory[M6502_##VEC##VectorLSB]= ((uint8_t)(ADDR)) & 0xff) ) \ +#define M6502_setVector(MPU, VEC, ADDR) \ + ( ( ((MPU)->memory[M6502_##VEC##VectorLSB]= ((uint8_t)(ADDR)) & 0xff) ) \ , ((MPU)->memory[M6502_##VEC##VectorMSB]= (uint8_t)((ADDR) >> 8)) ) -#define M6502_getCallback(MPU, TYPE, ADDR) ((MPU)->callbacks->TYPE[ADDR]) -#define M6502_setCallback(MPU, TYPE, ADDR, FN) ((MPU)->callbacks->TYPE[ADDR]= (FN)) +#define M6502_getCallback(MPU, TYPE, ADDR) ((MPU)->callbacks->TYPE[ADDR]) +#define M6502_setCallback(MPU, TYPE, ADDR, FN) ((MPU)->callbacks->TYPE[ADDR]= (FN)) #endif /* __m6502_h */ diff --git a/src/mame/arm.c b/src/mame/arm.c index 01fae90d..5bec9196 100644 --- a/src/mame/arm.c +++ b/src/mame/arm.c @@ -972,12 +972,12 @@ int loadDec(UINT32 pat, UINT32 rbv, UINT32 s, UINT32* deferredR15, int* defer) else /* Pull only address, preserve mode & status flags */ *deferredR15 = (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((cpu_read32(rbv-=4))&ADDRESS_MASK); - } - else - SetRegister( i, cpu_read32(rbv -=4) ); - result++; } + else + SetRegister( i, cpu_read32(rbv -=4) ); + result++; } + } return result; } diff --git a/src/opc5ls/opc5ls.c b/src/opc5ls/opc5ls.c new file mode 100644 index 00000000..a3a53419 --- /dev/null +++ b/src/opc5ls/opc5ls.c @@ -0,0 +1,217 @@ +#include +#include "opc5ls.h" +#include "../tube.h" +#include "../copro-opc5ls.h" + +#ifdef INCLUDE_DEBUGGER +#include "opc5ls_debug.h" +#include "../cpu_debug.h" +#endif + +// Encapsulate the persistent CPU state +opc5ls_state s; + +opc5ls_state *m_opc5ls = &s; + +// Point the memory read/write back to the Co Pro to include tube access +#define OPC5LS_READ copro_opc5ls_read +#define OPC5LS_WRITE copro_opc5ls_write + +static void int_action() { + s.pc_int = s.reg[PC]; + s.psr_int = s.psr & ~SWI_MASK; // Always clear the swi flag in the saved copy + DBG_PRINT("saving %04x %02x\r\n", s.pc_int, s.psr_int); + s.reg[PC] = s.pc_irq; + s.psr &= ~EI_MASK; +} + +void opc5ls_execute() { + + do { + +#ifdef INCLUDE_DEBUGGER + if (opc5ls_debug_enabled) + { + s.saved_pc = s.reg[PC]; + debug_preexec(&opc5ls_cpu_debug, s.reg[PC]); + } +#endif + + DBG_PRINT("%04x ", s.reg[PC]); + + // Fetch the instruction + register uint16_t instr = *(s.memory + s.reg[PC]++); + + DBG_PRINT("%04x ", instr); + + // Fetch the optional operant + register int operand = ((instr >> LEN) & 1) ? *(s.memory + s.reg[PC]++) : 0; + + DBG_PRINT("%04x %02x", operand, s.psr); + DBG_PRINT("\r\n"); + + // Evaluate the predicate + register int pred = (instr >> PRED) & 7; + switch (pred) { + case 0: + pred = 1; break; + case 1: + pred = 0; break; + case 2: + pred = s.psr & Z_MASK; break; + case 3: + pred = !(s.psr & Z_MASK); break; + case 4: + pred = s.psr & C_MASK; break; + case 5: + pred = !(s.psr & C_MASK); break; + case 6: + pred = s.psr & S_MASK; break; + case 7: + pred = !(s.psr & S_MASK); break; + } + + // Conditionally execute the instruction + if (pred) { + + // Force register 0 to be zero (it's overwritten by cmp) + s.reg[0] = 0; + + // Decode the instruction + int dst = (instr >> DST) & 15; + int src = (instr >> SRC) & 15; + int opcode = (instr >> OPCODE) & 15; + int ea_ed = (s.reg[src] + operand) & 0xffff; + + // Setup carry going into the "ALU" + uint32_t res = 0; + int cin = s.psr & C_MASK ? 1 : 0; + int cout = cin; + + // When to preserve the flags + int preserve_flag = 0; + + // Execute the instruction + switch(opcode) { + case op_mov: + s.reg[dst] = ea_ed; + break; + case op_and: + s.reg[dst] &= ea_ed; + break; + case op_or: + s.reg[dst] |= ea_ed; + break; + case op_xor: + s.reg[dst] ^= ea_ed; + break; + case op_add: + res = s.reg[dst] + ea_ed; + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_adc: + res = s.reg[dst] + ea_ed + cin; + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_sto: + preserve_flag = 1; + OPC5LS_WRITE(ea_ed, s.reg[dst]); + break; + case op_ld: + s.reg[dst] = OPC5LS_READ(ea_ed); + break; + case op_ror: + cout = ea_ed & 1; + s.reg[dst] = (cin << 15) | (ea_ed >> 1); + break; + case op_not: + s.reg[dst] = ~ea_ed; + break; + case op_sub: + res = s.reg[dst] + ((~ea_ed) & 0xffff) + 1; + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_sbc: + res = s.reg[dst] + ((~ea_ed) & 0xffff) + cin; + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_cmp: + res = s.reg[dst] + ((~ea_ed) & 0xffff) + 1; + dst = 0; // retarget cmp/cmpc to r0 + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_cmpc: + res = s.reg[dst] + ((~ea_ed) & 0xffff) + cin; + dst = 0; // retarget cmp/cmpc to r0 + s.reg[dst] = res & 0xffff; + cout = (res >> 16) & 1; + break; + case op_bswp: + s.reg[dst] = (((ea_ed & 0xFF00) >> 8) | ((ea_ed & 0x00FF) << 8)); + break; + case op_psr_rti: + if (dst == PC) { + // RTI + DBG_PRINT("restoring %04x %02x\r\n", s.pc_int, s.psr_int); + s.reg[PC] = s.pc_int; + s.psr = s.psr_int & ~SWI_MASK; + preserve_flag = 1; + } else if (dst == 0) { + // putpsr + s.psr = ea_ed & PSR_MASK; + preserve_flag = 1; + if (s.psr & SWI_MASK) { + int_action(); + } + } else if (src == 0) { + // getpsr + s.reg[dst] = s.psr & PSR_MASK; + } else { + DBG_PRINT("Illegal PSR instruction: %04x\r\n", instr); + } + break; + } + + // Update flags + if ((!preserve_flag) && (dst != PC)) { + s.psr &= ~(S_MASK | C_MASK | Z_MASK); + if (s.reg[dst] & 0x8000) { + s.psr |= S_MASK; + } + if (s.reg[dst] == 0) { + s.psr |= Z_MASK; + } + if (cout) { + s.psr |= C_MASK; + } + } + } + } while (tubeContinueRunning()); +} + +void opc5ls_reset() { + for (int i = 0; i < 16; i++) { + s.reg[i] = 0; + } + s.reg[PC] = s.pc_rst; + s.psr = 0; + s.pc_int = 0; + s.psr_int = 0; +} + +void opc5ls_irq() { + if (s.psr & EI_MASK) { + int_action(); + } +} + +void opc5ls_init(uint16_t *memory, uint16_t pc_rst, uint16_t pc_irq) { + s.memory = memory; + s.pc_rst = pc_rst; + s.pc_irq = pc_irq; +} diff --git a/src/opc5ls/opc5ls.h b/src/opc5ls/opc5ls.h new file mode 100644 index 00000000..6d39bbe0 --- /dev/null +++ b/src/opc5ls/opc5ls.h @@ -0,0 +1,91 @@ +// opc5ls.h + +#ifndef OPC5LS_H +#define OPC5LS_H + +#include + +void opc5ls_init(uint16_t *memory, uint16_t pc_rst, uint16_t pc_irq); +void opc5ls_execute(); +void opc5ls_reset(); +void opc5ls_irq(); + + +// Instruction +#define PRED 13 +#define LEN 12 +#define OPCODE 8 +#define SRC 4 +#define DST 0 + + +// PSR flag bits +#define Z_FLAG 0 +#define C_FLAG 1 +#define S_FLAG 2 +#define EI_FLAG 3 +#define SWI_FLAG 4 + +#define Z_MASK (1 << Z_FLAG) +#define C_MASK (1 << C_FLAG) +#define S_MASK (1 << S_FLAG) +#define EI_MASK (1 << EI_FLAG) +#define SWI_MASK (15 << SWI_FLAG) + +#define PSR_MASK 0xFF + +// PC is register 15 +#define PC 15 + +typedef struct { + // Saved PC at the start of on instruction + uint16_t saved_pc; + + // Register file + uint16_t reg[16]; + + // Processor status flags + uint16_t psr; + + // Interrupt state + uint16_t pc_int; + uint16_t psr_int; + +#ifdef USE_ISRV + int16_t isrv; +#endif + + // Main memory + uint16_t *memory; + + // Value of PC on reset + uint16_t pc_rst; + + // Value of PC on irq + uint16_t pc_irq; + +} opc5ls_state; + +extern opc5ls_state *m_opc5ls; + +enum { + op_mov, + op_and, + op_or, + op_xor, + op_add, + op_adc, + op_sto, + op_ld, + op_ror, + op_not, + op_sub, + op_sbc, + op_cmp, + op_cmpc, + op_bswp, + op_psr_rti +}; + + +#endif diff --git a/src/opc5ls/opc5ls_debug.c b/src/opc5ls/opc5ls_debug.c new file mode 100644 index 00000000..6c60c11c --- /dev/null +++ b/src/opc5ls/opc5ls_debug.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include + +#include "../cpu_debug.h" +#include "../copro-opc5ls.h" + +#include "opc5ls.h" +#include "opc5ls_debug.h" + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +int opc5ls_debug_enabled = 0; + +enum register_numbers { + i_R0, + i_R1, + i_R2, + i_R3, + i_R4, + i_R5, + i_R6, + i_R7, + i_R8, + i_R9, + i_R10, + i_R11, + i_R12, + i_R13, + i_R14, + i_PC, + i_PSR, + i_PC_int, + i_PSR_int, +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "R8", + "R9", + "R10", + "R11", + "R12", + "R13", + "R14", + "PC", + "PSR", + "PC_int", + "PSR_int", + NULL +}; + + +static const char *opcode_names[] = { + "mov", + "and", + "or", + "xor", + "add", + "adc", + "sto", + "ld", + "ror", + "not", + "sub", + "sbc", + "cmp", + "cmpc", + "bswp", + "psr", + "rti", + "???" +}; + +static const char *pred_names[] = { + "", + "0.", + "z.", + "nz.", + "c.", + "nc.", + "mi.", + "pl.", +}; + +// NULL pointer terminated list of trap names. +static const char *dbg_trap_names[] = { + NULL +}; + +// enable/disable debugging on this CPU, returns previous value. +static int dbg_debug_enable(int newvalue) { + int oldvalue = opc5ls_debug_enabled; + opc5ls_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_read(uint32_t addr) { + return copro_opc5ls_read(addr); +}; + +// CPU's usual memory write function. +static void dbg_write(uint32_t addr, uint32_t value) { + copro_opc5ls_write(addr, value); +}; + +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + int len; + int i; + + // Read the instruction + uint16_t instr = copro_opc5ls_read(addr); + + // Output address/instruction in hex + len = snprintf(buf, bufsize, "%04x %04x ", (uint16_t) addr, instr); + buf += len; + bufsize -= len; + + // Move on to next word + addr += 1; + + // Decode the instruction + int opcode = (instr >> OPCODE) & 15; + int pred = (instr >> PRED) & 7; + int dst = (instr >> DST) & 15; + int src = (instr >> SRC) & 15; + + // Special case RTI + if (opcode == 15) { + if (dst == 15) { + opcode++; // rti pc, ?? + } else if (dst == 0) { + dst = i_PSR; // putpsr psr, rs + } else if (src == 0) { + src = i_PSR; // getpsr rd, psr + } else { + opcode += 2; // ??? + } + } + + // Output operand in hex (or padding) + int operand_present = ((instr >> LEN) & 1); + int operand = 0; + if (operand_present) { + operand = copro_opc5ls_read(addr); + addr += 1; + len = snprintf(buf, bufsize, "%04x ", operand); + } else { + len = snprintf(buf, bufsize, " "); + } + buf += len; + bufsize -= len; + + // Output instruction + len = snprintf(buf, bufsize, ": %s%s %s, %s", + pred_names[pred], opcode_names[opcode], + dbg_reg_names[dst], dbg_reg_names[src]); + // Lower case the buffer, so the registers don't stand out + for (i = 0; i < len; i++) { + buf[i] = tolower(buf[i]); + } + buf += len; + bufsize -= len; + + // Output optional operand + if (operand_present) { + snprintf(buf, bufsize, ", 0x%04x", operand); + } + + return addr; +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + if (which == i_PSR) { + return m_opc5ls->psr; + } else if (which == i_PSR_int) { + return m_opc5ls->psr_int; + } else if (which == i_PC_int) { + return m_opc5ls->pc_int; + } else { + return m_opc5ls->reg[which]; + } +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + if (which == i_PSR) { + m_opc5ls->psr = value; + } else if (which == i_PSR_int) { + m_opc5ls->psr_int = value; + } else if (which == i_PC_int) { + m_opc5ls->pc_int = value; + } else { + m_opc5ls->reg[which] = value; + } +}; + +static const char* flagname = "EI S C Z "; + +// Print register value in CPU standard form. +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + if (which == i_PSR) { + int i; + int bit; + char c; + const char *flagnameptr = flagname; + int psr = dbg_reg_get(i_PSR); + + if (bufsize < 40) { + strncpy(buf, "buffer too small!!!", bufsize); + } + + // Print the 4-bit SWI field + *buf++ = 'S'; + *buf++ = 'W'; + *buf++ = 'I'; + *buf++ = ':'; + sprintf(buf, "%x", (psr >> 4) & 0x0F); + buf++; + *buf++ = ' '; + + // Print the remaining flag bits + bit = 0x8; + for (i = 0; i < 4; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + *buf++ = '\0'; + return strlen(buf); + } else { + return snprintf(buf, bufsize, "%04"PRIx32, dbg_reg_get(which)); + } +}; + +// Parse a value into a register. +static void dbg_reg_parse(int which, char *strval) { + uint32_t val = 0; + sscanf(strval, "%"SCNx32, &val); + dbg_reg_set(which, val); +}; + +static uint32_t dbg_get_instr_addr() { + return m_opc5ls->saved_pc; +} + +cpu_debug_t opc5ls_cpu_debug = { + .cpu_name = "OPC5LS", + .debug_enable = dbg_debug_enable, + .memread = dbg_read, + .memwrite = dbg_write, + .disassemble = dbg_disassemble, + .reg_names = dbg_reg_names, + .reg_get = dbg_reg_get, + .reg_set = dbg_reg_set, + .reg_print = dbg_reg_print, + .reg_parse = dbg_reg_parse, + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names, + .mem_width = WIDTH_16BITS +}; diff --git a/src/opc5ls/opc5ls_debug.h b/src/opc5ls/opc5ls_debug.h new file mode 100644 index 00000000..ea2b89f8 --- /dev/null +++ b/src/opc5ls/opc5ls_debug.h @@ -0,0 +1,5 @@ +#include "../cpu_debug.h" + +extern int opc5ls_debug_enabled; + +extern cpu_debug_t opc5ls_cpu_debug; diff --git a/src/opc5ls/opc5lsasm.py b/src/opc5ls/opc5lsasm.py new file mode 100644 index 00000000..b349453c --- /dev/null +++ b/src/opc5ls/opc5lsasm.py @@ -0,0 +1,66 @@ +import sys, re +op = "mov,and,or,xor,add,adc,sto,ld,ror,not,sub,sbc,cmp,cmpc,bswp,psr,halt".split(',')+[""]*14+["rti"] #halt aliassed to mov, rti to psr (modulo 16) +symtab = dict( [ ("r%d"%d,d) for d in range(0,16)] + [("pc",15), ("psr",0)]) +predicates = {"1":0x0000,"0":0x2000,"z":0x4000,"nz":0x6000,"c":0x8000,"nc":0xA000,"mi":0xC000,"pl":0xE000,"":0x0000} +def expand_macro(line, macro): # recursively expand macros, passing on instances not (yet) defined + (text,mobj)=([line],re.match("^(?P