From 31c5cc8798e63af389de2bd52827c7a5a032e825 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 4 Mar 2017 18:14:23 +0000 Subject: [PATCH 001/149] Remove code that isn't needed in the Host/Parasite read/write fucntions. ( mainly tube_enable and IRQs NMIs) --- src/tube-ula.c | 123 +++++++++++++++++++++++++++++-------------------- src/tube-ula.h | 4 +- 2 files changed, 74 insertions(+), 53 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 77147285..a5f55109 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -169,7 +169,7 @@ void tube_reset_buffer() { } } #endif - +/* static void tube_updateints_IRQ() { // Test for IRQ @@ -185,6 +185,24 @@ static void tube_updateints_NMI() if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=2; if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=2; } +*/ +static void tube_reset() +{ + tube_enabled = 1; + tube_irq &= ~(4+2+1); + ph1pos = hp3pos = 0; + ph3pos = 1; + HSTAT1 = HSTAT2 = HSTAT4 = HBIT_6; + PSTAT1 = PSTAT2 = PSTAT3 = PSTAT4 = 0x40; + HSTAT3 = HBIT_7 | HBIT_6; + // On the Model B the initial write of &8E to FEE0 is missed + // If the Pi is slower in starting than the Beeb. A work around + // is to have the tube emulation reset to a state with interrupts + // enabled. + HSTAT1 |= HBIT_3 | HBIT_2 | HBIT_1; + //tube_updateints_IRQ(); + //tube_updateints_NMI(); +} // 6502 Host reading the tube registers // @@ -209,7 +227,7 @@ static void tube_host_read(uint16_t addr) PSTAT1 |= 0x40; if (!ph1pos) HSTAT1 &= ~HBIT_7; } - tube_updateints_IRQ(); + // tube_updateints_IRQ(); // the above can't change the irq status break; case 3: /*Register 2*/ if (HSTAT2 & HBIT_7) @@ -225,8 +243,9 @@ static void tube_host_read(uint16_t addr) ph3pos--; PSTAT3 |= 0xC0; if (!ph3pos) HSTAT3 &= ~HBIT_7; + if ((HSTAT1 & HBIT_3) && (ph3pos == 0)) tube_irq|=2; + //tube_updateints_NMI(); } - tube_updateints_NMI(); break; case 7: /*Register 4*/ if (HSTAT4 & HBIT_7) @@ -234,7 +253,7 @@ static void tube_host_read(uint16_t addr) HSTAT4 &= ~HBIT_7; PSTAT4 |= 0x40; } - tube_updateints_IRQ(); + // tube_updateints_IRQ(); // the above can't change the irq status break; } } @@ -244,8 +263,10 @@ static void tube_host_write(uint16_t addr, uint8_t val) switch (addr & 7) { case 0: /*Register 1 stat*/ + if (!tube_enabled) - return; + return; + if (val & 0x80) { // Implement software tube reset if (val & 0x40) { @@ -256,20 +277,23 @@ static void tube_host_write(uint16_t addr, uint8_t val) } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); } - tube_updateints_IRQ(); - tube_updateints_NMI(); + tube_irq = 0; + if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= 1; + if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= 1; + if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=2; + if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=2; break; case 1: /*Register 1*/ - if (!tube_enabled) - return; + //if (!tube_enabled) + // return; hp1 = val; PSTAT1 |= 0x80; HSTAT1 &= ~HBIT_6; - tube_updateints_IRQ(); + if (HSTAT1 & HBIT_1) tube_irq |= 1;//tube_updateints_IRQ(); break; case 3: /*Register 2*/ - if (!tube_enabled) - return; + //if (!tube_enabled) + // return; hp2 = val; PSTAT2 |= 0x80; HSTAT2 &= ~HBIT_6; @@ -279,12 +303,12 @@ static void tube_host_write(uint16_t addr, uint8_t val) copro_speed = 0; else copro_speed = (arm_speed/(1000000/256) / val); - LOG_DEBUG("New speed Copro = %d, %d\n", val, copro_speed); + LOG_DEBUG("New speed Copro = %d, %d\r\n", val, copro_speed); return; case 5: /*Register 3*/ - if (!tube_enabled) - return; + // if (!tube_enabled) + // return; #ifdef DEBUG_TRANSFERS checksum_h *= 13; checksum_h += val; @@ -299,6 +323,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) PSTAT3 |= 0x80; HSTAT3 &= ~HBIT_6; } + if ((HSTAT1 & HBIT_3) && (hp3pos > 1)) tube_irq|=2; } else { @@ -306,16 +331,17 @@ static void tube_host_write(uint16_t addr, uint8_t val) hp3pos = 1; PSTAT3 |= 0x80; HSTAT3 &= ~HBIT_6; + if (HSTAT1 & HBIT_3) tube_irq|=2; } - tube_updateints_NMI(); + //tube_updateints_NMI(); break; case 6: copro = val; - LOG_DEBUG("New Copro = %d\n", copro); + LOG_DEBUG("New Copro = %d\r\n", copro); return; case 7: /*Register 4*/ - if (!tube_enabled) - return; + // if (!tube_enabled) + // return; hp4 = val; PSTAT4 |= 0x80; HSTAT4 &= ~HBIT_6; @@ -329,7 +355,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) count_p = 0; } #endif - tube_updateints_IRQ(); + if (HSTAT1 & HBIT_2) tube_irq |= 1; //tube_updateints_IRQ(); break; default: LOG_WARN("Illegal host write to %d\r\n", addr); @@ -338,7 +364,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) uint8_t tube_parasite_read(uint32_t addr) { - uint8_t temp = 0; + uint8_t temp ; switch (addr & 7) { case 0: /*Register 1 stat*/ @@ -350,8 +376,9 @@ uint8_t tube_parasite_read(uint32_t addr) { PSTAT1 &= ~0x80; HSTAT1 |= HBIT_6; + //tube_updateints_IRQ(); // clear irq if required reg 4 isnt irqing + if (!(PSTAT4 & 128)) tube_irq = tube_irq & (0xFF - 1); } - tube_updateints_IRQ(); break; case 2: /*Register 2 stat*/ temp = PSTAT2; @@ -383,8 +410,12 @@ uint8_t tube_parasite_read(uint32_t addr) HSTAT3 |= HBIT_6; PSTAT3 &= ~0x80; } - } - tube_updateints_NMI(); + //tube_updateints_NMI(); + // here we want to only really clear NMI if required, but setting irq might be simpler + tube_irq = tube_irq &(0xFF - 2); + if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0))) tube_irq|=2; + if ((HSTAT1 & HBIT_3) && (ph3pos == 0)) tube_irq|=2; + } break; case 6: /*Register 4 stat*/ temp = PSTAT4; @@ -395,8 +426,9 @@ uint8_t tube_parasite_read(uint32_t addr) { PSTAT4 &= ~0x80; HSTAT4 |= HBIT_6; + //tube_updateints_IRQ(); // clear irq if reg 1 isnt irqing + if (!(PSTAT1 & 128)) tube_irq = tube_irq & (0xFF - 1); } - tube_updateints_IRQ(); break; } @@ -453,7 +485,7 @@ void tube_parasite_write(uint32_t addr, uint8_t val) HSTAT1 |= HBIT_7; if (ph1pos == 24) PSTAT1 &= ~0x40; } - tube_updateints_IRQ(); + // tube_updateints_IRQ(); // the above can't change the IRQ flags break; case 3: /*Register 2*/ PH2 = BYTE_TO_WORD(val); @@ -476,6 +508,8 @@ void tube_parasite_write(uint32_t addr, uint8_t val) HSTAT3 |= HBIT_7; PSTAT3 &= ~0x40; } + //NMI if other case isn't seting it + if (!(hp3pos > 1) ) tube_irq = tube_irq &(0xFF - 2); } else { @@ -483,36 +517,23 @@ void tube_parasite_write(uint32_t addr, uint8_t val) ph3pos = 1; HSTAT3 |= HBIT_7; PSTAT3 &= ~0xC0; + tube_irq = tube_irq &(0xFF - 2); + //NMI if other case isn't seting it + if (!(hp3pos > 0) ) tube_irq = tube_irq &(0xFF - 2); } - tube_updateints_NMI(); + //tube_updateints_NMI(); + // here we want to only clear NMI if required + break; case 7: /*Register 4*/ PH4 = BYTE_TO_WORD(val); HSTAT4 |= HBIT_7; PSTAT4 &= ~0x40; - tube_updateints_IRQ(); + // tube_updateints_IRQ(); // the above can't change IRQ flag break; } } -void tube_reset() -{ - tube_enabled = 1; - tube_irq = 0; - ph1pos = hp3pos = 0; - ph3pos = 1; - HSTAT1 = HSTAT2 = HSTAT4 = HBIT_6; - PSTAT1 = PSTAT2 = PSTAT3 = PSTAT4 = 0x40; - HSTAT3 = HBIT_7 | HBIT_6; - // On the Model B the initial write of &8E to FEE0 is missed - // If the Pi is slower in starting than the Beeb. A work around - // is to have the tube emulation reset to a state with interrupts - // enabled. - HSTAT1 |= HBIT_3 | HBIT_2 | HBIT_1; - tube_updateints_IRQ(); - tube_updateints_NMI(); -} - // Returns bit 0 set if IRQ is asserted by the tube // Returns bit 1 set if NMI is asserted by the tube // Returns bit 2 set if RST is asserted by the host or tube @@ -603,7 +624,7 @@ int tube_io_handler(uint32_t mail) if (nrst == 0 || (tube_enabled && (HSTAT1 & HBIT_5))) { return tube_irq | 4; } else { - return tube_irq; + return tube_irq & 3; } } @@ -738,14 +759,14 @@ int tube_is_rst_active() { } return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || (tube_enabled && (HSTAT1 & HBIT_5)); } - -void tube_wait_for_rst_active() { +#if 0 +static void tube_wait_for_rst_active() { while (!tube_is_rst_active()); } - +#endif // Debounce RST -// On my Model B the characterisc of RST bounce on release is a bust +// On my Model B the characterisc of RST bounce on release is a burst // of short (2us) high pulses approx 2ms before a clean rising RST edge // On my Master 128 there is no RST bounce, and RST is clean diff --git a/src/tube-ula.h b/src/tube-ula.h index 379aa08e..71d81619 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -27,7 +27,7 @@ extern void tube_parasite_write(uint32_t addr, uint8_t val); extern void tube_parasite_write_banksel(uint32_t addr, uint8_t val); -extern void tube_reset(); +//extern void tube_reset(); extern int tube_io_handler(uint32_t mail); @@ -35,7 +35,7 @@ extern void tube_init_hardware(); extern int tube_is_rst_active(); -extern void tube_wait_for_rst_active(); +//extern void tube_wait_for_rst_active(); extern void tube_wait_for_rst_release(); From 724db9e177535752ade52c3829b06dd1d6c050d3 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 4 Mar 2017 21:10:38 +0000 Subject: [PATCH 002/149] Speed up tube transfers Paratsite to Host register 1 --- src/tube-ula.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index a5f55109..41abb0b2 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -96,7 +96,8 @@ static perf_counters_t pct; uint8_t ph1[24],ph3_1; uint8_t hp1,hp2,hp3[2],hp4; uint8_t pstat[4]; -int ph1pos,ph3pos,hp3pos; +int ph3pos,hp3pos; +int ph1rdpos,ph1wrpos,ph1len; // Host end of the fifos are the ones read by the tube isr #define PH1_0 tube_regs[1] @@ -190,7 +191,8 @@ static void tube_reset() { tube_enabled = 1; tube_irq &= ~(4+2+1); - ph1pos = hp3pos = 0; + hp3pos = 0; + ph1rdpos = ph1wrpos = ph1len = 0; ph3pos = 1; HSTAT1 = HSTAT2 = HSTAT4 = HBIT_6; PSTAT1 = PSTAT2 = PSTAT3 = PSTAT4 = 0x40; @@ -216,16 +218,22 @@ static void tube_reset() static void tube_host_read(uint16_t addr) { - int c; switch (addr & 7) { case 1: /*Register 1*/ - if (ph1pos > 0) { - PH1_0 = BYTE_TO_WORD(ph1[1]); - for (c = 1; c < 23; c++) ph1[c] = ph1[c + 1]; - ph1pos--; + if (ph1len > 0) { + PH1_0 = BYTE_TO_WORD(ph1[ph1rdpos]); + //for (c = 1; c < 23; c++) ph1[c] = ph1[c + 1]; + ph1len--; + if ( ph1len != 0) + { + if (ph1rdpos== 23) + ph1rdpos =0; + else + ph1rdpos++; + } PSTAT1 |= 0x40; - if (!ph1pos) HSTAT1 &= ~HBIT_7; + if (!ph1len) HSTAT1 &= ~HBIT_7; } // tube_updateints_IRQ(); // the above can't change the irq status break; @@ -474,16 +482,21 @@ void tube_parasite_write(uint32_t addr, uint8_t val) switch (addr & 7) { case 1: /*Register 1*/ - if (ph1pos < 24) + if (ph1len < 24) { - if (ph1pos == 0) { + if (ph1len == 0) { PH1_0 = BYTE_TO_WORD(val); } else { - ph1[ph1pos] = val; + ph1[ph1wrpos] = val; + if (ph1wrpos== 23) + ph1wrpos =0; + else + ph1wrpos++; } - ph1pos++; + + ph1len++; HSTAT1 |= HBIT_7; - if (ph1pos == 24) PSTAT1 &= ~0x40; + if (ph1len == 24) PSTAT1 &= ~0x40; } // tube_updateints_IRQ(); // the above can't change the IRQ flags break; From c69aa842c0e4a155c70d7562d9eae3acba5f3e36 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 5 Mar 2017 18:42:13 +0000 Subject: [PATCH 003/149] Start of making all cores use the same memory --- src/NS32016/32016.c | 3 +-- src/NS32016/Profile.c | 2 +- src/NS32016/mem32016.c | 5 +++-- src/mc6809nc/mc6809.c | 6 +++--- src/tube-client.c | 17 ++++++++++++++--- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index b27c24f6..5d78c641 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -351,7 +351,7 @@ static void GetGenPhase2(RegLKU gen, int c) default: { - PiWARN("Illegal RegType value: %d\n", gen.RegType) + PiWARN("Illegal RegType value: %u\n", gen.RegType) } } @@ -3003,7 +3003,6 @@ void n32016_exec() case OpImmediate: { GOTO_TRAP(IllegalWritingImmediate); - goto DoTrap; } } } else { diff --git a/src/NS32016/Profile.c b/src/NS32016/Profile.c index 8547eaaf..a5fdbca6 100644 --- a/src/NS32016/Profile.c +++ b/src/NS32016/Profile.c @@ -50,7 +50,7 @@ uint16_t processOperand(uint16_t operand) { return 0; // --none-- } - else if (operand >= 0 && operand <= 7) + else if ( && operand <= 7) { return 2; // RN } diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index cac6ab4a..963e42b6 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -11,6 +11,7 @@ #include #include "32016.h" #include "mem32016.h" +#include "../tube-client.h" //#ifdef BEEBEM #include "../tube-ula.h" @@ -32,12 +33,12 @@ #include "pandora/PandoraV2_00.h" #endif -uint8_t ns32016ram[MEG16]; +uint8_t * ns32016ram; void init_ram(void) { + ns32016ram = copro_mem_reset(MEG16); #ifdef TEST_SUITE - memset(ns32016ram, 0, sizeof(ns32016ram)); memcpy(ns32016ram, ROM, sizeof(ROM)); #elif defined(PANDORA_BASE) memcpy(ns32016ram + PANDORA_BASE, PandoraV2_00, sizeof(PandoraV2_00)); diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index 7db44789..726c4ad3 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -525,10 +525,10 @@ unsigned get_cc (void) void set_cc (unsigned arg) { EFI = arg & (E_FLAG | F_FLAG | I_FLAG); - H = (arg & H_FLAG ? 0x10 : 0); - N = (arg & N_FLAG ? 0x80 : 0); + H = ((arg & H_FLAG) ? 0x10 : 0); + N = ((arg & N_FLAG) ? 0x80 : 0); Z = (~arg) & Z_FLAG; - OV = (arg & V_FLAG ? 0x80 : 0); + OV = ((arg & V_FLAG) ? 0x80 : 0); C = arg & C_FLAG; cc_changed = 1; } diff --git a/src/tube-client.c b/src/tube-client.c index 3d571b4b..fab51737 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "tube-defs.h" #include "tube.h" @@ -90,6 +91,16 @@ static func_ptr emulator; #define SWI_VECTOR (HIGH_VECTORS_BASE + 0x28) #define FIQ_VECTOR (HIGH_VECTORS_BASE + 0x3C) +unsigned char * copro_mem_reset(int length) +{ + // Wipe memory + // Memory starts at zero now vectors have moved. + unsigned char * mpu_memory = 0; + memset(mpu_memory, 0, length); + // return pointer to memory + return mpu_memory; +} + void init_emulator() { _disable_interrupts(); @@ -122,7 +133,7 @@ void init_emulator() { copro = DEFAULT_COPRO; } - LOG_DEBUG("Raspberry Pi Direct %d %s Client\r\n", copro,emulator_names[copro]); + LOG_DEBUG("Raspberry Pi Direct %u %s Client\r\n", copro,emulator_names[copro]); emulator = emulator_functions[copro]; @@ -191,7 +202,7 @@ static void get_copro_speed() { if (copro_speed > 255){ copro_speed = 0; } - LOG_DEBUG("emulator speed %d\r\n", copro_speed); + LOG_DEBUG("emulator speed %u\r\n", copro_speed); if (copro_speed !=0) copro_speed = (arm_speed/(1000000/256) / copro_speed); } @@ -231,7 +242,7 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) #ifdef HAS_MULTICORE - LOG_DEBUG("main running on core %d\r\n", _get_core()); + LOG_DEBUG("main running on core %u\r\n", _get_core()); for (i = 0; i < 10000000; i++); start_core(1, _spin_core); for (i = 0; i < 10000000; i++); From bf397a78a208e3eda7083f4fc6217981e27ad7d7 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 5 Mar 2017 18:44:49 +0000 Subject: [PATCH 004/149] Syncing to master --- src/tube-ula.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 41abb0b2..8d5ebc7b 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -145,7 +145,7 @@ unsigned int tube_buffer[0x10000]; void tube_dump_buffer() { int i; - LOG_INFO("tube_index = %d\r\n", tube_index); + LOG_INFO("tube_index = %u\r\n", tube_index); for (i = 0; i < tube_index; i++) { if (tube_buffer[i] & (TUBE_READ_MARKER | TUBE_WRITE_MARKER)) { if (tube_buffer[i] & TUBE_READ_MARKER) { @@ -155,7 +155,7 @@ void tube_dump_buffer() { LOG_INFO("Wr R"); } // Covert address (1,3,5,7) to R1,R2,R3,R4 - LOG_INFO("%d = %02x\r\n", 1 + ((tube_buffer[i] & 0xF00) >> 9), tube_buffer[i] & 0xFF); + LOG_INFO("%u = %02x\r\n", 1 + ((tube_buffer[i] & 0xF00) >> 9), tube_buffer[i] & 0xFF); } else { LOG_INFO("?? %08x\r\n", tube_buffer[i]); } @@ -227,13 +227,13 @@ static void tube_host_read(uint16_t addr) ph1len--; if ( ph1len != 0) { + HSTAT1 &= ~HBIT_7; if (ph1rdpos== 23) ph1rdpos =0; else ph1rdpos++; } PSTAT1 |= 0x40; - if (!ph1len) HSTAT1 &= ~HBIT_7; } // tube_updateints_IRQ(); // the above can't change the irq status break; @@ -311,7 +311,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) copro_speed = 0; else copro_speed = (arm_speed/(1000000/256) / val); - LOG_DEBUG("New speed Copro = %d, %d\r\n", val, copro_speed); + LOG_DEBUG("New speed Copro = %u, %u\r\n", val, copro_speed); return; case 5: /*Register 3*/ @@ -345,7 +345,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) break; case 6: copro = val; - LOG_DEBUG("New Copro = %d\r\n", copro); + LOG_DEBUG("New Copro = %u\r\n", copro); return; case 7: /*Register 4*/ // if (!tube_enabled) @@ -834,7 +834,7 @@ void tube_log_performance_counters() { read_performance_counters(&pct); print_performance_counters(&pct); #endif - LOG_DEBUG("tube reset - copro %d\r\n", copro); + LOG_DEBUG("tube reset - copro %u\r\n", copro); #ifdef DEBUG_TRANSFERS LOG_INFO("checksum_h = %08"PRIX32" %08"PRIX32"\r\n", count_h, checksum_h); LOG_INFO("checksum_p = %08"PRIX32" %08"PRIX32"\r\n", count_p, checksum_p); From e87a73fab3f8bbf01eee629d6581c161355a53e7 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 5 Mar 2017 19:30:10 +0000 Subject: [PATCH 005/149] untested Changes to only use one function to clear RAM for each copro --- src/CMakeLists.txt | 2 +- src/copro-65tube.c | 11 ++++--- src/copro-arm2.c | 14 +++++---- src/copro-mc6809.c | 5 ++- src/copro-mc6809nc.c | 5 ++- src/copro-mc6809sc.c | 5 ++- src/copro-null.c | 2 +- src/copro-z80.c | 13 +++----- src/cpu80186/mem80186.c | 6 ++-- src/cpu80186/mem80186.h | 6 ++-- src/toolchain-arm-none-eabi-rpi2.cmake | 1 + src/toolchain-arm-none-eabi-rpi3.cmake | 12 ++++++-- src/tubevc.c | 34 ++++++++++----------- vidcore/tubevc.s | 42 +++++++++++++------------- 14 files changed, 82 insertions(+), 76 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bff0d67d..e84b6ad6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,7 +40,7 @@ project( tube-client C ASM ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostartfiles" ) -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPROFILING -fomit-frame-pointer" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer" ) #set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffixed-ip" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-delete-null-pointer-checks -fdata-sections -ffunction-sections ") diff --git a/src/copro-65tube.c b/src/copro-65tube.c index 0dbc62b4..d940d2a5 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -11,6 +11,7 @@ #include #include +#include "tube-client.h" #include "tube-defs.h" #include "tube.h" #include "tube-ula.h" @@ -38,11 +39,13 @@ void copro_65tube_dump_histogram() { #endif -static void copro_65tube_poweron_reset(unsigned char mpu_memory[]) { +static unsigned char *copro_65tube_poweron_reset(void) { // Wipe memory - memset(mpu_memory, 0, 0xF800); // only need to goto 0xF800 as rom will be put in later + unsigned char * mpu_memory; + mpu_memory = copro_mem_reset(0xF800); // only need to goto 0xF800 as rom will be put in later // Install test programs (like sphere) copy_test_programs(mpu_memory); + return mpu_memory; } static void copro_65tube_reset(unsigned char mpu_memory[]) { @@ -57,8 +60,8 @@ void copro_65tube_emulator() { int last_copro = copro; // unsigned char *addr; //__attribute__ ((aligned (64*1024))) unsigned char mpu_memory[64*1024]; // allocate the amount of ram - unsigned char * mpu_memory = 0; // now the arm vectors have moved we can set the core memory to start at 0 - copro_65tube_poweron_reset(mpu_memory); + unsigned char * mpu_memory; // now the arm vectors have moved we can set the core memory to start at 0 + mpu_memory = copro_65tube_poweron_reset(); copro_65tube_reset(mpu_memory); while (copro == last_copro) { diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 3d14f5a8..67ce0bba 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -16,6 +16,7 @@ #include "tuberom_arm.h" #include "copro-arm2.h" #include "startup.h" +#include "tube-client.h" #define RAM_MASK8 ((UINT32) 0x003fffff) #define ROM_MASK8 ((UINT32) 0x00003fff) @@ -23,10 +24,11 @@ #define ROM_MASK32 ((UINT32) 0x00003ffc) // 4MB of RAM starting at 0x00000000 -UINT8 arm2_ram[1024 * 1024 * 4] __attribute__((aligned(0x10000))); +#define ARM_RAM_SIZE 1024 * 1024 * 4 +UINT8 * arm2_ram; // 16KB of ROM starting at 0x03000000 -UINT8 arm2_rom[0x4000] __attribute__((aligned(0x10000))); +//UINT8 arm2_rom[0x4000] __attribute__((aligned(0x10000))); #define R15 arm2_getR15() @@ -45,7 +47,7 @@ UINT8 copro_arm2_read8(int addr) case 1: return tube_parasite_read((addr >> 2) & 7); case 3: - return *(UINT8*) (arm2_rom + (addr & ROM_MASK8)); + return *(UINT8*) (tuberom_arm_v100+(addr & ROM_MASK8)); } return 0; @@ -70,7 +72,7 @@ UINT32 copro_arm2_read32(int addr) result = tube_parasite_read((addr >> 2) & 7); break; case 3: - result = *(UINT32*) (arm2_rom + (addr & ROM_MASK32)); + result = *(UINT32*) (tuberom_arm_v100+(addr & ROM_MASK32)); break; default: result = 0; @@ -124,7 +126,7 @@ void copro_arm2_write32(int addr, UINT32 data) static void copro_arm2_poweron_reset() { // Wipe memory - memset(arm2_ram, 0, sizeof(arm2_ram)); + arm2_ram = copro_mem_reset(ARM_RAM_SIZE); } static void copro_arm2_reset() @@ -133,7 +135,7 @@ static void copro_arm2_reset() 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); + //memcpy(arm2_rom, tuberom_arm_v100, 0x4000); // Reset the ARM device arm2_device_reset(); // Wait for rst become inactive before continuing to execute diff --git a/src/copro-mc6809.c b/src/copro-mc6809.c index 8f2bcbb2..99c0a24f 100644 --- a/src/copro-mc6809.c +++ b/src/copro-mc6809.c @@ -11,6 +11,7 @@ #include "tube-ula.h" #include "startup.h" #include "tuberom_6809.h" +#include "tube-client.h" #include "copro-mc6809.h" @@ -60,9 +61,7 @@ static void copro_mc6809_mem_cycle(void *sptr, _Bool rnw, uint16_t addr) { static void copro_mc6809_poweron_reset() { // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) - copro_mc6809_ram = (unsigned char *) 0; - // Wipe memory - memset(copro_mc6809_ram, 0, 0x10000); + copro_mc6809_ram = copro_mem_reset(0x10000); } static void copro_mc6809_reset() { diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 576be7e6..55be2968 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -15,6 +15,7 @@ #include "copro-mc6809nc.h" #include "mc6809nc/mc6809.h" +#include "tube-client.h" static int overlay_rom = 0; @@ -54,9 +55,7 @@ uint8_t copro_mc6809nc_read(uint16_t addr) { static void copro_mc6809_poweron_reset() { // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) - copro_mc6809_ram = (unsigned char *) 0; - // Wipe memory - memset(copro_mc6809_ram, 0, 0x10000); + copro_mc6809_ram = copro_mem_reset(0x10000); } static void copro_mc6809_reset() { diff --git a/src/copro-mc6809sc.c b/src/copro-mc6809sc.c index 14914490..9123c546 100644 --- a/src/copro-mc6809sc.c +++ b/src/copro-mc6809sc.c @@ -15,6 +15,7 @@ #include "copro-mc6809sc.h" #include "mc6809sc/mc6809.h" +#include "tube-client.h" static int overlay_rom = 0; @@ -86,9 +87,7 @@ static void copro_mc6809sc_fault(mc6809__t *cpuptr, mc6809fault__t fault) { static void copro_mc6809_poweron_reset() { // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) - copro_mc6809_ram = (unsigned char *) 0; - // Wipe memory - memset(copro_mc6809_ram, 0, 0x10000); + copro_mc6809_ram = copro_mem_reset(0x10000); } static void copro_mc6809_reset() { diff --git a/src/copro-null.c b/src/copro-null.c index 5fcc0a91..0acc8689 100644 --- a/src/copro-null.c +++ b/src/copro-null.c @@ -17,7 +17,7 @@ void copro_null_emulator() { // Remember the current copro so we can exit if it changes int last_copro = copro; - printf("This Co Pro has not been implemented yet\r\n"); + printf("This is the NULL copro\r\n"); // Disable the tube, so the Beeb doesn't hang disable_tube(); diff --git a/src/copro-z80.c b/src/copro-z80.c index e6ce7fd8..31745005 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -4,17 +4,17 @@ * (c) 2016 David Banks */ #include -#include + #include "tube-defs.h" #include "tube.h" #include "tube-ula.h" #include "yaze/mem_mmu.h" #include "yaze/simz80.h" -#include "startup.h" +#include "tube-client.h" static int overlay_rom = 0; -unsigned char copro_z80_ram[0x10000]; +unsigned char *copro_z80_ram; static const unsigned char copro_z80_rom[0x1000] = { 0xf3, 0x11, 0x00, 0xf0, 0x21, 0x00, 0x00, 0x01, 0x00, 0x10, 0xed, 0xb0, 0xc3, 0x80, 0xf2, 0x43, @@ -298,11 +298,6 @@ void copro_z80_write_io(unsigned int addr, unsigned char data) { tube_parasite_write(addr & 7, data); } -static void copro_z80_poweron_reset() { - // Wipe memory - memset(copro_z80_ram, 0, 0x10000); -} - static void copro_z80_reset() { // Log ARM performance counters tube_log_performance_counters(); @@ -327,7 +322,7 @@ void copro_z80_emulator() // Remember the current copro so we can exit if it changes int last_copro = copro; - copro_z80_poweron_reset(); + copro_z80_ram = copro_mem_reset(0x10000); copro_z80_reset(); while (1) diff --git a/src/cpu80186/mem80186.c b/src/cpu80186/mem80186.c index d83ad49e..77f55e8f 100644 --- a/src/cpu80186/mem80186.c +++ b/src/cpu80186/mem80186.c @@ -26,9 +26,10 @@ #include "cpu80186.h" #include "mem80186.h" #include "Client86_v1_01.h" +#include "../tube-client.h" #ifdef DECLARE_RAM -uint8_t RAM[ONE_MEG]; +uint8_t* RAM;//[ONE_MEG]; #else uint8_t* RAM = (uint8_t*) m186_RamBase; #endif @@ -59,7 +60,8 @@ uint16_t readw86(uint32_t addr32) void Cleari80186Ram(void) { - memset(RAM, 0, ONE_MEG); + //memset(RAM, 0, ONE_MEG); + RAM = copro_mem_reset(ONE_MEG); } // The ARM must call RomCopy before starting the Processor diff --git a/src/cpu80186/mem80186.h b/src/cpu80186/mem80186.h index 8d69e4d4..1a475856 100644 --- a/src/cpu80186/mem80186.h +++ b/src/cpu80186/mem80186.h @@ -1,6 +1,6 @@ -#ifdef WIN32 + #define DECLARE_RAM -#endif + #define SIXTEEN_K 0x04000 #define ONE_MEG 0x100000 @@ -21,7 +21,7 @@ enum cpu80186_memory // Use Declare RAM when building on a machine with an REAL OS! #ifdef DECLARE_RAM -extern uint8_t RAM[ONE_MEG]; +extern uint8_t* RAM; #else extern uint8_t* RAM; #endif diff --git a/src/toolchain-arm-none-eabi-rpi2.cmake b/src/toolchain-arm-none-eabi-rpi2.cmake index f66bce65..1d5f0221 100644 --- a/src/toolchain-arm-none-eabi-rpi2.cmake +++ b/src/toolchain-arm-none-eabi-rpi2.cmake @@ -56,6 +56,7 @@ set( CMAKE_OBJCOPY ${TC_PATH}${CROSS_COMPILE}objcopy CACHE FILEPATH "The toolchain objcopy command " FORCE ) # Set the CMAKE C flags (which should also be used by the assembler! + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon-vfpv4" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a" ) diff --git a/src/toolchain-arm-none-eabi-rpi3.cmake b/src/toolchain-arm-none-eabi-rpi3.cmake index e575628d..8686175d 100644 --- a/src/toolchain-arm-none-eabi-rpi3.cmake +++ b/src/toolchain-arm-none-eabi-rpi3.cmake @@ -56,10 +56,16 @@ set( CMAKE_OBJCOPY ${TC_PATH}${CROSS_COMPILE}objcopy CACHE FILEPATH "The toolchain objcopy command " FORCE ) # Set the CMAKE C flags (which should also be used by the assembler! -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon-vfpv4" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon-vfpv4" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard" ) -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a" ) -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtune=cortex-a7" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtune=cortex-a7" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-a53" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtune=cortex-a7" ) + +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtune=cortex-a53" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=crypto-neon-fp-armv8" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" ) set( CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" ) diff --git a/src/tubevc.c b/src/tubevc.c index 8293967f..be414ef4 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -5,21 +5,21 @@ unsigned char tubevc_asm[] = { 0x52, 0xc3, 0x50, 0x1f, 0xf2, 0xc0, 0x5f, 0x97, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x03, 0xe8, 0x80, 0xb8, 0x00, 0x7e, 0x04, 0x60, 0x06, 0xe8, - 0x00, 0x00, 0x20, 0x7e, 0x67, 0x2d, 0x47, 0x6c, 0x3e, 0x18, 0x17, 0x6d, - 0xfc, 0x18, 0x67, 0x2d, 0x17, 0x6d, 0xf9, 0x18, 0x27, 0x6d, 0x2d, 0x18, - 0x08, 0x60, 0x87, 0xc1, 0x10, 0x3f, 0xa8, 0xc1, 0xc1, 0x40, 0x87, 0xc1, - 0x11, 0x3f, 0xa8, 0xc1, 0xc2, 0x40, 0x87, 0xc1, 0x12, 0x3f, 0xa8, 0xc1, - 0xc4, 0x40, 0x08, 0xa0, 0x08, 0x07, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, - 0x68, 0x37, 0x65, 0x37, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, - 0x88, 0xc1, 0x10, 0x47, 0x03, 0x18, 0x80, 0x90, 0x23, 0x00, 0x67, 0x2d, - 0x77, 0x6c, 0xfe, 0x18, 0x65, 0x3a, 0x69, 0x3a, 0x6a, 0x09, 0x6b, 0x31, - 0x6c, 0x32, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcd, 0x18, - 0x27, 0x6d, 0xcb, 0x18, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, - 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, 0x80, 0x90, 0x0b, 0x00, 0x41, 0x1f, - 0x78, 0x40, 0x80, 0x90, 0x07, 0x00, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, - 0x7f, 0x9e, 0xba, 0xff, 0x18, 0x47, 0x02, 0x6a, 0x08, 0x18, 0xf8, 0x71, - 0x27, 0x08, 0xf7, 0x6d, 0x08, 0xc2, 0xde, 0x40, 0x28, 0x09, 0x5a, 0x00, - 0x48, 0x4d, 0x44, 0xe8, 0x00, 0x10, 0x00, 0x00, 0xe4, 0xe8, 0x00, 0xf0, - 0x00, 0x00, 0x48, 0x7c, 0xa8, 0xc1, 0x4a, 0x47, 0x38, 0x09, 0x5a, 0x00 + 0x00, 0x00, 0x20, 0x7e, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, 0x3b, 0x18, + 0x18, 0x6d, 0xfc, 0x18, 0x68, 0x2d, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, + 0x2a, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, + 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, + 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, + 0x65, 0x37, 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, + 0x03, 0x18, 0x80, 0x90, 0x22, 0x00, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, + 0x65, 0x3a, 0x69, 0x3a, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x67, 0x2d, + 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcf, 0x18, 0x27, 0x6d, 0xcd, 0x18, + 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, + 0xfd, 0x18, 0x80, 0x90, 0x0a, 0x00, 0x43, 0x1f, 0x80, 0x90, 0x07, 0x00, + 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0xbd, 0xff, 0x18, 0x47, + 0x02, 0x6a, 0x08, 0x18, 0xf8, 0x71, 0x27, 0x08, 0xf7, 0x6d, 0x08, 0xc2, + 0xde, 0x40, 0x28, 0x09, 0x5a, 0x00, 0x48, 0x4d, 0x44, 0xe8, 0x00, 0x10, + 0x00, 0x00, 0xe4, 0xe8, 0x00, 0xf0, 0x00, 0x00, 0x48, 0x7c, 0xa8, 0xc1, + 0x4a, 0x47, 0x38, 0x09, 0x5a, 0x00 }; -unsigned int tubevc_asm_len = 264; +unsigned int tubevc_asm_len = 258; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 3312dcfc..6d614272 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -128,28 +128,30 @@ # poll for nTube being low Poll_loop: - ld r7, GPLEV0_offset(r6) - btst r7, nRST + mov r7, r0 +Poll_tube_low: + ld r8, GPLEV0_offset(r6) + btst r8, nRST beq post_reset - btst r7, nTUBE - bne Poll_loop - ld r7, GPLEV0_offset(r6) # check ntube again to remove glitches - btst r7, nTUBE - bne Poll_loop + btst r8, nTUBE + bne Poll_tube_low + ld r8, GPLEV0_offset(r6) # check ntube again to remove glitches + btst r8, nTUBE + bne Poll_tube_low # we now know nTube is low - btst r7, RnW + btst r8, RnW beq wr_cycle # So we are in a read cycle # sort out the address bus - mov r8, 0 - btst r7, r16 - orne r8, 1 - btst r7, r17 - orne r8, 2 - btst r7, r18 - orne r8, 4 - ld r8, (r0, r8) # Read word from tube register + + btst r8, r16 + orne r7, 4 + btst r8, r17 + orne r7, 8 + btst r8, r18 + orne r7, 16 + ld r8, (r7) # Read word from tube register st r13, (r6) # Drive data bus st r14, 4(r6) # Drive data bus st r15, 8(r6) # Drive data bus @@ -159,11 +161,10 @@ Poll_loop: # spin waiting for clk high rd_wait_for_clk_high1: - ld r7, GPLEV0_offset(r6) - btst r7, CLK + ld r8, GPLEV0_offset(r6) + btst r8, CLK beq rd_wait_for_clk_high1 -# we now have half a cycle to do post mail ( 500ns early) - mov r8,r7 +# we now have half a cycle to do post mail btst r8, r16 beq rd_wait_for_clk_low bl do_post_mailbox @@ -215,7 +216,6 @@ post_mail: # Post a message to indicate a reset post_reset: - mov r8, r7 bl do_post_mailbox # Wait for reset to be released (so we don't overflow the mailbox) post_reset_loop: From 82200f42d411d955c8c8d3980a3327960448db14 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 5 Mar 2017 19:39:44 +0000 Subject: [PATCH 006/149] Header file with copro_mem_reset( int length ); defined --- src/tube-client.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/tube-client.h diff --git a/src/tube-client.h b/src/tube-client.h new file mode 100644 index 00000000..715e5806 --- /dev/null +++ b/src/tube-client.h @@ -0,0 +1,10 @@ +// tube-client.h + +#ifndef TUBE_CLIENT_H +#define TUBE_CLIENT_H + + +unsigned char * copro_mem_reset(int length); + + +#endif From beb197232c4ddc6bcb9b43960df878c5113ef297 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 8 Mar 2017 21:40:49 +0000 Subject: [PATCH 007/149] Many bug fixes for using the same memory for all cores and code size reduction --- src/CMakeLists.txt | 11 +++++++---- src/armc-start.S | 18 +++++++++++------- src/cache.c | 7 ++----- src/copro-65tube.c | 7 +++++++ src/rpi-mailbox-interface.c | 2 +- src/tube-ula.c | 2 +- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e84b6ad6..2b6e278c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,19 +37,22 @@ project( tube-client C ASM ) # Add any C compiler flags here. The C flags concerned with processor tuning # are in the toolchain files toolchain-arm-none-eabi-bcm2835.cmake, etc. -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostartfiles" ) -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer" ) +#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer " ) #set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffixed-ip" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-delete-null-pointer-checks -fdata-sections -ffunction-sections ") -#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --specs=nano.specs --specs=nosys.specs -u _printf_float" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --specs=nano.specs --specs=nosys.specs -u _printf_float" ) # Set the linker flags so that we use our "custom" linker script -set( CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -Wl,-unresolved-symbols=ignore-in-object-files -Wl,-T,${PROJECT_SOURCE_DIR}/rpi.ld" ) +#set( CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -Wl,--print-gc-sections -Wl,-unresolved-symbols=ignore-in-object-files -Wl,-T,${PROJECT_SOURCE_DIR}/rpi.ld" ) + +set( CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -Wl,-T,${PROJECT_SOURCE_DIR}/rpi.ld" ) + file( GLOB core_files armc-cstartup.c diff --git a/src/armc-start.S b/src/armc-start.S index 348887b6..21fe966b 100644 --- a/src/armc-start.S +++ b/src/armc-start.S @@ -373,11 +373,7 @@ _invalidate_dtlb_mva: mcr p15, 0, r0, c8, c6, 1 mov pc, lr -#ifdef HAS_MULTICORE -_get_core: - mrc p15, 0, r0, c0, c0, 5 - and r0, #3 - mov pc, lr +#ifdef USE_MULTICORE _init_core: // On a Raspberry Pi 2 we enter in HYP mode, and need to force a switch to supervisor mode @@ -396,7 +392,7 @@ _init_not_in_hyp_mode: msr cpsr_c, r0 _init_continue: - ldr r4,=start + ldr r4,=_start // Initialise Stack Pointers --------------------------------------------- // We're going to use interrupt mode, so setup the interrupt mode @@ -444,7 +440,10 @@ _init_continue: vmsr fpexc, r0 bl run_core +#endif +#ifdef HAS_MULTICORE + // If main does return for some reason, just catch it and stay here. _spin_core: #ifdef DEBUG @@ -467,7 +466,12 @@ _spin_core: _spin_core1: wfi b _spin_core1 - + +_get_core: + mrc p15, 0, r0, c0, c0, 5 + and r0, #3 + mov pc, lr + #endif #ifdef HAS_40PINS diff --git a/src/cache.c b/src/cache.c index 88cbeadb..2b0af620 100644 --- a/src/cache.c +++ b/src/cache.c @@ -14,8 +14,8 @@ const static unsigned l1_cached_threshold = L2_CACHED_MEM_BASE >> 20; const static unsigned l2_cached_threshold = UNCACHED_MEM_BASE >> 20; const static unsigned uncached_threshold = PERIPHERAL_BASE >> 20; -volatile __attribute__ ((aligned (0x4000))) unsigned PageTable[4096]; -volatile __attribute__ ((aligned (0x4000))) unsigned PageTable2[NUM_4K_PAGES]; +volatile __attribute__ ((aligned (0x4000))) unsigned int PageTable[4096]; +volatile __attribute__ ((aligned (0x4000))) unsigned int PageTable2[NUM_4K_PAGES]; const static int aa = 1; const static int bb = 1; @@ -217,9 +217,6 @@ void enable_MMU_and_IDCaches(void) map_4k_page(base, base); } - // Make page 64K point to page 0 so that accesses LDA 0xFFFF, X work without needing masking - map_4k_page(16, 0); - // relocate the vector pointer to the moved page asm volatile("mcr p15, 0, %[addr], c12, c0, 0" : : [addr] "r" (HIGH_VECTORS_BASE)); diff --git a/src/copro-65tube.c b/src/copro-65tube.c index d940d2a5..592cd3f9 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -18,6 +18,7 @@ #include "tuberom_6502.h" #include "programs.h" #include "copro-65tube.h" +#include "cache.h" #ifdef HISTOGRAM @@ -63,6 +64,9 @@ void copro_65tube_emulator() { unsigned char * mpu_memory; // now the arm vectors have moved we can set the core memory to start at 0 mpu_memory = copro_65tube_poweron_reset(); copro_65tube_reset(mpu_memory); + + // Make page 64K point to page 0 so that accesses LDA 0xFFFF, X work without needing masking + map_4k_page(16, 0); while (copro == last_copro) { #ifdef HISTOGRAM @@ -76,5 +80,8 @@ void copro_65tube_emulator() { #endif copro_65tube_reset(mpu_memory); } + + // restore memory mapping + map_4k_page(16, 16); } diff --git a/src/rpi-mailbox-interface.c b/src/rpi-mailbox-interface.c index 1fb55361..ecad8b6a 100644 --- a/src/rpi-mailbox-interface.c +++ b/src/rpi-mailbox-interface.c @@ -9,7 +9,7 @@ we only have 28-bits available in the property interface protocol to pass the address of the buffer to the VC. */ static int pt[PROP_BUFFER_SIZE] __attribute__((aligned(16))); -static int pt_index = 0; +static int pt_index ; //#define PRINT_PROP_DEBUG 1 diff --git a/src/tube-ula.c b/src/tube-ula.c index 88b9508e..625f24db 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -227,12 +227,12 @@ static void tube_host_read(uint16_t addr) ph1len--; if ( ph1len != 0) { - HSTAT1 &= ~HBIT_7; if (ph1rdpos== 23) ph1rdpos =0; else ph1rdpos++; } + if (!ph1len) HSTAT1 &= ~HBIT_7; PSTAT1 |= 0x40; } // tube_updateints_IRQ(); // the above can't change the irq status From 37ff567c22a1e61793e709c8fdb1b65e4fbec048 Mon Sep 17 00:00:00 2001 From: dp111 Date: Thu, 9 Mar 2017 19:18:10 +0000 Subject: [PATCH 008/149] Make Lib6502 only available in DEBUG mode. Saves about 75K of code space --- src/tube-client.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tube-client.c b/src/tube-client.c index b2d5ef6e..1f74ba61 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -62,8 +62,13 @@ static const char * emulator_names[] = { static const func_ptr emulator_functions[] = { copro_65tube_emulator, copro_65tube_emulator, +#if DEBUG copro_lib6502_emulator, copro_lib6502_emulator, +#else + copro_65tube_emulator, + copro_65tube_emulator, +#endif copro_z80_emulator, copro_z80_emulator, copro_z80_emulator, From c8b727b63bc34f1e2f89f2609c0ac0c396211a83 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 11 Mar 2017 12:42:59 +0000 Subject: [PATCH 009/149] restore all 6502 memory map pages back to 1 to 1 --- src/copro-65tube.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index 592cd3f9..5a9be2b4 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -81,7 +81,12 @@ void copro_65tube_emulator() { copro_65tube_reset(mpu_memory); } - // restore memory mapping - map_4k_page(16, 16); + // restore memory mapping + { + int i; + for ( i= 0 ; i<17; i++ ) + map_4k_page(i, i); + } + } From a6f887d2ae54698e36ebbab10289c6a00bb8b3cc Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 12 Mar 2017 12:38:35 +0000 Subject: [PATCH 010/149] Speedup memory access as memory is now at 0x0000 --- src/copro-z80.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/copro-z80.c b/src/copro-z80.c index 31745005..21972ac2 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -282,12 +282,20 @@ int copro_z80_read_mem(unsigned int addr) { if (overlay_rom) { return copro_z80_rom[addr & 0xfff]; } else { +#if USE_MEMORY_POINTER return copro_z80_ram[addr & 0xffff]; +#else + return *(unsigned char *)(addr & 0xffff); +#endif } } void copro_z80_write_mem(unsigned int addr, unsigned char data) { +#ifdef USE_MEMORY_POINTER copro_z80_ram[addr & 0xffff] = data; +#else + *(unsigned char *)(addr & 0xffff) = data; +#endif } int copro_z80_read_io(unsigned int addr) { From cf103677021a504653a36298ec43e4fc39c01e72 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 12 Mar 2017 12:57:36 +0000 Subject: [PATCH 011/149] make copro_z80_ram static --- src/copro-z80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/copro-z80.c b/src/copro-z80.c index 21972ac2..716c7405 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -14,7 +14,7 @@ static int overlay_rom = 0; -unsigned char *copro_z80_ram; +static unsigned char *copro_z80_ram; static const unsigned char copro_z80_rom[0x1000] = { 0xf3, 0x11, 0x00, 0xf0, 0x21, 0x00, 0x00, 0x01, 0x00, 0x10, 0xed, 0xb0, 0xc3, 0x80, 0xf2, 0x43, From d8ecbf35ad17466d7637b457f72c56739712e847 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 12 Mar 2017 13:37:04 +0000 Subject: [PATCH 012/149] Speedup memory access as memory is now at 0x0000 --- src/NS32016/mem32016.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 1a318d4e..12919b69 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -31,7 +31,7 @@ #include "pandora/PandoraV2_00.h" #endif -uint8_t * ns32016ram; +static uint8_t * ns32016ram; void init_ram(void) { @@ -78,7 +78,11 @@ uint8_t read_x8(uint32_t addr) if (addr < IO_BASE) { +#ifdef USE_MEMORY_POINTER return ns32016ram[addr]; +#else + return *(unsigned char *)(addr); +#endif } if ((addr & 0xFFFFF1) == 0xFFFFF0) @@ -98,7 +102,12 @@ uint16_t read_x16(uint32_t addr) #ifdef NS_FAST_RAM if (addr < IO_BASE) { +#ifdef USE_MEMORY_POINTER return *((uint16_t*) (ns32016ram + addr)); +#else + return *((uint16_t*) ( addr)); +#endif + } #endif @@ -112,7 +121,11 @@ uint32_t read_x32(uint32_t addr) #ifdef NS_FAST_RAM if (addr < IO_BASE) { +#ifdef USE_MEMORY_POINTER return *((uint32_t*) (ns32016ram + addr)); +#else + return *((uint32_t*) (addr)); +#endif } #endif @@ -159,7 +172,11 @@ void write_x8(uint32_t addr, uint8_t val) if (addr <= (RAM_SIZE - sizeof(uint8_t))) { +#ifdef USE_MEMORY_POINTER ns32016ram[addr] = val; +#else + *(unsigned char *)(addr) = val; +#endif return; } @@ -199,7 +216,11 @@ void write_x16(uint32_t addr, uint16_t val) #ifdef NS_FAST_RAM if (addr <= (RAM_SIZE - sizeof(uint16_t))) { +#ifdef USE_MEMORY_POINTER *((uint16_t*) (ns32016ram + addr)) = val; +#else + *((uint16_t*) (addr)) = val; +#endif return; } #endif @@ -219,7 +240,11 @@ void write_x32(uint32_t addr, uint32_t val) #ifdef NS_FAST_RAM if (addr <= (RAM_SIZE - sizeof(uint32_t))) { +#ifdef USE_MEMORY_POINTER *((uint32_t*) (ns32016ram + addr)) = val; +#else + *((uint32_t*) (addr)) = val; +#endif return; } #endif From ad610f174d780a93fb4dbbbaa67a1aaa878a4ce5 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 12 Mar 2017 18:29:49 +0000 Subject: [PATCH 013/149] UART now interrupt driven, and echos received chars (for testing) Change-Id: If8740a421b224bd028473be22d2030bbcc40d993 --- src/rpi-aux.c | 88 +++++++++++++++++++++++++++++++++++++++++++-------- src/rpi-aux.h | 13 ++++++++ 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index f029a35a..323e977f 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -9,6 +9,10 @@ http://elinux.org/BCM2835_datasheet_errata */ #define FALLBACK_SYS_FREQ 250000000 +#define USE_IRQ + +#define TX_BUFFER_SIZE 65536 // Must be a power of 2 + static aux_t* auxillary = (aux_t*) AUX_BASE; aux_t* RPI_GetAux(void) @@ -16,6 +20,50 @@ aux_t* RPI_GetAux(void) return auxillary; } +#if defined(USE_IRQ) + +#include "rpi-interrupts.h" + +// Note, at the point the MiniUART is initialized, low vectors are in use +#define IRQ_VECTOR 0x38 + +static char tx_buffer[TX_BUFFER_SIZE]; +static int tx_head; +static int tx_tail; + +static void __attribute__((interrupt("IRQ"))) RPI_AuxMiniUartIRQHandler() { + + while (1) { + + int iir = auxillary->MU_IIR; + + if (iir & AUX_MUIIR_INT_NOT_PENDING) { + /* No more interrupts */ + break; + } + + /* Handle TxEmpty interrupt */ + if (iir & AUX_MUIIR_INT_IS_TX) { + if (tx_tail != tx_head) { + /* Transmit the character */ + tx_tail = (tx_tail + 1) & (TX_BUFFER_SIZE - 1); + auxillary->MU_IO = tx_buffer[tx_tail]; + } else { + /* Disable TxEmpty interrupt */ + auxillary->MU_IER &= ~AUX_MUIER_TX_INT; + } + } + + /* Handle RxReady interrupt */ + if (iir & AUX_MUIIR_INT_IS_RX) { + /* For now just echo all received characters */ + RPI_AuxMiniUartWrite(auxillary->MU_IO & 0xFF); + } + + } +} +#endif + void RPI_AuxMiniUartInit(int baud, int bits) { volatile int i; @@ -34,11 +82,6 @@ void RPI_AuxMiniUartInit(int baud, int bits) peripheral. You can not even read or write the registers */ auxillary->ENABLES = AUX_ENA_MINIUART; - /* Disable interrupts for now */ - /* auxillary->IRQ &= ~AUX_IRQ_MU; */ - - auxillary->MU_IER = 0; - /* Disable flow control,enable transmitter and receiver! */ auxillary->MU_CNTL = 0; @@ -52,41 +95,60 @@ void RPI_AuxMiniUartInit(int baud, int bits) /* Disable all interrupts from MU and clear the fifos */ auxillary->MU_IER = 0; - auxillary->MU_IIR = 0xC6; - /* Transposed calculation from Section 2.2.1 of the ARM peripherals - manual */ + /* Transposed calculation from Section 2.2.1 of the ARM peripherals manual */ auxillary->MU_BAUD = ( sys_freq / (8 * baud)) - 1; +#ifdef USE_IRQ + tx_head = tx_tail = 0; + *((uint32_t *) IRQ_VECTOR) = (uint32_t) RPI_AuxMiniUartIRQHandler; + RPI_GetIrqController()->Enable_IRQs_1 = (1 << 29); + auxillary->MU_IER |= AUX_MUIER_RX_INT; +#endif + /* Setup GPIO 14 and 15 as alternative function 5 which is UART 1 TXD/RXD. These need to be set before enabling the UART */ RPI_SetGpioPinFunction(RPI_GPIO14, FS_ALT5); RPI_SetGpioPinFunction(RPI_GPIO15, FS_ALT5); + // Note: the delay values are important, with 150 the receiver did not work! RPI_GpioBase->GPPUD = 0; - for (i = 0; i < 150; i++) + for (i = 0; i < 1000; i++) { } - RPI_GpioBase->GPPUDCLK0 = (1 << 14); - for (i = 0; i < 150; i++) + RPI_GpioBase->GPPUDCLK0 = (1 << 14) | (1 << 15); + for (i = 0; i < 1000; i++) { } RPI_GpioBase->GPPUDCLK0 = 0; /* Disable flow control,enable transmitter and receiver! */ - auxillary->MU_CNTL = AUX_MUCNTL_TX_ENABLE; + auxillary->MU_CNTL = AUX_MUCNTL_TX_ENABLE | AUX_MUCNTL_RX_ENABLE; } void RPI_AuxMiniUartWrite(char c) { +#ifdef USE_IRQ + int tmp_head = (tx_head + 1) & (TX_BUFFER_SIZE - 1); + + /* Wait for space in buffer */ + while (tmp_head == tx_tail) { + } + + tx_buffer[tmp_head] = c; + tx_head = tmp_head; + + /* Enable TxEmpty interrupt */ + auxillary->MU_IER |= AUX_MUIER_TX_INT; +#else /* Wait until the UART has an empty space in the FIFO */ while ((auxillary->MU_LSR & AUX_MULSR_TX_EMPTY) == 0) { } - /* Write the character to the FIFO for transmission */ auxillary->MU_IO = c; +#endif } extern void RPI_EnableUart(char* pMessage) diff --git a/src/rpi-aux.h b/src/rpi-aux.h index 613cd1be..dd80fc98 100644 --- a/src/rpi-aux.h +++ b/src/rpi-aux.h @@ -83,6 +83,19 @@ #define AUX_MUSTAT_RX_FIFO_LEVEL ( 7 << 16 ) #define AUX_MUSTAT_TX_FIFO_LEVEL ( 7 << 24 ) +// Interrupt enables are incorrect on page 12 of: +// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf +// See errata: +// http://elinux.org/BCM2835_datasheet_errata#p12 +#define AUX_MUIER_TX_INT ( (1 << 1) ) +#define AUX_MUIER_RX_INT ( (1 << 0 )| (1 << 2) ) + +#define AUX_MUIIR_INT_NOT_PENDING ( 1 << 0 ) +#define AUX_MUIIR_INT_IS_TX ( 1 << 1 ) +#define AUX_MUIIR_INT_IS_RX ( 1 << 2 ) + + + #define FSEL0(x) ( x ) #define FSEL1(x) ( x << 3 ) #define FSEL2(x) ( x << 6 ) From db5afc4cd199bc40c19c8a4e8db54fbcbb079c5d Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 12 Mar 2017 20:18:48 +0000 Subject: [PATCH 014/149] The start of improving GPU ULA performance --- src/copro-65tubeasm.S | 2 +- src/tube-ula.c | 25 +++++++++++++++++++++++-- src/tube-ula.h | 2 +- src/tubevc.c | 35 ++++++++++++++++++----------------- vidcore/tubevc.s | 37 +++++++++++++++++++++++++++++-------- 5 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 731aca66..b4b6359b 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1531,7 +1531,7 @@ Event_Handler: str r0, [r1] // As ARM FIQ interrupts currently disabled ldr r1, =MBOX0_READ ldr r0, [r1] - lsr r0, r0, #4 + //lsr r0, r0, #4 #else ldr r1, =tube_mailbox ldr r1, [r1] diff --git a/src/tube-ula.c b/src/tube-ula.c index 625f24db..5404a7c2 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -554,6 +554,7 @@ void tube_parasite_write(uint32_t addr, uint8_t val) int tube_io_handler(uint32_t mail) { int addr; +#ifndef USE_GPU int data; int rnw; int ntube; @@ -565,7 +566,7 @@ int tube_io_handler(uint32_t mail) static int exp_seq_num = -1; act_seq_num = (mail >> 12) & 15; #endif - +#endif // Toggle the LED on each tube access static int led = 0; if (led) { @@ -574,7 +575,25 @@ int tube_io_handler(uint32_t mail) LED_ON(); } led = ~led; - +#ifdef USE_GPU + + if ((mail >> 12) & 1) // Check for Reset + return tube_irq | 4; // Set reset Flag + else + { + addr = (mail>>8) & 7; + if ( ( (mail >>11 ) & 1) == 0) { // Check read write flag + tube_host_write(addr, mail & 0xFF); + } else { + tube_host_read(addr); + } + if ((tube_enabled && (HSTAT1 & HBIT_5))) { + return tube_irq | 4; + } else { + return tube_irq & 3; + } + } +#else addr = 0; if (mail & A0_MASK) { addr += 1; @@ -614,6 +633,7 @@ int tube_io_handler(uint32_t mail) LOG_WARN("OVERRUN: A=%d; D=%02X; RNW=%d; NTUBE=%d; nRST=%d\r\n", addr, data, rnw, ntube, nrst); } #endif + if (mail & GLITCH_MASK) { LOG_WARN("GLITCH: A=%d; D=%02X; RNW=%d; NTUBE=%d; nRST=%d\r\n", addr, data, rnw, ntube, nrst); @@ -639,6 +659,7 @@ int tube_io_handler(uint32_t mail) } else { return tube_irq & 3; } +#endif } diff --git a/src/tube-ula.h b/src/tube-ula.h index 71d81619..20f76974 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -54,7 +54,7 @@ static volatile inline int is_mailbox_non_empty() { } static volatile inline unsigned int read_mailbox() { - return (*(volatile uint32_t *)MBOX0_READ) >> 4; + return (*(volatile uint32_t *)MBOX0_READ); } #else diff --git a/src/tubevc.c b/src/tubevc.c index be414ef4..d85b4a87 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -5,21 +5,22 @@ unsigned char tubevc_asm[] = { 0x52, 0xc3, 0x50, 0x1f, 0xf2, 0xc0, 0x5f, 0x97, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x03, 0xe8, 0x80, 0xb8, 0x00, 0x7e, 0x04, 0x60, 0x06, 0xe8, - 0x00, 0x00, 0x20, 0x7e, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, 0x3b, 0x18, - 0x18, 0x6d, 0xfc, 0x18, 0x68, 0x2d, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, - 0x2a, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, - 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, - 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, - 0x65, 0x37, 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, - 0x03, 0x18, 0x80, 0x90, 0x22, 0x00, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, - 0x65, 0x3a, 0x69, 0x3a, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x67, 0x2d, - 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcf, 0x18, 0x27, 0x6d, 0xcd, 0x18, - 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, - 0xfd, 0x18, 0x80, 0x90, 0x0a, 0x00, 0x43, 0x1f, 0x80, 0x90, 0x07, 0x00, - 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0xbd, 0xff, 0x18, 0x47, - 0x02, 0x6a, 0x08, 0x18, 0xf8, 0x71, 0x27, 0x08, 0xf7, 0x6d, 0x08, 0xc2, - 0xde, 0x40, 0x28, 0x09, 0x5a, 0x00, 0x48, 0x4d, 0x44, 0xe8, 0x00, 0x10, - 0x00, 0x00, 0xe4, 0xe8, 0x00, 0xf0, 0x00, 0x00, 0x48, 0x7c, 0xa8, 0xc1, - 0x4a, 0x47, 0x38, 0x09, 0x5a, 0x00 + 0x00, 0x00, 0x20, 0x7e, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, + 0x54, 0x00, 0x18, 0x6d, 0xfb, 0x18, 0x68, 0x2d, 0x18, 0x6d, 0xf8, 0x18, + 0x28, 0x6d, 0x2c, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, + 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, + 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, + 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, + 0x10, 0x47, 0x05, 0x18, 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, + 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, 0x65, 0x3a, 0x69, 0x3a, 0x6a, 0x09, + 0x6b, 0x31, 0x6c, 0x32, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, + 0xcc, 0x18, 0x27, 0x6d, 0xca, 0x18, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, + 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, 0x47, 0xc3, 0x48, 0x47, + 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, 0xe4, 0xe8, 0xf0, 0x00, + 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, 0x07, 0xc2, 0xc8, 0x38, + 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, 0x88, 0xc1, 0x12, 0x47, + 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, 0xab, 0xff, 0x07, 0xe8, + 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, + 0x7f, 0x9e, 0xa2, 0xff }; -unsigned int tubevc_asm_len = 258; +unsigned int tubevc_asm_len = 268; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 6d614272..d31ea004 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -59,6 +59,9 @@ .equ ATTN_MASK, 31 .equ OVERRUN_MASK, 30 +.equ RESET_MAILBOX_BIT, 12 +.equ RW_MAILBOX_BIT, 11 + .org 0 # code entry point @@ -165,9 +168,12 @@ rd_wait_for_clk_high1: btst r8, CLK beq rd_wait_for_clk_high1 # we now have half a cycle to do post mail - btst r8, r16 + btst r8, r16 # no need to post mail if A0 = 0 beq rd_wait_for_clk_low - bl do_post_mailbox + sub r7, r0 # just get the address bits + lsl r7, 6 # put address bits in correct place + bset r7, RW_MAILBOX_BIT # set read bit + st r7, (r3) # store in mail box # spin waiting for clk low rd_wait_for_clk_low: @@ -209,21 +215,36 @@ wr_wait_for_clk_low: btst r7, CLK bne wr_wait_for_clk_low -# Post a message to indicate a tube register read or write -post_mail: - bl do_post_mailbox +# Post a message to indicate a tube register write + +# move databus to correct position + lsr r7,r8, D0D3_shift + lsr r4,r8, D4D7_shift -4 + and r7, 0x0F + and r4, 0xF0 + or r7, r4 + +# move address bit to correct position + btst r8, r16 + bsetne r7, 8 + btst r8, r17 + bsetne r7, 9 + btst r8, r18 + bsetne r7, 10 + st r7, (r3) # post mail b Poll_loop # Post a message to indicate a reset post_reset: - bl do_post_mailbox + mov r7, 1< Date: Sun, 12 Mar 2017 20:37:09 +0000 Subject: [PATCH 015/149] Make native arm work --- src/copro-armnativeasm.S | 4 +--- src/tube-isr.c | 8 +++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/copro-armnativeasm.S b/src/copro-armnativeasm.S index ef08ba50..90f54740 100644 --- a/src/copro-armnativeasm.S +++ b/src/copro-armnativeasm.S @@ -48,7 +48,6 @@ copro_armnative_fiq_handler: ldr r1, =MBOX0_READ // Read the GPU mailbox ldr r0, [r1] - lsr r0, r0, #4 // Shift so it looks like the format of the software mailbox bl tube_io_handler // Update the Tube ULA emulation @@ -119,8 +118,7 @@ copro_armnative_fiq_handler: ldr r1, =MBOX0_READ // Read the GPU mailbox ldr r0, [r1] - lsr r0, r0, #4 // Shift so it looks like the format of the software mailbox - + push {r0} bl tube_io_handler // Update the Tube ULA emulation pop {r0} diff --git a/src/tube-isr.c b/src/tube-isr.c index aa56ba75..1734093c 100644 --- a/src/tube-isr.c +++ b/src/tube-isr.c @@ -77,7 +77,12 @@ void copro_armnative_tube_interrupt_handler(uint32_t mail) { int ntube; int nrst; int unexpected = 0; - +#ifdef USE_GPU + addr = (mail>>8) & 7; + rnw = ( (mail >>11 ) & 1); + nrst = !((mail >> 12) & 1) ; + ntube = ((mail >> 12) & 1) ; +#else addr = 0; if (mail & A0_MASK) { addr += 1; @@ -92,6 +97,7 @@ void copro_armnative_tube_interrupt_handler(uint32_t mail) { rnw = (mail >> RNW_PIN) & 1; ntube = (mail >> NTUBE_PIN) & 1; nrst = (mail >> NRST_PIN) & 1; +#endif // Handle a reset if (nrst == 0) { From 8f81a8fdee0f14d1a31742503ab86e2f303d790e Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 12 Mar 2017 22:05:03 +0000 Subject: [PATCH 016/149] Start of adding *fx151,226,xx commands --- src/tube-ula.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 5404a7c2..dabb7bc5 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -90,7 +90,7 @@ static volatile uint8_t *tube_regs; extern volatile uint32_t gpfsel_data_idle[3]; extern volatile uint32_t gpfsel_data_driving[3]; const static uint32_t magic[3] = {MAGIC_C0, MAGIC_C1, MAGIC_C2 | MAGIC_C3 }; - +static char copro_command =0; static perf_counters_t pct; uint8_t ph1[24],ph3_1; @@ -187,6 +187,25 @@ static void tube_updateints_NMI() if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=2; } */ +void copro_command_excute(unsigned char copro_command,unsigned char val) +{ + switch (copro_command) + { + case 0 : + if (val == 0) + copro_speed = 0; + else + copro_speed = (arm_speed/(1000000/256) / val); + LOG_DEBUG("New speed Copro = %u, %u\n", val, copro_speed); + return; + + default : + + break; + } + +} + static void tube_reset() { tube_enabled = 1; @@ -299,6 +318,9 @@ static void tube_host_write(uint16_t addr, uint8_t val) HSTAT1 &= ~HBIT_6; if (HSTAT1 & HBIT_1) tube_irq |= 1;//tube_updateints_IRQ(); break; + case 2: + copro_command = val; + break; case 3: /*Register 2*/ //if (!tube_enabled) // return; @@ -307,13 +329,8 @@ static void tube_host_write(uint16_t addr, uint8_t val) HSTAT2 &= ~HBIT_6; break; case 4: - if (val == 0) - copro_speed = 0; - else - copro_speed = (arm_speed/(1000000/256) / val); - LOG_DEBUG("New speed Copro = %u, %u\n", val, copro_speed); - return; - + copro_command_excute(copro_command,val); + break; case 5: /*Register 3*/ // if (!tube_enabled) // return; From e02fbc3c8ea2b00665ec519b89caba91ebcde3ea Mon Sep 17 00:00:00 2001 From: David Banks Date: Mon, 13 Mar 2017 18:04:41 +0000 Subject: [PATCH 017/149] Simple debugger with a couple of command; things crash very quickly! Change-Id: Iff24744bbebbe028f28c4bc606bbe1a32517c985 --- src/CMakeLists.txt | 8 ++ src/debugger/debugger.c | 192 ++++++++++++++++++++++++++++++++++++++++ src/debugger/debugger.h | 1 + src/rpi-aux.c | 14 +-- 4 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 src/debugger/debugger.c create mode 100644 src/debugger/debugger.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b6e278c..64489380 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -242,6 +242,12 @@ file( GLOB copro_arm_files darm/thumb-tbl.h ) +# Interactive debugger +file( GLOB debugger_files + debugger/debugger.c + debugger/debugger.h +) + if( ${DEBUG} ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG=1" ) @@ -255,6 +261,7 @@ if( ${MINIMAL_BUILD} ) add_executable( tube-client ${core_files} + ${debugger_files} ${copro_65tube_files} ${shared_6502_files} ) @@ -263,6 +270,7 @@ else() add_executable( tube-client ${core_files} + ${debugger_files} ${copro_65tube_files} ${copro_lib6502_files} ${shared_6502_files} diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c new file mode 100644 index 00000000..168d232f --- /dev/null +++ b/src/debugger/debugger.c @@ -0,0 +1,192 @@ +#include +#include +#include +#include + +#include "debugger.h" +#include "../rpi-aux.h" + +#define NUM_CMDS 4 + +// The Atom CRC Polynomial +#define CRC_POLY 0x002d + +static void doCmdCrc(char *params); +static void doCmdFill(char *params); +static void doCmdHelp(char *params); +static void doCmdMem(char *params); + +// The command process accepts abbreviated forms, for example +// if h is entered, then help will match. + +// Must be kept in step with dbgCmdFuncs (just below) +static char *dbgCmdStrings[NUM_CMDS] = { + "help", + "fill", + "crc", + "mem", +}; + +// Must be kept in step with dbgCmdStrings (just above) +static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { + doCmdHelp, + doCmdFill, + doCmdCrc, + doCmdMem, +}; + + +/******************************************************** + * Other global variables + ********************************************************/ + +char cmd[1000]; + + +// The current memory address (e.g. used when disassembling) +unsigned int memAddr = 0; + +/******************************************* + * Memory accessors + *******************************************/ + +static void writeMem(uint32_t address, uint8_t data) { + *(uint8_t *)(address) = data; +} + +static uint8_t readMem(uint32_t address) { + return *(uint8_t *)(address); +} + +/******************************************* + * User Commands + *******************************************/ + +static void doCmdHelp(char *params) { + int i; + printf("Commands:\r\n"); + for (i = 0; i < NUM_CMDS; i++) { + printf(" %s\r\n", dbgCmdStrings[i]); + } +} + +static void doCmdFill(char *params) { + long i; + unsigned int start; + unsigned int end; + unsigned int data; + sscanf(params, "%x %x %x", &start, &end, &data); + printf("Wr: %04X to %04X = %02X\r\n", start, end, data); + for (i = start; i <= end; i++) { + writeMem(i, data); + } +} + +static void doCmdCrc(char *params) { + long i; + int j; + unsigned int start; + unsigned int end; + unsigned int data; + unsigned int crc = 0; + sscanf(params, "%x %x", &start, &end); + for (i = start; i <= end; i++) { + data = readMem(i); + for (j = 0; j < 8; j++) { + crc = crc << 1; + crc = crc | (data & 1); + data >>= 1; + if (crc & 0x10000) + crc = (crc ^ CRC_POLY) & 0xFFFF; + } + } + printf("crc: %04X\r\n", crc); +} + +static void doCmdMem(char *params) { + int i, j; + unsigned int row[16]; + sscanf(params, "%x", &memAddr); + for (i = 0; i < 0x100; i+= 16) { + for (j = 0; j < 16; j++) { + row[j] = readMem(memAddr + i + j); + } + printf("%04X ", memAddr + i); + for (j = 0; j < 16; j++) { + printf("%02X ", row[j]); + } + printf(" "); + for (j = 0; j < 16; j++) { + unsigned int c = row[j]; + if (c < 32 || c > 126) { + c = '.'; + } + printf("%c", c); + } + printf("\r\n"); + } + memAddr += 0x100; +} + +/******************************************************** + * User Command Processor + ********************************************************/ + +static void dispatchCmd(char *cmd) { + int i; + char *cmdString; + int minLen; + int cmdStringLen; + int cmdLen = 0; + while (cmd[cmdLen] >= 'a' && cmd[cmdLen] <= 'z') { + cmdLen++; + } + for (i = 0; i < NUM_CMDS; i++) { + cmdString = dbgCmdStrings[i]; + cmdStringLen = strlen(cmdString); + minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; + if (strncmp(cmdString, cmd, minLen) == 0) { + (*dbgCmdFuncs[i])(cmd + cmdLen); + return; + } + } + printf("Unknown command %s\r\n", cmd); +} + +/******************************************************** + * External interface + ********************************************************/ + +void debugger_rx_char(char c) { + static int i = 0; + if (c == 8) { + // Handle backspace/delete + if (i > 0) { + i--; + RPI_AuxMiniUartWrite(c); + RPI_AuxMiniUartWrite(32); + RPI_AuxMiniUartWrite(c); + } + } else if (c == 13) { + // Handle return + if (i == 0) { + while (cmd[i]) { + RPI_AuxMiniUartWrite(cmd[i++]); + } + } else { + cmd[i] = 0; + } + RPI_AuxMiniUartWrite(10); + RPI_AuxMiniUartWrite(13); + dispatchCmd(cmd); + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite(' '); + i = 0; + } else if (c >= 32) { + // Handle any other non-control character + RPI_AuxMiniUartWrite(c); + cmd[i++] = c; + } +} + diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h new file mode 100644 index 00000000..8393a322 --- /dev/null +++ b/src/debugger/debugger.h @@ -0,0 +1 @@ +void debugger_rx_char(char c); diff --git a/src/rpi-aux.c b/src/rpi-aux.c index 323e977f..18825ba8 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -3,6 +3,7 @@ #include "rpi-base.h" #include "rpi-gpio.h" #include "info.h" +#include "debugger/debugger.h" /* Define the system clock frequency in MHz for the baud rate calculation. This is clearly defined on the BCM2835 datasheet errata page: @@ -42,6 +43,12 @@ static void __attribute__((interrupt("IRQ"))) RPI_AuxMiniUartIRQHandler() { break; } + /* Handle RxReady interrupt */ + if (iir & AUX_MUIIR_INT_IS_RX) { + /* Forward all received characters to the debugger */ + debugger_rx_char(auxillary->MU_IO & 0xFF); + } + /* Handle TxEmpty interrupt */ if (iir & AUX_MUIIR_INT_IS_TX) { if (tx_tail != tx_head) { @@ -53,13 +60,6 @@ static void __attribute__((interrupt("IRQ"))) RPI_AuxMiniUartIRQHandler() { auxillary->MU_IER &= ~AUX_MUIER_TX_INT; } } - - /* Handle RxReady interrupt */ - if (iir & AUX_MUIIR_INT_IS_RX) { - /* For now just echo all received characters */ - RPI_AuxMiniUartWrite(auxillary->MU_IO & 0xFF); - } - } } #endif From e811f5724d8d329b0f9932b9e6ee6efdf4fc6382 Mon Sep 17 00:00:00 2001 From: David Banks Date: Tue, 14 Mar 2017 14:10:57 +0000 Subject: [PATCH 018/149] Added Pandora 1.00 ROM for reference Change-Id: Ib08245c00f3622aab692099c24f9040e9a87ccf9 --- src/NS32016/mem32016.c | 11 +- src/NS32016/pandora/PandoraV1_00.h | 2733 ++++++++++++++++++++++++++ src/NS32016/pandora/PandoraV1_00.rom | Bin 0 -> 32768 bytes 3 files changed, 2741 insertions(+), 3 deletions(-) create mode 100644 src/NS32016/pandora/PandoraV1_00.h create mode 100644 src/NS32016/pandora/PandoraV1_00.rom diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 12919b69..c4abc185 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -28,7 +28,12 @@ #define ROM fpu_test #endif #else +// #include "pandora/PandoraV0_61.h" +// #define PANDORA_VERSION PandoraV0_61 +// #include "pandora/PandoraV1_00.h" +// #define PANDORA_VERSION PandoraV1_00 #include "pandora/PandoraV2_00.h" +#define PANDORA_VERSION PandoraV2_00 #endif static uint8_t * ns32016ram; @@ -39,13 +44,13 @@ void init_ram(void) #ifdef TEST_SUITE memcpy(ns32016ram, ROM, sizeof(ROM)); #elif defined(PANDORA_BASE) - memcpy(ns32016ram + PANDORA_BASE, PandoraV2_00, sizeof(PandoraV2_00)); + memcpy(ns32016ram + PANDORA_BASE, PANDORA_VERSION, sizeof(PANDORA_VERSION)); #else uint32_t Address; - for (Address = 0; Address < MEG16; Address += sizeof(PandoraV2_00)) + for (Address = 0; Address < MEG16; Address += sizeof(PANDORA_VERSION)) { - memcpy(ns32016ram + Address, PandoraV2_00, sizeof(PandoraV2_00)); + memcpy(ns32016ram + Address, PANDORA_VERSION, sizeof(PANDORA_VERSION)); } #endif } diff --git a/src/NS32016/pandora/PandoraV1_00.h b/src/NS32016/pandora/PandoraV1_00.h new file mode 100644 index 00000000..e07b82f7 --- /dev/null +++ b/src/NS32016/pandora/PandoraV1_00.h @@ -0,0 +1,2733 @@ +uint8_t PandoraV1_00[] = { + 0x7f, 0xaa, 0xc0, 0xf0, 0x07, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x08, 0x64, 0x14, 0xd0, 0x00, 0x20, 0x00, 0x42, 0x00, 0xc0, 0x00, + 0x04, 0x0b, 0xd0, 0x00, 0xe3, 0x13, 0xc0, 0x00, 0xeb, 0x13, 0xc0, 0x00, + 0xf2, 0x13, 0xc0, 0x00, 0xf9, 0x13, 0xc0, 0x00, 0xa0, 0x0e, 0xc0, 0x00, + 0x00, 0x14, 0xc0, 0x00, 0x07, 0x14, 0xc0, 0x00, 0x0e, 0x14, 0xc0, 0x00, + 0x15, 0x14, 0xc0, 0x00, 0x1c, 0x14, 0xc0, 0x00, 0x46, 0x14, 0xc0, 0x00, + 0x4f, 0x14, 0xc0, 0x00, 0x58, 0x14, 0xc0, 0x00, 0x61, 0x14, 0xc0, 0x00, + 0x69, 0x14, 0xc0, 0x00, 0x71, 0x14, 0xc0, 0x00, 0x79, 0x14, 0xc0, 0x00, + 0x81, 0x14, 0xc0, 0x00, 0x89, 0x14, 0xc0, 0x00, 0x91, 0x14, 0xc0, 0x00, + 0x99, 0x14, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf5, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xff, 0xfd, 0xf2, 0xe0, 0x03, 0x01, + 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x05, 0x01, 0x14, 0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, + 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x00, 0x01, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, + 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x01, 0x01, 0x1d, 0x4f, 0x53, 0x5f, + 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x63, 0x61, + 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x75, 0x73, + 0x65, 0x72, 0x02, 0x01, 0x2b, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, + 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x20, 0x70, + 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x4f, 0x53, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, + 0x03, 0x01, 0x25, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x53, + 0x56, 0x43, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x20, 0x62, 0x79, 0x20, 0x4f, 0x53, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x69, + 0x6c, 0x65, 0x67, 0x65, 0x04, 0x01, 0x20, 0x49, 0x6c, 0x6c, 0x65, 0x67, + 0x61, 0x6c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x61, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x20, 0x62, 0x79, 0x20, 0x4f, 0x53, 0x5f, 0x4f, 0x53, + 0x43, 0x4c, 0x49, 0x06, 0x01, 0x11, 0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, + 0x33, 0x32, 0x30, 0x31, 0x36, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x1b, + 0x01, 0x06, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0xfe, 0x01, 0x0b, 0x45, + 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0xff, 0x01, + 0x0b, 0x4b, 0x65, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0xd7, 0x05, 0xd7, 0x0d, 0x57, 0xd0, 0x81, 0x58, 0xce, 0x99, 0x46, 0x00, + 0x00, 0xce, 0x18, 0x48, 0x02, 0x97, 0x06, 0x04, 0xa7, 0xd0, 0x08, 0x8f, + 0x09, 0x0e, 0x00, 0x00, 0x57, 0xb8, 0x17, 0xb8, 0x12, 0x00, 0x74, 0xa5, + 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x05, 0x72, 0x12, 0x00, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, + 0x7c, 0x54, 0xa8, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, + 0x76, 0x74, 0xa0, 0x07, 0x12, 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, + 0x80, 0xb7, 0x81, 0x20, 0x44, 0xa0, 0x80, 0x5a, 0x2d, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x04, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, + 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x98, 0xa8, 0x76, 0x7c, + 0xa1, 0x20, 0x12, 0x00, 0x7c, 0xa1, 0x20, 0xee, 0x40, 0xd8, 0x10, 0x8a, + 0x1c, 0x7d, 0xef, 0xd8, 0x04, 0x0c, 0x00, 0x10, 0x00, 0x16, 0x00, 0x84, + 0x82, 0x5f, 0x10, 0x12, 0x00, 0x97, 0xd0, 0x80, 0xd0, 0x12, 0x00, 0x2f, + 0x15, 0x12, 0x00, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x06, + 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, + 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x1d, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0x0d, 0x76, 0x44, 0xa0, 0x9d, 0x1a, 0x07, 0x7c, 0xa1, 0x20, + 0x12, 0x00, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x74, + 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x98, 0xa8, 0x76, 0xd7, 0x10, 0x4e, + 0x95, 0xa0, 0x08, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x94, 0xa8, 0x76, + 0x34, 0xa0, 0x07, 0x3c, 0xd4, 0x81, 0x54, 0x7d, 0xa1, 0x00, 0x20, 0x12, + 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0x10, 0x00, 0x05, 0x00, 0x05, + 0x02, 0x05, 0x08, 0x0e, 0x04, 0x01, 0x01, 0x05, 0x00, 0x10, 0x10, 0x10, + 0x0d, 0x00, 0x08, 0x80, 0x10, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x05, 0x09, 0x05, 0x00, 0x08, 0x10, 0x10, 0x0d, 0x0d, 0x80, 0x08, + 0x80, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0x8d, 0x81, 0x20, 0x44, + 0xa0, 0x00, 0x0a, 0x80, 0x8a, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0xa5, 0x08, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, + 0x04, 0x0d, 0x80, 0xaa, 0x0a, 0x0f, 0x11, 0xce, 0x18, 0x50, 0x7e, 0xea, + 0x12, 0x44, 0xa0, 0x14, 0xba, 0x04, 0x5f, 0x08, 0xce, 0x58, 0x08, 0xce, + 0x18, 0xe0, 0xd9, 0xbf, 0x9c, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x05, 0x76, 0x1c, 0x00, 0x0a, 0x10, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, + 0x54, 0xe5, 0x50, 0x7f, 0x76, 0xcc, 0x07, 0x75, 0x04, 0x0d, 0x80, 0xaa, + 0x08, 0xce, 0x18, 0x50, 0x7f, 0xea, 0x08, 0xce, 0x18, 0xe0, 0xd9, 0xbf, + 0x85, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x1c, 0x00, + 0x0a, 0x10, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xaf, 0x50, 0x76, + 0x7f, 0xcc, 0x07, 0x75, 0x5f, 0xd0, 0x81, 0x20, 0x7d, 0xa1, 0x00, 0x20, + 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, + 0x54, 0x55, 0x06, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x55, + 0x05, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x55, 0x04, 0x76, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x07, 0x76, 0x74, 0xa5, + 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x76, 0x74, 0xa5, 0x07, 0x74, + 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x1c, 0x00, 0x7a, + 0x10, 0xa7, 0xde, 0xbd, 0xbe, 0x81, 0x58, 0x02, 0xbd, 0xdd, 0x7c, 0xa3, + 0x20, 0x12, 0x00, 0x17, 0x50, 0x00, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0x14, 0xaa, 0x76, 0x00, 0x8f, 0x00, 0x04, 0xa2, 0x0d, 0x7f, 0x1a, 0x70, + 0xd7, 0x00, 0xe3, 0x50, 0x00, 0x8f, 0x1f, 0x7c, 0xa1, 0x20, 0x12, 0x00, + 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x34, 0x81, 0x20, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x10, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, + 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, + 0x81, 0x20, 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, + 0x12, 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x3d, 0x81, 0x20, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0e, 0x76, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x74, 0xa5, 0x07, 0x74, 0x9a, + 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x34, 0xa0, 0x07, 0x9a, 0x09, 0x97, 0xa6, + 0x00, 0x00, 0x01, 0xfe, 0x00, 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, + 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0x82, 0x81, 0x20, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x12, 0x76, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x1c, 0x08, 0x1a, 0x1e, 0x74, 0xa5, + 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, + 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x7d, 0xa1, 0x00, 0x20, + 0x12, 0x00, 0x1f, 0x18, 0x0a, 0x1c, 0x14, 0x50, 0x00, 0x07, 0xa0, 0x00, + 0x00, 0x00, 0x0d, 0x0a, 0x11, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x05, 0x76, 0x8f, 0x1f, 0x8f, 0x10, 0xea, 0x64, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0xce, 0x58, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x1c, 0x08, 0x0a, 0x08, + 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0xa7, 0xde, 0xbb, 0xcf, 0x81, 0x58, + 0x02, 0xbc, 0xac, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0xaf, 0xd4, 0x81, + 0x24, 0xa7, 0xde, 0x80, 0x59, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0xa5, 0x0c, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x15, 0x76, 0x5f, 0x02, 0x4e, 0xc3, 0xa0, 0x08, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0x1d, 0x76, 0xcf, 0x07, 0x73, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, + 0xa8, 0x76, 0x5f, 0x02, 0x4e, 0xd7, 0xa0, 0x08, 0x74, 0xa5, 0x07, 0x74, + 0x9a, 0x7c, 0xd4, 0xa8, 0x76, 0xcf, 0x07, 0x73, 0x5f, 0xd0, 0x81, 0x20, + 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, + 0xd7, 0x1d, 0x27, 0xd0, 0x80, 0xe8, 0x17, 0x22, 0x00, 0x17, 0x2a, 0x04, + 0x17, 0x32, 0x08, 0x17, 0x3a, 0x0c, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, + 0x80, 0x93, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, + 0x14, 0x76, 0xd7, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xe5, 0x43, 0x7f, 0x76, 0xcf, 0x1f, 0x75, 0xd7, 0xc8, + 0x00, 0x1f, 0x18, 0x0a, 0x19, 0x14, 0x50, 0x00, 0x04, 0xa0, 0x0d, 0x0a, + 0x11, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x8f, 0x1f, + 0x8f, 0x10, 0xea, 0x67, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, + 0x0d, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x74, + 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, + 0x6b, 0xa0, 0x00, 0x00, 0x00, 0x7f, 0x27, 0xd0, 0x80, 0xe8, 0xd7, 0xa0, + 0x00, 0x00, 0x00, 0x10, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xaf, + 0x43, 0x76, 0x7f, 0xcf, 0x1f, 0x75, 0x17, 0x41, 0x00, 0x57, 0x41, 0x04, + 0x97, 0x41, 0x08, 0xd7, 0x41, 0x0c, 0xd7, 0xb8, 0x7c, 0xa1, 0x20, 0x12, + 0x00, 0xd7, 0xb8, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0xaf, 0xd4, 0x81, + 0x24, 0xa7, 0xde, 0x80, 0x8d, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0xa5, 0x16, 0x76, 0x94, 0x0e, 0x80, 0xe8, 0x67, 0xd0, 0x80, + 0xe8, 0x54, 0x12, 0x01, 0x57, 0x1a, 0x02, 0x57, 0x22, 0x06, 0x57, 0x2a, + 0x0a, 0x14, 0xa0, 0x0e, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xe5, + 0x48, 0x7f, 0x76, 0xcc, 0x07, 0x75, 0x14, 0xa0, 0x0d, 0x74, 0xa5, 0x07, + 0x74, 0x9a, 0x7c, 0x14, 0xaf, 0x48, 0x76, 0x00, 0xcc, 0x07, 0x75, 0x57, + 0x49, 0x0a, 0x17, 0x49, 0x06, 0xd7, 0x48, 0x02, 0xce, 0x98, 0x48, 0x01, + 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x74, 0xa5, 0x07, + 0x74, 0x9a, 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x04, 0xd5, 0x80, 0xe8, 0x01, + 0xaa, 0x10, 0x04, 0xd5, 0x80, 0xe8, 0x04, 0x4a, 0x09, 0x1f, 0x20, 0xbc, + 0x00, 0x4e, 0x20, 0x00, 0x34, 0xa0, 0x07, 0x5f, 0xd0, 0x81, 0x20, 0x8a, + 0x04, 0x12, 0x00, 0x97, 0xa6, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x7c, 0xa3, + 0x20, 0x12, 0x00, 0x62, 0x07, 0xce, 0x98, 0x48, 0x00, 0xcf, 0x10, 0x0b, + 0x8f, 0x08, 0x14, 0x48, 0x00, 0x02, 0xbb, 0x0d, 0xcf, 0x17, 0x78, 0x72, + 0xe0, 0x12, 0x00, 0xd5, 0x05, 0x14, 0x48, 0x00, 0x1c, 0x00, 0x0a, 0x14, + 0x02, 0xba, 0xfa, 0x04, 0xa0, 0x0d, 0x1a, 0x08, 0x14, 0xa0, 0x0a, 0x02, + 0xba, 0xef, 0x8f, 0x08, 0xea, 0x69, 0x15, 0xb8, 0x12, 0x00, 0xd7, 0x0d, + 0x57, 0xc8, 0x04, 0x02, 0x5c, 0x67, 0x4e, 0x01, 0x04, 0x57, 0xb8, 0x12, + 0x00, 0xd7, 0x0d, 0x57, 0xc8, 0x04, 0x02, 0x4d, 0x67, 0x4e, 0x01, 0x04, + 0x57, 0xb8, 0x02, 0x64, 0x0d, 0x00, 0x12, 0x00, 0x62, 0x03, 0xce, 0x58, + 0xa0, 0x20, 0x0f, 0x0e, 0x2e, 0x08, 0xc8, 0x04, 0x04, 0x00, 0xa0, 0x30, + 0x04, 0x05, 0x39, 0x7a, 0x04, 0x8c, 0x03, 0x02, 0xba, 0xab, 0x1f, 0x08, + 0x1a, 0x6a, 0x72, 0xc0, 0x12, 0x00, 0x62, 0x03, 0xce, 0x58, 0xa0, 0x08, + 0xea, 0x5e, 0x62, 0x03, 0xce, 0x58, 0xa0, 0x18, 0xea, 0x56, 0x82, 0x02, + 0x0c, 0x67, 0xc0, 0x74, 0x02, 0x09, 0x02, 0xbf, 0x6d, 0x92, 0x40, 0x12, + 0x00, 0x62, 0x17, 0x27, 0xa9, 0x0a, 0xd4, 0x25, 0x1f, 0x00, 0x97, 0x00, + 0xce, 0x33, 0x20, 0xce, 0xb7, 0x20, 0x4e, 0xf0, 0x15, 0xc0, 0xa5, 0x30, + 0x4f, 0x00, 0x72, 0x7a, 0x05, 0xd4, 0xa5, 0x2d, 0xa7, 0x48, 0x01, 0x67, + 0xb8, 0xdf, 0x07, 0x0e, 0x00, 0x06, 0x7f, 0x05, 0x72, 0x68, 0x4e, 0x74, + 0x02, 0x00, 0x17, 0xb8, 0x12, 0x00, 0x5c, 0xa8, 0xc0, 0xf9, 0x00, 0x00, + 0x0e, 0x0b, 0x00, 0x67, 0xad, 0xc0, 0xf0, 0x00, 0x00, 0x80, 0xd8, 0xef, + 0xa4, 0x00, 0x00, 0x01, 0x00, 0x27, 0xd8, 0xb8, 0x63, 0x6f, 0x07, 0x17, + 0xa0, 0x00, 0x02, 0x00, 0x00, 0x57, 0x00, 0x4e, 0x48, 0xa0, 0x11, 0x8a, + 0x04, 0x5f, 0x08, 0x97, 0x40, 0x00, 0xd7, 0x48, 0x00, 0x17, 0xa2, 0x55, + 0x55, 0xaa, 0xaa, 0x00, 0x57, 0xa2, 0xaa, 0xaa, 0x55, 0x55, 0x00, 0x07, + 0x45, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x1a, 0x3a, 0x07, 0x4d, 0x00, 0xaa, + 0xaa, 0x55, 0x55, 0x1a, 0x31, 0x17, 0xa2, 0xaa, 0xaa, 0x55, 0x55, 0x00, + 0x57, 0xa2, 0x55, 0x55, 0xaa, 0xaa, 0x00, 0x07, 0x45, 0x00, 0xaa, 0xaa, + 0x55, 0x55, 0x1a, 0x1a, 0x07, 0x4d, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x1a, + 0x11, 0x17, 0x12, 0x00, 0x57, 0x1a, 0x00, 0x03, 0xa0, 0x00, 0x02, 0x00, + 0x00, 0xea, 0xbf, 0xa4, 0x17, 0x12, 0x00, 0x57, 0x1a, 0x00, 0x57, 0x00, + 0x63, 0xa0, 0x00, 0x00, 0x02, 0xe2, 0xef, 0x0c, 0xd7, 0x05, 0xd7, 0x08, + 0x67, 0xa8, 0x00, 0xa7, 0xa8, 0x04, 0x17, 0xa0, 0x00, 0x00, 0x00, 0x3f, + 0x5f, 0x48, 0x00, 0x0e, 0x03, 0x00, 0x67, 0xad, 0xc0, 0xf0, 0x00, 0x00, + 0x80, 0xc8, 0x67, 0xad, 0xc0, 0xf0, 0x00, 0x00, 0x80, 0xd8, 0x67, 0xdd, + 0x82, 0xa8, 0x08, 0x57, 0x1d, 0x80, 0xc0, 0xe7, 0xad, 0x80, 0xc0, 0xe7, + 0xdd, 0x05, 0x32, 0x00, 0x97, 0xbe, 0x80, 0xcc, 0x57, 0xa6, 0x65, 0x76, + 0x61, 0x64, 0x7c, 0x67, 0xc8, 0x7c, 0xa7, 0x48, 0x7c, 0x17, 0xa0, 0x00, + 0x00, 0x00, 0xff, 0x0e, 0x03, 0x01, 0x67, 0xc8, 0x00, 0x63, 0xa0, 0x00, + 0x00, 0x04, 0x00, 0x97, 0x0e, 0x80, 0xd4, 0xa7, 0xae, 0x81, 0x00, 0x80, + 0xd0, 0x02, 0xbe, 0x80, 0x50, 0x61, 0x6e, 0x64, 0x6f, 0x72, 0x61, 0x20, + 0x33, 0x32, 0x30, 0x31, 0x36, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x0d, 0x00, 0x17, 0xd0, 0x80, 0xcc, + 0x02, 0xbe, 0x4e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x73, 0x69, + 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x00, 0x4e, 0x17, 0xa0, 0xf6, 0x02, 0xbe, + 0x8c, 0x02, 0xbe, 0x44, 0x20, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x0d, 0x00, 0x02, 0x81, 0x60, 0xa7, 0xde, 0x28, 0x81, 0x20, + 0xdf, 0xd0, 0x81, 0x18, 0x7d, 0xa3, 0x08, 0x00, 0x74, 0xa5, 0x06, 0x70, + 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x72, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0x94, 0xae, 0x76, 0x81, 0x2c, 0x5f, 0xd0, 0x81, 0x20, 0xea, 0x12, 0x67, + 0xd0, 0x81, 0x74, 0x97, 0xa0, 0x00, 0x00, 0x00, 0xea, 0xe2, 0x1f, 0xe2, + 0x02, 0xe2, 0x04, 0x5c, 0x08, 0xdc, 0x10, 0x02, 0xb8, 0xf7, 0x97, 0x16, + 0x80, 0x8c, 0x9c, 0xd1, 0x80, 0x8c, 0x0a, 0x0b, 0xce, 0x18, 0xa8, 0xc0, + 0xf9, 0x00, 0x00, 0xea, 0x0e, 0x54, 0xa0, 0xa1, 0x94, 0xa0, 0x12, 0x02, + 0xb8, 0xdb, 0xce, 0x18, 0x18, 0x97, 0x06, 0x80, 0xd8, 0x28, 0xa0, 0x03, + 0x7c, 0xe7, 0xd8, 0x04, 0x08, 0x0d, 0x12, 0x17, 0x0e, 0x0b, 0x00, 0xea, + 0x0f, 0x0e, 0x0b, 0x01, 0xea, 0x0a, 0x0e, 0x0b, 0x02, 0xea, 0x05, 0x0e, + 0x0b, 0x03, 0x02, 0x81, 0x5e, 0x84, 0xa6, 0x00, 0x81, 0x3c, 0x0a, 0x80, + 0x83, 0x97, 0xa6, 0x12, 0x34, 0x56, 0x78, 0x81, 0x30, 0x84, 0xa6, 0x80, + 0x81, 0x2c, 0x1a, 0x81, 0x55, 0x87, 0xa6, 0x64, 0x61, 0x6f, 0x4c, 0x81, + 0x40, 0x1a, 0x81, 0x4a, 0x17, 0xd0, 0x81, 0x10, 0x02, 0x80, 0x7f, 0x9a, + 0x81, 0x40, 0x97, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x81, 0x64, 0x97, 0x06, + 0x81, 0x6c, 0x97, 0x0e, 0x81, 0x38, 0x02, 0x80, 0x9e, 0x67, 0xd8, 0x8b, + 0x30, 0x47, 0xd0, 0x81, 0x6c, 0x0a, 0x30, 0x67, 0xd0, 0x00, 0xef, 0x0c, + 0x63, 0xa0, 0x00, 0x00, 0x04, 0x00, 0x7d, 0xa3, 0x02, 0x00, 0xef, 0x0c, + 0x57, 0xd0, 0x81, 0x64, 0xd5, 0xa5, 0x0a, 0x00, 0x17, 0xd0, 0x81, 0x38, + 0x4e, 0x15, 0xa0, 0x08, 0x59, 0x06, 0x00, 0xd5, 0xa5, 0x01, 0x00, 0xd7, + 0xd5, 0x81, 0x6c, 0x42, 0x00, 0x57, 0xd0, 0x81, 0x64, 0x47, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x8a, 0xee, 0xea, 0x8a, 0xeb, 0x87, 0xa6, 0xab, + 0xcd, 0xef, 0x01, 0x81, 0x30, 0x1a, 0xbf, 0x80, 0x17, 0xd0, 0x81, 0x34, + 0x97, 0xa6, 0x00, 0x00, 0x00, 0x01, 0x81, 0x64, 0x57, 0xd0, 0x81, 0x38, + 0xea, 0xbf, 0x92, 0xdf, 0x08, 0xce, 0x98, 0x40, 0x07, 0x07, 0xa7, 0x02, + 0x29, 0x43, 0x28, 0x00, 0x1a, 0x1e, 0x54, 0x40, 0x06, 0x68, 0xa0, 0x0d, + 0x44, 0xa0, 0x09, 0x1a, 0x18, 0x5f, 0x08, 0x0f, 0x12, 0x1c, 0xe0, 0x02, + 0x0a, 0x06, 0x8f, 0x10, 0xea, 0x79, 0x03, 0xe0, 0x42, 0x05, 0x7c, 0xa3, + 0x20, 0x12, 0x00, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0x02, 0x0f, 0x02, 0x28, + 0x02, 0x80, 0x48, 0x02, 0x80, 0x66, 0x02, 0x80, 0x5b, 0x12, 0x00, 0x67, + 0xd8, 0xb6, 0x2b, 0xa7, 0xd0, 0x82, 0x62, 0x17, 0xa0, 0x00, 0x00, 0x00, + 0x0d, 0x0e, 0x03, 0x00, 0x5f, 0xd0, 0x81, 0x5c, 0x5f, 0xd0, 0x81, 0x60, + 0x12, 0x00, 0x97, 0xa6, 0x65, 0x76, 0x61, 0x44, 0x80, 0x90, 0x5c, 0xd0, + 0x80, 0x88, 0x97, 0xa6, 0x00, 0x00, 0x01, 0x00, 0x81, 0x1c, 0x5f, 0xd0, + 0x81, 0x20, 0xdf, 0xd0, 0x81, 0x4c, 0xdf, 0xd0, 0x81, 0x48, 0x12, 0x00, + 0xa7, 0xde, 0xb5, 0xc2, 0x80, 0xdc, 0x67, 0xd8, 0xb5, 0x90, 0xa7, 0xd0, + 0x82, 0x96, 0x17, 0xa0, 0x00, 0x00, 0x00, 0x0b, 0x0e, 0x03, 0x00, 0x12, + 0x00, 0x27, 0xd0, 0x82, 0x96, 0x6f, 0x07, 0x12, 0x00, 0x67, 0xd8, 0xb6, + 0x01, 0xa7, 0xd0, 0x82, 0xc2, 0x17, 0xa0, 0x00, 0x00, 0x00, 0x08, 0x0e, + 0x03, 0x00, 0x12, 0x00, 0xdc, 0x0e, 0x5c, 0x10, 0xdc, 0x1f, 0xe2, 0x06, + 0xce, 0x98, 0x16, 0x81, 0x3c, 0x12, 0x00, 0x1f, 0xd8, 0xb5, 0x41, 0x0a, + 0x1c, 0x27, 0xd8, 0xb5, 0x2b, 0x03, 0xd8, 0xb5, 0x37, 0x02, 0xbf, 0x2e, + 0x97, 0xa6, 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, 0x97, 0x06, 0x81, 0x34, + 0x8a, 0xbe, 0xae, 0xa7, 0xde, 0x89, 0xe6, 0x81, 0x34, 0x27, 0xd8, 0x89, + 0xe0, 0x5f, 0x08, 0xea, 0xbe, 0x9f, 0x17, 0xb8, 0x57, 0xb8, 0xe2, 0x21, + 0x74, 0xa5, 0x07, 0x7c, 0x8a, 0x0b, 0x74, 0xa5, 0x07, 0x70, 0x8a, 0x0b, + 0xea, 0x88, 0xcb, 0x02, 0x81, 0x32, 0xea, 0x84, 0x88, 0x7c, 0xa5, 0x0c, + 0x62, 0x07, 0x74, 0xa5, 0x07, 0x70, 0x9a, 0x7c, 0x14, 0xa8, 0x72, 0x04, + 0x05, 0x00, 0xda, 0x16, 0x34, 0xa0, 0x06, 0x3c, 0xd4, 0x80, 0x88, 0x3f, + 0xcc, 0x10, 0x57, 0xa6, 0x00, 0x00, 0x00, 0xfd, 0x14, 0xea, 0x80, 0xa1, + 0x74, 0xa5, 0x07, 0x70, 0x8a, 0x0d, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x76, + 0x02, 0x80, 0xf9, 0xea, 0x71, 0xce, 0x58, 0xae, 0x72, 0x0c, 0x74, 0xa5, + 0x07, 0x70, 0x8a, 0x0d, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x76, 0x02, 0x80, + 0xe3, 0xea, 0x71, 0xce, 0x58, 0xae, 0x72, 0x10, 0x74, 0xa5, 0x07, 0x70, + 0x8a, 0x0d, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x76, 0x02, 0x80, 0xcd, 0xea, + 0x71, 0xce, 0x18, 0xa8, 0x72, 0x57, 0x06, 0x14, 0x04, 0x05, 0x06, 0x4a, + 0x80, 0x4f, 0x7d, 0xef, 0xd8, 0x04, 0x12, 0x00, 0x1b, 0x00, 0x24, 0x00, + 0x2c, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x44, 0x00, 0x72, 0xe0, 0x7f, 0xd0, + 0x82, 0x62, 0xea, 0x80, 0x4b, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x66, 0xea, + 0x80, 0x42, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x6a, 0xea, 0x39, 0x72, 0xe0, + 0x7f, 0xd0, 0x82, 0x6e, 0xea, 0x31, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x72, + 0xea, 0x29, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x76, 0xea, 0x21, 0x72, 0xe0, + 0x7f, 0xd0, 0x82, 0x7a, 0xea, 0x19, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x82, + 0xea, 0x11, 0x72, 0xe0, 0xb4, 0xa6, 0x00, 0x81, 0x60, 0x9a, 0x08, 0x7f, + 0xd0, 0x82, 0x8e, 0xea, 0x02, 0x7c, 0xa5, 0xf4, 0xea, 0x83, 0xae, 0x32, + 0x00, 0x82, 0x0f, 0x1e, 0x7d, 0xa3, 0x08, 0x00, 0x54, 0xa0, 0xda, 0x5c, + 0x10, 0x5c, 0x18, 0xe2, 0x06, 0xe2, 0x15, 0x1b, 0x0a, 0x0d, 0x3c, 0x3c, + 0x3c, 0x20, 0x55, 0x6e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x54, + 0xc0, 0x0c, 0x02, 0xbb, 0x24, 0xe2, 0x15, 0x03, 0x20, 0x3a, 0x20, 0x67, + 0xc0, 0x62, 0xa7, 0xa8, 0x1e, 0xe2, 0x1f, 0xe2, 0x02, 0xe2, 0x15, 0x05, + 0x3e, 0x3e, 0x3e, 0x0a, 0x0d, 0x92, 0xf0, 0x32, 0x00, 0x62, 0x07, 0x2f, + 0xad, 0x80, 0xd0, 0x95, 0xa6, 0x13, 0xe3, 0x82, 0x9c, 0xce, 0x18, 0xa8, + 0x7e, 0x94, 0x06, 0x80, 0xe0, 0x04, 0x05, 0x00, 0xca, 0x81, 0x65, 0x87, + 0xa6, 0x65, 0x76, 0x61, 0x44, 0x80, 0x90, 0x0a, 0x80, 0x49, 0x97, 0x3e, + 0x80, 0xb0, 0x97, 0x36, 0x80, 0xac, 0x97, 0x2e, 0x80, 0xa8, 0x97, 0x26, + 0x80, 0xa4, 0x97, 0x1e, 0x80, 0xa0, 0x97, 0xce, 0x00, 0x80, 0x9c, 0x97, + 0xce, 0x04, 0x80, 0x98, 0x97, 0xce, 0x08, 0x80, 0x94, 0x97, 0xce, 0x10, + 0x80, 0xc0, 0x97, 0xce, 0x14, 0x80, 0xc4, 0x2f, 0xd4, 0x80, 0xbc, 0xa7, + 0xce, 0x14, 0x80, 0xb4, 0x7d, 0xa3, 0x02, 0x00, 0xaf, 0xd4, 0x80, 0xb8, + 0x7d, 0xa1, 0x02, 0x00, 0x2f, 0xd7, 0x80, 0xc8, 0x74, 0xa5, 0x07, 0x7c, + 0x9a, 0x7c, 0x94, 0xae, 0x7e, 0x80, 0xe4, 0x9c, 0x02, 0x0a, 0x81, 0x00, + 0x5c, 0x0a, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x7c, 0xd4, 0xad, 0x7e, 0xcc, + 0x0f, 0x77, 0x57, 0xbd, 0x80, 0xd0, 0x97, 0xae, 0x80, 0xd0, 0x81, 0x70, + 0x95, 0xee, 0xd8, 0x81, 0x55, 0x82, 0x9c, 0x9c, 0xd0, 0x81, 0x4c, 0x0a, + 0x07, 0x34, 0xa0, 0x00, 0x8a, 0x32, 0x04, 0x05, 0x06, 0xda, 0x80, 0x72, + 0x04, 0x05, 0x04, 0x1a, 0x1b, 0x97, 0xa6, 0x64, 0x61, 0x6f, 0x4c, 0x81, + 0x40, 0x84, 0xa6, 0x01, 0x81, 0x18, 0x1a, 0x0c, 0x97, 0xd6, 0x81, 0x70, + 0x81, 0x10, 0x5c, 0xd0, 0x81, 0x18, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x7c, + 0x14, 0xa8, 0x7e, 0xea, 0x80, 0xa6, 0xdf, 0xd0, 0x81, 0x50, 0x9c, 0x00, + 0x0a, 0x2d, 0x9c, 0x01, 0x0a, 0x32, 0x14, 0xa0, 0x80, 0x1c, 0xa8, 0x7c, + 0xca, 0x7d, 0x1c, 0xa8, 0x7e, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x94, 0xae, + 0x7a, 0x81, 0x44, 0x0f, 0x09, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x94, 0xae, + 0x7a, 0x81, 0x44, 0xcc, 0x07, 0x6a, 0xea, 0x80, 0x73, 0x95, 0xa6, 0x0e, + 0x6d, 0x82, 0x9c, 0xea, 0xbf, 0x97, 0x95, 0xa6, 0x0e, 0x74, 0x82, 0x9c, + 0xea, 0xbf, 0x8e, 0x57, 0xa8, 0x80, 0xd0, 0x14, 0xa0, 0x80, 0x1c, 0xd3, + 0x80, 0xe0, 0x0a, 0x06, 0x1a, 0x30, 0x00, 0x00, 0x1c, 0xa8, 0x7c, 0xca, + 0x7d, 0x1c, 0xa8, 0x7e, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0x4d, 0x00, + 0x7a, 0x0f, 0x09, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0x4d, 0x7f, 0x7a, + 0xcc, 0x07, 0x6c, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0x05, 0x7a, 0xea, + 0x26, 0x00, 0x00, 0x00, 0x1c, 0xa8, 0x7c, 0xca, 0x7d, 0x1c, 0xa8, 0x7e, + 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0xaa, 0x7a, 0x00, 0x0f, 0x09, 0x1c, + 0xa8, 0x78, 0xca, 0x7d, 0x54, 0xaa, 0x7a, 0x7f, 0xcc, 0x07, 0x6c, 0xea, + 0x02, 0x72, 0xe0, 0x12, 0x00, 0xdf, 0xd7, 0x00, 0x7d, 0xa3, 0x08, 0x00, + 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xa8, 0x76, 0x67, 0xd0, 0x08, + 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x94, 0xae, 0x76, 0x00, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xaa, 0x76, 0x00, 0x8f, 0x08, 0x1c, 0x48, + 0x7f, 0x1a, 0x71, 0x8f, 0x0f, 0xa7, 0xd0, 0x08, 0x63, 0x10, 0x97, 0x0e, + 0x04, 0x1f, 0xd0, 0x81, 0x20, 0x0a, 0x19, 0x72, 0xe0, 0xef, 0xd4, 0x81, + 0x24, 0xad, 0xbe, 0xd9, 0xa5, 0x08, 0x00, 0xad, 0xbf, 0xd7, 0xd5, 0x81, + 0x20, 0x5f, 0xd0, 0x81, 0x20, 0x52, 0x72, 0xe0, 0xe7, 0xad, 0x80, 0xfe, + 0x5f, 0xb8, 0xd7, 0xd5, 0x00, 0x7f, 0xd0, 0x82, 0x7e, 0xea, 0xbd, 0xc8, + 0x72, 0xe0, 0xea, 0x81, 0x74, 0x3d, 0x0e, 0x47, 0x0e, 0x51, 0x0e, 0x5f, + 0x0e, 0xe3, 0x13, 0xe3, 0x13, 0xe3, 0x13, 0xe3, 0x13, 0x54, 0xd5, 0x00, + 0x7a, 0x8f, 0xa8, 0x80, 0xd0, 0x42, 0x00, 0x94, 0xae, 0x7a, 0x00, 0x8f, + 0xa8, 0x80, 0xd0, 0x42, 0x00, 0x54, 0xd5, 0x00, 0x7a, 0x54, 0xd5, 0x01, + 0x7a, 0x0f, 0xa9, 0x80, 0xd0, 0x42, 0x00, 0x94, 0xae, 0x7a, 0x00, 0x94, + 0xae, 0x7a, 0x01, 0x0f, 0xa9, 0x80, 0xd0, 0x42, 0x00, 0x94, 0xae, 0x7a, + 0x81, 0x44, 0x42, 0x00, 0x94, 0xae, 0x7a, 0x81, 0x44, 0x94, 0xae, 0x7a, + 0x81, 0x44, 0x42, 0x00, 0xd7, 0x05, 0x0f, 0xc9, 0x04, 0x74, 0xa6, 0x08, + 0x0a, 0x8a, 0x09, 0xce, 0x18, 0x88, 0x04, 0x7f, 0xea, 0x1a, 0xae, 0x9c, + 0x8e, 0x04, 0x7f, 0x81, 0x14, 0xce, 0x18, 0xd0, 0x81, 0x14, 0xea, 0x0c, + 0xd7, 0x05, 0x0f, 0xc9, 0x04, 0xce, 0x18, 0x88, 0x04, 0x7f, 0xb7, 0x06, + 0x82, 0xc2, 0x9a, 0x85, 0x75, 0x9c, 0x07, 0x3c, 0xb8, 0x00, 0xb8, 0x48, + 0xa6, 0x20, 0x0a, 0x7d, 0xef, 0xd8, 0x04, 0x78, 0x00, 0x0f, 0x01, 0x53, + 0x01, 0x2f, 0x03, 0x5b, 0x03, 0x74, 0x03, 0xa8, 0x03, 0xcf, 0x03, 0xe0, + 0x03, 0x68, 0x05, 0xae, 0x04, 0xc3, 0x04, 0xdc, 0x04, 0xed, 0x04, 0xfe, + 0x04, 0x0f, 0x05, 0x68, 0x05, 0x7c, 0x01, 0x68, 0x05, 0x68, 0x05, 0xb8, + 0x02, 0x1d, 0x01, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x32, 0x02, 0x93, 0x02, 0x3e, + 0x01, 0x48, 0x01, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x26, 0x03, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x33, + 0x01, 0x14, 0x02, 0x73, 0x01, 0x0a, 0x01, 0x1c, 0x03, 0xc7, 0x02, 0xfb, + 0x01, 0x95, 0x01, 0xce, 0x18, 0xc8, 0x00, 0x9c, 0x07, 0x3c, 0xb8, 0x00, + 0xb8, 0x1f, 0x00, 0x0a, 0x84, 0xe4, 0xea, 0xbf, 0x68, 0x1c, 0xd0, 0x81, + 0x5c, 0x1a, 0x04, 0x42, 0x00, 0xb4, 0xa6, 0x00, 0x81, 0x5c, 0x8a, 0x80, + 0x4c, 0xb4, 0xa6, 0x02, 0x81, 0x5c, 0x8a, 0x23, 0x74, 0xa6, 0x05, 0x06, + 0x8a, 0x04, 0x42, 0x00, 0xe7, 0xad, 0x80, 0xfb, 0xd7, 0xa5, 0x00, 0x00, + 0x00, 0x00, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xd0, 0x82, 0x8a, + 0x7c, 0xa5, 0xf4, 0x42, 0x00, 0x9c, 0xd0, 0x81, 0x68, 0x0a, 0x3e, 0xe7, + 0xad, 0x80, 0xfc, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x2c, 0x7f, 0xd0, 0x82, 0x86, 0x7c, 0xa5, 0xf4, + 0x42, 0x00, 0x74, 0xa6, 0x08, 0x06, 0x8a, 0x04, 0x42, 0x00, 0xe7, 0xad, + 0x80, 0xfa, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xd0, 0x82, 0x92, 0x7c, 0xa5, 0xf4, 0x42, 0x00, 0x5c, + 0xd0, 0x81, 0x68, 0x42, 0x00, 0x17, 0xb8, 0xea, 0xbf, 0x7e, 0x74, 0xa5, + 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x0d, 0x72, 0x17, 0xb8, 0xea, 0xbf, 0x70, + 0xd7, 0x0d, 0xd7, 0x15, 0x57, 0xc8, 0x0c, 0xce, 0x98, 0x48, 0x00, 0x8f, + 0x08, 0x17, 0x08, 0x03, 0x10, 0x57, 0x06, 0x0c, 0xea, 0x26, 0x95, 0xa6, + 0x0e, 0x80, 0x82, 0xac, 0x17, 0xb8, 0xea, 0xbf, 0x4f, 0x49, 0xa6, 0x01, + 0x00, 0x0a, 0x17, 0xb8, 0xea, 0xbf, 0x45, 0x17, 0xb8, 0x57, 0x06, 0x00, + 0x55, 0x0e, 0x04, 0xea, 0x83, 0xe0, 0xd7, 0x0d, 0xd7, 0x15, 0x1f, 0x10, + 0x0a, 0x11, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x4d, 0x00, 0x72, + 0x8f, 0x08, 0xcf, 0x17, 0x74, 0x97, 0xb8, 0x57, 0xb8, 0x17, 0xb8, 0xea, + 0xbf, 0x1a, 0x57, 0xd0, 0x81, 0x1c, 0x17, 0xb8, 0xea, 0xbf, 0x11, 0xd4, + 0xa1, 0x09, 0x67, 0xa8, 0x0d, 0x94, 0x38, 0x5f, 0x18, 0xe2, 0x06, 0x8c, + 0x3f, 0x1c, 0x38, 0xda, 0x73, 0x5f, 0xd1, 0x81, 0x64, 0xea, 0xba, 0x82, + 0x04, 0x0d, 0xfa, 0xaa, 0x80, 0x4a, 0x04, 0x0d, 0xff, 0x0a, 0x80, 0x44, + 0x04, 0x0d, 0xfc, 0x7a, 0x1e, 0xce, 0x18, 0x08, 0x23, 0xa0, 0x00, 0x00, + 0x00, 0xfd, 0xb4, 0xa0, 0x00, 0x8a, 0x09, 0x4e, 0x8b, 0x06, 0x81, 0x60, + 0xea, 0x3b, 0x4e, 0x9b, 0x06, 0x81, 0x60, 0xea, 0x34, 0xce, 0x18, 0x08, + 0x23, 0xa0, 0x00, 0x00, 0x00, 0xfa, 0xb4, 0xa0, 0x00, 0x8a, 0x0d, 0x4e, + 0x8b, 0x06, 0x81, 0x5c, 0xdc, 0xd0, 0x81, 0x68, 0xea, 0x1b, 0x4e, 0x9b, + 0x06, 0x81, 0x5c, 0xea, 0x14, 0xa7, 0xde, 0xb0, 0x31, 0x81, 0x58, 0x02, + 0xb1, 0x25, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbe, 0x99, 0x3f, + 0x14, 0x17, 0xb8, 0xea, 0xbe, 0x92, 0x74, 0xa0, 0x00, 0xce, 0x58, 0xd0, + 0x81, 0x48, 0x9a, 0x08, 0xdc, 0xd0, 0x81, 0x48, 0xea, 0x06, 0x5c, 0xd0, + 0x81, 0x48, 0x17, 0xb8, 0xea, 0xbe, 0x79, 0x1f, 0x08, 0x0a, 0x13, 0x97, + 0xa6, 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, 0x97, 0x0e, 0x81, 0x34, 0x17, + 0xb8, 0xea, 0xbe, 0x64, 0x5f, 0xd2, 0x81, 0x64, 0xdf, 0x09, 0xea, 0xb9, + 0xe5, 0xd7, 0x0d, 0xce, 0x58, 0x08, 0x04, 0x0d, 0x06, 0x4a, 0x15, 0x17, + 0xf0, 0xd1, 0x82, 0x62, 0x97, 0x17, 0xd1, 0x82, 0x62, 0x97, 0x00, 0x57, + 0xb8, 0x17, 0xb8, 0xea, 0xbe, 0x3e, 0x1c, 0x0d, 0x0a, 0x3c, 0x9c, 0x0d, + 0x0a, 0x2c, 0x1c, 0x0e, 0x0a, 0x22, 0x9c, 0x0e, 0x0a, 0x2a, 0x1c, 0x0f, + 0x0a, 0x11, 0x9c, 0x0f, 0x0a, 0x11, 0x57, 0xb8, 0x58, 0xa6, 0x20, 0x0a, + 0x17, 0xb8, 0xea, 0xbe, 0x1b, 0xdf, 0x0b, 0xea, 0x48, 0x67, 0xa8, 0x08, + 0xea, 0x43, 0x67, 0xa8, 0x09, 0xea, 0xbf, 0xbe, 0x67, 0xa8, 0x0a, 0xea, + 0xbf, 0xb8, 0x67, 0xa8, 0x0b, 0xea, 0xbf, 0xb2, 0x67, 0xa8, 0x0c, 0xea, + 0xbf, 0xac, 0xd7, 0x0d, 0x87, 0xd0, 0x04, 0x6a, 0x05, 0x97, 0xd0, 0x04, + 0xd7, 0x15, 0x17, 0x10, 0x97, 0x08, 0x67, 0xd0, 0x08, 0x0e, 0x00, 0x00, + 0x5f, 0xd0, 0x04, 0x97, 0xb8, 0x57, 0xb8, 0x17, 0xb8, 0xd7, 0xd0, 0x00, + 0xea, 0xbd, 0xd5, 0x9c, 0xd0, 0x80, 0x88, 0x1a, 0x06, 0x58, 0xa6, 0x20, + 0x0a, 0x17, 0xb8, 0xea, 0xbd, 0xc6, 0x74, 0xa6, 0x08, 0x0a, 0x8a, 0x27, + 0x44, 0x00, 0x0a, 0x2e, 0xce, 0x58, 0x08, 0xf7, 0x0e, 0xaf, 0x1f, 0x9a, + 0x30, 0xb4, 0xa0, 0x00, 0x8a, 0x09, 0x4e, 0x8b, 0x0e, 0x82, 0xc2, 0xea, + 0x07, 0x4e, 0x9b, 0x0e, 0x82, 0xc2, 0x3f, 0x0c, 0x17, 0xb8, 0xea, 0xbd, + 0x9b, 0xa7, 0xde, 0xaf, 0x49, 0x81, 0x58, 0x02, 0xb0, 0x15, 0xea, 0x18, + 0xa7, 0xde, 0xaf, 0x5e, 0x81, 0x58, 0x02, 0xb0, 0x0a, 0xea, 0x0d, 0xa7, + 0xde, 0xaf, 0x81, 0x81, 0x58, 0x02, 0xaf, 0xff, 0xea, 0x02, 0x58, 0xa6, + 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbd, 0x71, 0xce, 0x58, 0xd0, 0x80, 0xd8, + 0x17, 0xb8, 0xea, 0xbd, 0x67, 0x97, 0x0e, 0x80, 0xdc, 0x17, 0xb8, 0xea, + 0xbd, 0x5e, 0x44, 0xa0, 0x0d, 0x0a, 0x10, 0x74, 0xa5, 0x06, 0x70, 0x9a, + 0x7c, 0x54, 0x0d, 0x72, 0x17, 0xb8, 0xea, 0xbd, 0x4b, 0x74, 0xa5, 0x06, + 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x72, 0x74, 0xa5, 0x06, 0x70, 0x9a, + 0x7c, 0x54, 0xa5, 0x0d, 0x72, 0x17, 0xb8, 0xea, 0xbd, 0x32, 0x74, 0xa5, + 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x72, 0x74, 0xa5, 0x06, 0x70, + 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x72, 0x17, 0xb8, 0xea, 0xbd, 0x19, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x76, 0x74, 0xa5, 0x07, + 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0xce, 0x58, 0xa8, 0x76, 0x34, 0xa0, 0x07, 0x9a, 0x0f, 0xa7, 0xde, 0xaf, + 0x52, 0x81, 0x58, 0x02, 0xaf, 0x71, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, + 0xea, 0xbc, 0xe5, 0x02, 0xaf, 0xb3, 0x9a, 0x09, 0x57, 0xd0, 0x00, 0x58, + 0xa6, 0x20, 0x0a, 0xb4, 0xa6, 0x00, 0x81, 0x54, 0x8a, 0x0c, 0x4e, 0x48, + 0xa6, 0x00, 0x0a, 0x17, 0xb8, 0xea, 0xbc, 0xc8, 0x4e, 0x58, 0xa6, 0x00, + 0x0a, 0x17, 0xb8, 0xea, 0xbc, 0xbe, 0x02, 0xb0, 0x77, 0x9a, 0x09, 0x58, + 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbc, 0xad, 0x5f, + 0xd0, 0x81, 0x50, 0xdf, 0xd0, 0x81, 0x18, 0x97, 0xd6, 0x81, 0x48, 0x81, + 0x4c, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x02, 0x76, 0xaf, + 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0xa6, 0x81, 0x20, 0x1f, 0x10, 0x0a, + 0x19, 0x14, 0x48, 0x00, 0x04, 0xa0, 0x0d, 0x0a, 0x11, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x8f, 0x08, 0x8f, 0x17, 0xea, 0x67, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x76, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0xdf, 0xd0, 0x81, 0x4c, 0x9c, + 0xd0, 0x81, 0x50, 0x0a, 0x80, 0x58, 0x04, 0xa0, 0x80, 0x0a, 0x07, 0x17, + 0xb8, 0xea, 0xbc, 0x48, 0x17, 0xd0, 0x81, 0x10, 0x02, 0xb7, 0x07, 0x9a, + 0x32, 0x1f, 0x08, 0x0a, 0x1b, 0x95, 0xce, 0x0a, 0x81, 0x28, 0x17, 0xb8, + 0x7c, 0xa5, 0xf8, 0xd5, 0xd5, 0x81, 0x28, 0xd5, 0xa5, 0x01, 0x00, 0xd7, + 0xd5, 0x81, 0x70, 0xea, 0xbc, 0x22, 0x97, 0xa6, 0xab, 0xcd, 0xef, 0x01, + 0x81, 0x30, 0x97, 0x06, 0x81, 0x34, 0xdf, 0xd1, 0x81, 0x64, 0xea, 0xb6, + 0x64, 0xa7, 0xde, 0xae, 0x56, 0x81, 0x58, 0x02, 0xae, 0x89, 0x58, 0xa6, + 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbb, 0xfd, 0xa7, 0xde, 0xae, 0x21, 0x81, + 0x58, 0x02, 0xae, 0x77, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbb, + 0xeb, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, + 0xdf, 0xd7, 0x15, 0x02, 0xb2, 0x1d, 0x97, 0xb8, 0x9a, 0x09, 0x58, 0xa6, + 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0xca, 0xd7, 0x15, + 0xd7, 0x1d, 0x02, 0xb1, 0x17, 0xd7, 0xb8, 0x97, 0xb8, 0x9a, 0x09, 0x58, + 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0xb1, 0x02, + 0xb1, 0x8e, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, + 0xb8, 0xea, 0xbb, 0xa0, 0x02, 0xb0, 0xaa, 0x9a, 0x09, 0x58, 0xa6, 0x20, + 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0x8f, 0x02, 0xb0, 0x5b, + 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, + 0xbb, 0x7e, 0x02, 0xb2, 0x6f, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, + 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0x6d, 0xd7, 0x05, 0x27, 0xa8, 0x00, + 0xea, 0x80, 0x49, 0xd7, 0x05, 0x27, 0xa8, 0x04, 0xea, 0x80, 0x41, 0xd7, + 0x05, 0x27, 0xa8, 0x08, 0xea, 0x39, 0xd7, 0x05, 0x27, 0xa8, 0x0c, 0xea, + 0x32, 0xd7, 0x05, 0x27, 0xa8, 0x10, 0xea, 0x2b, 0xd7, 0x05, 0x27, 0xa8, + 0x18, 0xea, 0x24, 0xd7, 0x05, 0x27, 0xa8, 0x1c, 0xea, 0x1d, 0xd7, 0x05, + 0x27, 0xa8, 0x20, 0xea, 0x16, 0xd7, 0x05, 0x27, 0xa8, 0x24, 0xea, 0x0f, + 0xd7, 0x05, 0x27, 0xa8, 0x28, 0xea, 0x08, 0x0f, 0xcf, 0x04, 0x27, 0xa8, + 0x14, 0x03, 0xd0, 0x80, 0xdc, 0xce, 0xd9, 0x45, 0x00, 0xce, 0xd9, 0x45, + 0x02, 0xc3, 0x8d, 0x04, 0x08, 0x14, 0xc8, 0x12, 0x08, 0xa0, 0x02, 0x6c, + 0x00, 0x17, 0xc8, 0x08, 0x32, 0x04, 0xd7, 0xa5, 0x49, 0x56, 0x4e, 0x03, + 0xea, 0x80, 0x55, 0xd7, 0xa5, 0x49, 0x4d, 0x4e, 0x03, 0xea, 0x80, 0x4c, + 0xd7, 0xa5, 0x54, 0x42, 0x41, 0x03, 0xea, 0x80, 0x43, 0xd7, 0xa5, 0x55, + 0x50, 0x46, 0x03, 0xea, 0x3a, 0xd7, 0xa5, 0x4c, 0x4c, 0x49, 0x03, 0xea, + 0x32, 0xd7, 0xa5, 0x43, 0x56, 0x53, 0x03, 0xea, 0x2a, 0xd7, 0xa5, 0x5a, + 0x56, 0x44, 0x03, 0xea, 0x22, 0xd7, 0xa5, 0x47, 0x4c, 0x46, 0x03, 0xea, + 0x1a, 0xd7, 0xa5, 0x54, 0x50, 0x42, 0x03, 0xea, 0x12, 0xd7, 0xa5, 0x43, + 0x52, 0x54, 0x03, 0xea, 0x0a, 0xd7, 0xa5, 0x44, 0x4e, 0x55, 0x03, 0xea, + 0x02, 0x02, 0xb2, 0x65, 0x0d, 0x0a, 0x0a, 0x2a, 0x2a, 0x2a, 0x20, 0x45, + 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x00, 0x67, + 0xb8, 0x02, 0xb2, 0x16, 0x02, 0xb2, 0x4a, 0x29, 0x20, 0x61, 0x74, 0x20, + 0x50, 0x43, 0x20, 0x3d, 0x20, 0x00, 0x17, 0xc8, 0x04, 0x02, 0xb2, 0x85, + 0x02, 0xb2, 0x52, 0xea, 0x00, 0xed, 0xa7, 0x00, 0xc0, 0x6f, 0xad, 0x80, + 0xc0, 0x2f, 0x0d, 0xef, 0x0c, 0xe2, 0x15, 0x01, 0x2a, 0x5f, 0x08, 0xa7, + 0xd0, 0x81, 0x08, 0xa7, 0xd2, 0x81, 0x74, 0x00, 0x94, 0xa2, 0xea, 0x04, + 0x94, 0xa2, 0x20, 0x05, 0x94, 0xa2, 0x7f, 0x06, 0xe2, 0x07, 0x8a, 0x12, + 0x7d, 0xa3, 0x02, 0x00, 0xef, 0xd4, 0x80, 0xd4, 0x7d, 0xa1, 0x02, 0x00, + 0x02, 0x20, 0xea, 0x4f, 0x57, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0xe2, 0x06, + 0x67, 0xd0, 0x81, 0x74, 0xa7, 0xa8, 0x80, 0xea, 0xe2, 0x1f, 0xe2, 0x02, + 0xe2, 0x15, 0x02, 0x0a, 0x0d, 0xea, 0xbf, 0xb8, 0x67, 0xd0, 0x81, 0x74, + 0x97, 0x08, 0x7d, 0xa3, 0x08, 0x00, 0x84, 0xa2, 0x0d, 0x00, 0x0a, 0x06, + 0x8f, 0x10, 0xea, 0x78, 0xa3, 0x08, 0x8f, 0x10, 0xd7, 0x11, 0x97, 0x09, + 0x02, 0x80, 0xa1, 0x8a, 0x80, 0x83, 0xc7, 0xa0, 0x00, 0x00, 0x00, 0x02, + 0x1a, 0x22, 0x85, 0xa2, 0x53, 0x47, 0x00, 0x0a, 0x80, 0x82, 0x85, 0xa2, + 0x55, 0x47, 0x00, 0x0a, 0x80, 0x6d, 0x85, 0xa2, 0x73, 0x67, 0x00, 0x0a, + 0x80, 0x72, 0x85, 0xa2, 0x75, 0x67, 0x00, 0x0a, 0x80, 0x5d, 0x57, 0x30, + 0x97, 0x38, 0x7d, 0xa3, 0x03, 0x00, 0xe2, 0x08, 0x8a, 0x0a, 0xe2, 0x20, + 0x7d, 0xa1, 0x02, 0x00, 0x12, 0x00, 0xe2, 0x20, 0x7d, 0xa1, 0x02, 0x00, + 0x67, 0xd0, 0x08, 0x97, 0xd0, 0x04, 0xe2, 0x02, 0xe2, 0x04, 0x12, 0x00, + 0xd5, 0xa5, 0x0b, 0x00, 0xd5, 0xa5, 0x01, 0x00, 0xd7, 0x05, 0x42, 0x00, + 0xd5, 0xa5, 0x0a, 0x00, 0xd5, 0xa5, 0x01, 0x00, 0xd7, 0x05, 0x42, 0x00, + 0x02, 0xb1, 0x61, 0x0a, 0x0d, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0d, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x57, 0x20, 0x02, 0x17, 0x8a, 0x7a, 0x02, 0x80, + 0x47, 0x8a, 0x5b, 0xea, 0x41, 0x57, 0x20, 0x02, 0x0a, 0x8a, 0x6d, 0x02, + 0x3a, 0x8a, 0x4f, 0xea, 0x41, 0x44, 0xa2, 0x0d, 0x00, 0x0a, 0x2b, 0x44, + 0xa2, 0x20, 0x00, 0x1a, 0x06, 0x8f, 0x08, 0xea, 0x72, 0x17, 0x09, 0x44, + 0xa2, 0x0d, 0x00, 0x0a, 0x0c, 0x44, 0xa2, 0x20, 0x00, 0x0a, 0x06, 0x8f, + 0x08, 0xea, 0x72, 0x97, 0x20, 0x17, 0x09, 0xd7, 0x08, 0xe3, 0x10, 0x7c, + 0xa1, 0x20, 0x12, 0x00, 0x7c, 0xa3, 0x20, 0x12, 0x00, 0x17, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x84, 0xa2, 0x23, 0x00, 0x1a, 0x34, 0x8f, 0x10, 0x8f, + 0x1f, 0x1f, 0x18, 0x0a, 0x80, 0x65, 0xce, 0x58, 0x50, 0x00, 0x44, 0xa0, + 0x30, 0x4a, 0x80, 0x5b, 0x44, 0xa0, 0x39, 0xaa, 0x80, 0x55, 0x63, 0xa0, + 0x00, 0x00, 0x00, 0x30, 0xce, 0x23, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x03, + 0x08, 0x8f, 0x10, 0xcf, 0x1f, 0x5f, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0xce, + 0x58, 0x50, 0x00, 0x44, 0xa0, 0x30, 0x4a, 0x32, 0x44, 0xa0, 0x39, 0xaa, + 0x0a, 0x63, 0xa0, 0x00, 0x00, 0x00, 0x30, 0xea, 0x12, 0x44, 0xa0, 0x41, + 0x4a, 0x20, 0x44, 0xa0, 0x46, 0xaa, 0x1b, 0x63, 0xa0, 0x00, 0x00, 0x00, + 0x37, 0xce, 0x23, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x03, 0x08, 0x8f, 0x10, + 0xcf, 0x1f, 0x4f, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0x7c, 0xa3, 0x20, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0x18, 0x00, + 0x0c, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x77, 0x00, 0x7f, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x63, 0x00, + 0x63, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, + 0x66, 0x00, 0x66, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x6c, 0x00, + 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x6c, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7c, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x06, 0x00, + 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xaa, 0xc0, 0xf0, 0x07, 0x9e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x64, 0x14, 0xd0, 0x00, 0x20, 0x00, + 0x42, 0x00, 0xc0, 0x00, 0x04, 0x0b, 0xd0, 0x00, 0xe3, 0x13, 0xc0, 0x00, + 0xeb, 0x13, 0xc0, 0x00, 0xf2, 0x13, 0xc0, 0x00, 0xf9, 0x13, 0xc0, 0x00, + 0xa0, 0x0e, 0xc0, 0x00, 0x00, 0x14, 0xc0, 0x00, 0x07, 0x14, 0xc0, 0x00, + 0x0e, 0x14, 0xc0, 0x00, 0x15, 0x14, 0xc0, 0x00, 0x1c, 0x14, 0xc0, 0x00, + 0x46, 0x14, 0xc0, 0x00, 0x4f, 0x14, 0xc0, 0x00, 0x58, 0x14, 0xc0, 0x00, + 0x61, 0x14, 0xc0, 0x00, 0x69, 0x14, 0xc0, 0x00, 0x71, 0x14, 0xc0, 0x00, + 0x79, 0x14, 0xc0, 0x00, 0x81, 0x14, 0xc0, 0x00, 0x89, 0x14, 0xc0, 0x00, + 0x91, 0x14, 0xc0, 0x00, 0x99, 0x14, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf5, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, + 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xc0, 0x00, 0xf3, 0x0b, 0xff, 0xfd, + 0xf2, 0xe0, 0x03, 0x01, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x05, 0x01, 0x14, 0x69, 0x6c, 0x6c, + 0x65, 0x67, 0x61, 0x6c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x01, 0x0e, 0x46, 0x69, 0x6c, 0x65, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x01, 0x01, + 0x1d, 0x4f, 0x53, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, + 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x75, 0x73, 0x65, 0x72, 0x02, 0x01, 0x2b, 0x41, 0x74, 0x74, + 0x65, 0x6d, 0x70, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x20, 0x70, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, + 0x20, 0x6f, 0x66, 0x20, 0x4f, 0x53, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x69, + 0x6c, 0x65, 0x67, 0x65, 0x03, 0x01, 0x25, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x20, 0x53, 0x56, 0x43, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x79, 0x20, 0x4f, 0x53, 0x5f, 0x70, + 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x04, 0x01, 0x20, 0x49, + 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, + 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x20, 0x62, 0x79, 0x20, 0x4f, + 0x53, 0x5f, 0x4f, 0x53, 0x43, 0x4c, 0x49, 0x06, 0x01, 0x11, 0x4e, 0x6f, + 0x74, 0x20, 0x61, 0x20, 0x33, 0x32, 0x30, 0x31, 0x36, 0x20, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x1b, 0x01, 0x06, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, + 0xfe, 0x01, 0x0b, 0x45, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0xff, 0x01, 0x0b, 0x4b, 0x65, 0x79, 0x20, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0xd7, 0x05, 0xd7, 0x0d, 0x57, 0xd0, 0x81, 0x58, + 0xce, 0x99, 0x46, 0x00, 0x00, 0xce, 0x18, 0x48, 0x02, 0x97, 0x06, 0x04, + 0xa7, 0xd0, 0x08, 0x8f, 0x09, 0x0e, 0x00, 0x00, 0x57, 0xb8, 0x17, 0xb8, + 0x12, 0x00, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x05, 0x72, 0x12, + 0x00, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x76, 0x74, + 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xa8, 0x76, 0x74, 0xa5, 0x07, 0x74, + 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x74, 0xa0, 0x07, 0x12, 0x00, 0xaf, 0xd4, + 0x81, 0x24, 0xa7, 0xde, 0x80, 0xb7, 0x81, 0x20, 0x44, 0xa0, 0x80, 0x5a, + 0x2d, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x04, 0x76, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, + 0x98, 0xa8, 0x76, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0x7c, 0xa1, 0x20, 0xee, + 0x40, 0xd8, 0x10, 0x8a, 0x1c, 0x7d, 0xef, 0xd8, 0x04, 0x0c, 0x00, 0x10, + 0x00, 0x16, 0x00, 0x84, 0x82, 0x5f, 0x10, 0x12, 0x00, 0x97, 0xd0, 0x80, + 0xd0, 0x12, 0x00, 0x2f, 0x15, 0x12, 0x00, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0xa5, 0x06, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x15, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x1d, 0x76, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x44, 0xa0, 0x9d, 0x1a, + 0x07, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0x14, 0xa8, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x98, 0xa8, + 0x76, 0xd7, 0x10, 0x4e, 0x95, 0xa0, 0x08, 0x74, 0xa5, 0x07, 0x74, 0x9a, + 0x7c, 0x94, 0xa8, 0x76, 0x34, 0xa0, 0x07, 0x3c, 0xd4, 0x81, 0x54, 0x7d, + 0xa1, 0x00, 0x20, 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0x10, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x08, 0x0e, 0x04, 0x01, 0x01, 0x05, + 0x00, 0x10, 0x10, 0x10, 0x0d, 0x00, 0x08, 0x80, 0x10, 0x05, 0x00, 0x05, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x09, 0x05, 0x00, 0x08, 0x10, 0x10, + 0x0d, 0x0d, 0x80, 0x08, 0x80, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, + 0x8d, 0x81, 0x20, 0x44, 0xa0, 0x00, 0x0a, 0x80, 0x8a, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x08, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, + 0x7c, 0x54, 0x0d, 0x76, 0x04, 0x0d, 0x80, 0xaa, 0x0a, 0x0f, 0x11, 0xce, + 0x18, 0x50, 0x7e, 0xea, 0x12, 0x44, 0xa0, 0x14, 0xba, 0x04, 0x5f, 0x08, + 0xce, 0x58, 0x08, 0xce, 0x18, 0xe0, 0xd9, 0xbf, 0x9c, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x1c, 0x00, 0x0a, 0x10, 0x74, 0xa5, + 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xe5, 0x50, 0x7f, 0x76, 0xcc, 0x07, 0x75, + 0x04, 0x0d, 0x80, 0xaa, 0x08, 0xce, 0x18, 0x50, 0x7f, 0xea, 0x08, 0xce, + 0x18, 0xe0, 0xd9, 0xbf, 0x85, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x05, 0x76, 0x1c, 0x00, 0x0a, 0x10, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, + 0x14, 0xaf, 0x50, 0x76, 0x7f, 0xcc, 0x07, 0x75, 0x5f, 0xd0, 0x81, 0x20, + 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x76, 0x74, 0xa5, + 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x55, 0x06, 0x76, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0x55, 0x05, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, + 0x54, 0x55, 0x04, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, + 0x07, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x76, + 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, + 0x20, 0x1c, 0x00, 0x7a, 0x10, 0xa7, 0xde, 0xbd, 0xbe, 0x81, 0x58, 0x02, + 0xbd, 0xdd, 0x7c, 0xa3, 0x20, 0x12, 0x00, 0x17, 0x50, 0x00, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xaa, 0x76, 0x00, 0x8f, 0x00, 0x04, 0xa2, + 0x0d, 0x7f, 0x1a, 0x70, 0xd7, 0x00, 0xe3, 0x50, 0x00, 0x8f, 0x1f, 0x7c, + 0xa1, 0x20, 0x12, 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x34, 0x81, + 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x10, 0x76, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, + 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, + 0x7d, 0xa3, 0x00, 0x20, 0x12, 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, + 0x3d, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0e, + 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, 0x74, + 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x34, 0xa0, 0x07, + 0x9a, 0x09, 0x97, 0xa6, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x12, 0x00, 0x7d, + 0xa3, 0x00, 0x20, 0x12, 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, + 0x82, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x12, + 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x1c, 0x08, + 0x1a, 0x1e, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x74, + 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, + 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0x1f, 0x18, 0x0a, 0x1c, 0x14, 0x50, + 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x11, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x8f, 0x1f, 0x8f, 0x10, 0xea, 0x64, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x76, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x5f, 0xd0, 0x81, 0x20, + 0x1c, 0x08, 0x0a, 0x08, 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0xa7, 0xde, + 0xbb, 0xcf, 0x81, 0x58, 0x02, 0xbc, 0xac, 0x7d, 0xa3, 0x00, 0x20, 0x12, + 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0x59, 0x81, 0x20, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x0c, 0x76, 0x74, 0xa5, 0x06, + 0x74, 0x9a, 0x7c, 0x54, 0x15, 0x76, 0x5f, 0x02, 0x4e, 0xc3, 0xa0, 0x08, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x1d, 0x76, 0xcf, 0x07, 0x73, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x0d, 0x76, 0x74, 0xa5, 0x07, + 0x74, 0x9a, 0x7c, 0x54, 0xa8, 0x76, 0x5f, 0x02, 0x4e, 0xd7, 0xa0, 0x08, + 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xd4, 0xa8, 0x76, 0xcf, 0x07, 0x73, + 0x5f, 0xd0, 0x81, 0x20, 0x7d, 0xa1, 0x00, 0x20, 0x12, 0x00, 0x7d, 0xa3, + 0x00, 0x20, 0x12, 0x00, 0xd7, 0x1d, 0x27, 0xd0, 0x80, 0xe8, 0x17, 0x22, + 0x00, 0x17, 0x2a, 0x04, 0x17, 0x32, 0x08, 0x17, 0x3a, 0x0c, 0xaf, 0xd4, + 0x81, 0x24, 0xa7, 0xde, 0x80, 0x93, 0x81, 0x20, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xa5, 0x14, 0x76, 0xd7, 0xa0, 0x00, 0x00, 0x00, 0x10, + 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xe5, 0x43, 0x7f, 0x76, 0xcf, + 0x1f, 0x75, 0xd7, 0xc8, 0x00, 0x1f, 0x18, 0x0a, 0x19, 0x14, 0x50, 0x00, + 0x04, 0xa0, 0x0d, 0x0a, 0x11, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0x05, 0x76, 0x8f, 0x1f, 0x8f, 0x10, 0xea, 0x67, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x76, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, + 0x54, 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xa8, 0x76, + 0x5f, 0xd0, 0x81, 0x20, 0x6b, 0xa0, 0x00, 0x00, 0x00, 0x7f, 0x27, 0xd0, + 0x80, 0xe8, 0xd7, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x74, 0xa5, 0x07, 0x74, + 0x9a, 0x7c, 0x14, 0xaf, 0x43, 0x76, 0x7f, 0xcf, 0x1f, 0x75, 0x17, 0x41, + 0x00, 0x57, 0x41, 0x04, 0x97, 0x41, 0x08, 0xd7, 0x41, 0x0c, 0xd7, 0xb8, + 0x7c, 0xa1, 0x20, 0x12, 0x00, 0xd7, 0xb8, 0x7d, 0xa3, 0x00, 0x20, 0x12, + 0x00, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0x8d, 0x81, 0x20, 0x74, + 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x16, 0x76, 0x94, 0x0e, 0x80, + 0xe8, 0x67, 0xd0, 0x80, 0xe8, 0x54, 0x12, 0x01, 0x57, 0x1a, 0x02, 0x57, + 0x22, 0x06, 0x57, 0x2a, 0x0a, 0x14, 0xa0, 0x0e, 0x74, 0xa5, 0x06, 0x74, + 0x9a, 0x7c, 0x54, 0xe5, 0x48, 0x7f, 0x76, 0xcc, 0x07, 0x75, 0x14, 0xa0, + 0x0d, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xaf, 0x48, 0x76, 0x00, + 0xcc, 0x07, 0x75, 0x57, 0x49, 0x0a, 0x17, 0x49, 0x06, 0xd7, 0x48, 0x02, + 0xce, 0x98, 0x48, 0x01, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, + 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x04, + 0xd5, 0x80, 0xe8, 0x01, 0xaa, 0x10, 0x04, 0xd5, 0x80, 0xe8, 0x04, 0x4a, + 0x09, 0x1f, 0x20, 0xbc, 0x00, 0x4e, 0x20, 0x00, 0x34, 0xa0, 0x07, 0x5f, + 0xd0, 0x81, 0x20, 0x8a, 0x04, 0x12, 0x00, 0x97, 0xa6, 0x00, 0x00, 0x01, + 0xfe, 0x00, 0x7c, 0xa3, 0x20, 0x12, 0x00, 0x62, 0x07, 0xce, 0x98, 0x48, + 0x00, 0xcf, 0x10, 0x0b, 0x8f, 0x08, 0x14, 0x48, 0x00, 0x02, 0xbb, 0x0d, + 0xcf, 0x17, 0x78, 0x72, 0xe0, 0x12, 0x00, 0xd5, 0x05, 0x14, 0x48, 0x00, + 0x1c, 0x00, 0x0a, 0x14, 0x02, 0xba, 0xfa, 0x04, 0xa0, 0x0d, 0x1a, 0x08, + 0x14, 0xa0, 0x0a, 0x02, 0xba, 0xef, 0x8f, 0x08, 0xea, 0x69, 0x15, 0xb8, + 0x12, 0x00, 0xd7, 0x0d, 0x57, 0xc8, 0x04, 0x02, 0x5c, 0x67, 0x4e, 0x01, + 0x04, 0x57, 0xb8, 0x12, 0x00, 0xd7, 0x0d, 0x57, 0xc8, 0x04, 0x02, 0x4d, + 0x67, 0x4e, 0x01, 0x04, 0x57, 0xb8, 0x02, 0x64, 0x0d, 0x00, 0x12, 0x00, + 0x62, 0x03, 0xce, 0x58, 0xa0, 0x20, 0x0f, 0x0e, 0x2e, 0x08, 0xc8, 0x04, + 0x04, 0x00, 0xa0, 0x30, 0x04, 0x05, 0x39, 0x7a, 0x04, 0x8c, 0x03, 0x02, + 0xba, 0xab, 0x1f, 0x08, 0x1a, 0x6a, 0x72, 0xc0, 0x12, 0x00, 0x62, 0x03, + 0xce, 0x58, 0xa0, 0x08, 0xea, 0x5e, 0x62, 0x03, 0xce, 0x58, 0xa0, 0x18, + 0xea, 0x56, 0x82, 0x02, 0x0c, 0x67, 0xc0, 0x74, 0x02, 0x09, 0x02, 0xbf, + 0x6d, 0x92, 0x40, 0x12, 0x00, 0x62, 0x17, 0x27, 0xa9, 0x0a, 0xd4, 0x25, + 0x1f, 0x00, 0x97, 0x00, 0xce, 0x33, 0x20, 0xce, 0xb7, 0x20, 0x4e, 0xf0, + 0x15, 0xc0, 0xa5, 0x30, 0x4f, 0x00, 0x72, 0x7a, 0x05, 0xd4, 0xa5, 0x2d, + 0xa7, 0x48, 0x01, 0x67, 0xb8, 0xdf, 0x07, 0x0e, 0x00, 0x06, 0x7f, 0x05, + 0x72, 0x68, 0x4e, 0x74, 0x02, 0x00, 0x17, 0xb8, 0x12, 0x00, 0x5c, 0xa8, + 0xc0, 0xf9, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x67, 0xad, 0xc0, 0xf0, 0x00, + 0x00, 0x80, 0xd8, 0xef, 0xa4, 0x00, 0x00, 0x01, 0x00, 0x27, 0xd8, 0xb8, + 0x63, 0x6f, 0x07, 0x17, 0xa0, 0x00, 0x02, 0x00, 0x00, 0x57, 0x00, 0x4e, + 0x48, 0xa0, 0x11, 0x8a, 0x04, 0x5f, 0x08, 0x97, 0x40, 0x00, 0xd7, 0x48, + 0x00, 0x17, 0xa2, 0x55, 0x55, 0xaa, 0xaa, 0x00, 0x57, 0xa2, 0xaa, 0xaa, + 0x55, 0x55, 0x00, 0x07, 0x45, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x1a, 0x3a, + 0x07, 0x4d, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0x1a, 0x31, 0x17, 0xa2, 0xaa, + 0xaa, 0x55, 0x55, 0x00, 0x57, 0xa2, 0x55, 0x55, 0xaa, 0xaa, 0x00, 0x07, + 0x45, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0x1a, 0x1a, 0x07, 0x4d, 0x00, 0x55, + 0x55, 0xaa, 0xaa, 0x1a, 0x11, 0x17, 0x12, 0x00, 0x57, 0x1a, 0x00, 0x03, + 0xa0, 0x00, 0x02, 0x00, 0x00, 0xea, 0xbf, 0xa4, 0x17, 0x12, 0x00, 0x57, + 0x1a, 0x00, 0x57, 0x00, 0x63, 0xa0, 0x00, 0x00, 0x02, 0xe2, 0xef, 0x0c, + 0xd7, 0x05, 0xd7, 0x08, 0x67, 0xa8, 0x00, 0xa7, 0xa8, 0x04, 0x17, 0xa0, + 0x00, 0x00, 0x00, 0x3f, 0x5f, 0x48, 0x00, 0x0e, 0x03, 0x00, 0x67, 0xad, + 0xc0, 0xf0, 0x00, 0x00, 0x80, 0xc8, 0x67, 0xad, 0xc0, 0xf0, 0x00, 0x00, + 0x80, 0xd8, 0x67, 0xdd, 0x82, 0xa8, 0x08, 0x57, 0x1d, 0x80, 0xc0, 0xe7, + 0xad, 0x80, 0xc0, 0xe7, 0xdd, 0x05, 0x32, 0x00, 0x97, 0xbe, 0x80, 0xcc, + 0x57, 0xa6, 0x65, 0x76, 0x61, 0x64, 0x7c, 0x67, 0xc8, 0x7c, 0xa7, 0x48, + 0x7c, 0x17, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x0e, 0x03, 0x01, 0x67, 0xc8, + 0x00, 0x63, 0xa0, 0x00, 0x00, 0x04, 0x00, 0x97, 0x0e, 0x80, 0xd4, 0xa7, + 0xae, 0x81, 0x00, 0x80, 0xd0, 0x02, 0xbe, 0x80, 0x50, 0x61, 0x6e, 0x64, + 0x6f, 0x72, 0x61, 0x20, 0x33, 0x32, 0x30, 0x31, 0x36, 0x20, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x0d, 0x00, + 0x17, 0xd0, 0x80, 0xcc, 0x02, 0xbe, 0x4e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x00, 0x4e, 0x17, + 0xa0, 0xf6, 0x02, 0xbe, 0x8c, 0x02, 0xbe, 0x44, 0x20, 0x6b, 0x69, 0x6c, + 0x6f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x00, 0x02, 0x81, 0x60, 0xa7, + 0xde, 0x28, 0x81, 0x20, 0xdf, 0xd0, 0x81, 0x18, 0x7d, 0xa3, 0x08, 0x00, + 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x00, 0x72, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0x94, 0xae, 0x76, 0x81, 0x2c, 0x5f, 0xd0, 0x81, + 0x20, 0xea, 0x12, 0x67, 0xd0, 0x81, 0x74, 0x97, 0xa0, 0x00, 0x00, 0x00, + 0xea, 0xe2, 0x1f, 0xe2, 0x02, 0xe2, 0x04, 0x5c, 0x08, 0xdc, 0x10, 0x02, + 0xb8, 0xf7, 0x97, 0x16, 0x80, 0x8c, 0x9c, 0xd1, 0x80, 0x8c, 0x0a, 0x0b, + 0xce, 0x18, 0xa8, 0xc0, 0xf9, 0x00, 0x00, 0xea, 0x0e, 0x54, 0xa0, 0xa1, + 0x94, 0xa0, 0x12, 0x02, 0xb8, 0xdb, 0xce, 0x18, 0x18, 0x97, 0x06, 0x80, + 0xd8, 0x28, 0xa0, 0x03, 0x7c, 0xe7, 0xd8, 0x04, 0x08, 0x0d, 0x12, 0x17, + 0x0e, 0x0b, 0x00, 0xea, 0x0f, 0x0e, 0x0b, 0x01, 0xea, 0x0a, 0x0e, 0x0b, + 0x02, 0xea, 0x05, 0x0e, 0x0b, 0x03, 0x02, 0x81, 0x5e, 0x84, 0xa6, 0x00, + 0x81, 0x3c, 0x0a, 0x80, 0x83, 0x97, 0xa6, 0x12, 0x34, 0x56, 0x78, 0x81, + 0x30, 0x84, 0xa6, 0x80, 0x81, 0x2c, 0x1a, 0x81, 0x55, 0x87, 0xa6, 0x64, + 0x61, 0x6f, 0x4c, 0x81, 0x40, 0x1a, 0x81, 0x4a, 0x17, 0xd0, 0x81, 0x10, + 0x02, 0x80, 0x7f, 0x9a, 0x81, 0x40, 0x97, 0xa6, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x64, 0x97, 0x06, 0x81, 0x6c, 0x97, 0x0e, 0x81, 0x38, 0x02, 0x80, + 0x9e, 0x67, 0xd8, 0x8b, 0x30, 0x47, 0xd0, 0x81, 0x6c, 0x0a, 0x30, 0x67, + 0xd0, 0x00, 0xef, 0x0c, 0x63, 0xa0, 0x00, 0x00, 0x04, 0x00, 0x7d, 0xa3, + 0x02, 0x00, 0xef, 0x0c, 0x57, 0xd0, 0x81, 0x64, 0xd5, 0xa5, 0x0a, 0x00, + 0x17, 0xd0, 0x81, 0x38, 0x4e, 0x15, 0xa0, 0x08, 0x59, 0x06, 0x00, 0xd5, + 0xa5, 0x01, 0x00, 0xd7, 0xd5, 0x81, 0x6c, 0x42, 0x00, 0x57, 0xd0, 0x81, + 0x64, 0x47, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x8a, 0xee, 0xea, 0x8a, + 0xeb, 0x87, 0xa6, 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, 0x1a, 0xbf, 0x80, + 0x17, 0xd0, 0x81, 0x34, 0x97, 0xa6, 0x00, 0x00, 0x00, 0x01, 0x81, 0x64, + 0x57, 0xd0, 0x81, 0x38, 0xea, 0xbf, 0x92, 0xdf, 0x08, 0xce, 0x98, 0x40, + 0x07, 0x07, 0xa7, 0x02, 0x29, 0x43, 0x28, 0x00, 0x1a, 0x1e, 0x54, 0x40, + 0x06, 0x68, 0xa0, 0x0d, 0x44, 0xa0, 0x09, 0x1a, 0x18, 0x5f, 0x08, 0x0f, + 0x12, 0x1c, 0xe0, 0x02, 0x0a, 0x06, 0x8f, 0x10, 0xea, 0x79, 0x03, 0xe0, + 0x42, 0x05, 0x7c, 0xa3, 0x20, 0x12, 0x00, 0x7c, 0xa1, 0x20, 0x12, 0x00, + 0x02, 0x0f, 0x02, 0x28, 0x02, 0x80, 0x48, 0x02, 0x80, 0x66, 0x02, 0x80, + 0x5b, 0x12, 0x00, 0x67, 0xd8, 0xb6, 0x2b, 0xa7, 0xd0, 0x82, 0x62, 0x17, + 0xa0, 0x00, 0x00, 0x00, 0x0d, 0x0e, 0x03, 0x00, 0x5f, 0xd0, 0x81, 0x5c, + 0x5f, 0xd0, 0x81, 0x60, 0x12, 0x00, 0x97, 0xa6, 0x65, 0x76, 0x61, 0x44, + 0x80, 0x90, 0x5c, 0xd0, 0x80, 0x88, 0x97, 0xa6, 0x00, 0x00, 0x01, 0x00, + 0x81, 0x1c, 0x5f, 0xd0, 0x81, 0x20, 0xdf, 0xd0, 0x81, 0x4c, 0xdf, 0xd0, + 0x81, 0x48, 0x12, 0x00, 0xa7, 0xde, 0xb5, 0xc2, 0x80, 0xdc, 0x67, 0xd8, + 0xb5, 0x90, 0xa7, 0xd0, 0x82, 0x96, 0x17, 0xa0, 0x00, 0x00, 0x00, 0x0b, + 0x0e, 0x03, 0x00, 0x12, 0x00, 0x27, 0xd0, 0x82, 0x96, 0x6f, 0x07, 0x12, + 0x00, 0x67, 0xd8, 0xb6, 0x01, 0xa7, 0xd0, 0x82, 0xc2, 0x17, 0xa0, 0x00, + 0x00, 0x00, 0x08, 0x0e, 0x03, 0x00, 0x12, 0x00, 0xdc, 0x0e, 0x5c, 0x10, + 0xdc, 0x1f, 0xe2, 0x06, 0xce, 0x98, 0x16, 0x81, 0x3c, 0x12, 0x00, 0x1f, + 0xd8, 0xb5, 0x41, 0x0a, 0x1c, 0x27, 0xd8, 0xb5, 0x2b, 0x03, 0xd8, 0xb5, + 0x37, 0x02, 0xbf, 0x2e, 0x97, 0xa6, 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, + 0x97, 0x06, 0x81, 0x34, 0x8a, 0xbe, 0xae, 0xa7, 0xde, 0x89, 0xe6, 0x81, + 0x34, 0x27, 0xd8, 0x89, 0xe0, 0x5f, 0x08, 0xea, 0xbe, 0x9f, 0x17, 0xb8, + 0x57, 0xb8, 0xe2, 0x21, 0x74, 0xa5, 0x07, 0x7c, 0x8a, 0x0b, 0x74, 0xa5, + 0x07, 0x70, 0x8a, 0x0b, 0xea, 0x88, 0xcb, 0x02, 0x81, 0x32, 0xea, 0x84, + 0x88, 0x7c, 0xa5, 0x0c, 0x62, 0x07, 0x74, 0xa5, 0x07, 0x70, 0x9a, 0x7c, + 0x14, 0xa8, 0x72, 0x04, 0x05, 0x00, 0xda, 0x16, 0x34, 0xa0, 0x06, 0x3c, + 0xd4, 0x80, 0x88, 0x3f, 0xcc, 0x10, 0x57, 0xa6, 0x00, 0x00, 0x00, 0xfd, + 0x14, 0xea, 0x80, 0xa1, 0x74, 0xa5, 0x07, 0x70, 0x8a, 0x0d, 0x74, 0xa5, + 0x07, 0x7c, 0x9a, 0x76, 0x02, 0x80, 0xf9, 0xea, 0x71, 0xce, 0x58, 0xae, + 0x72, 0x0c, 0x74, 0xa5, 0x07, 0x70, 0x8a, 0x0d, 0x74, 0xa5, 0x07, 0x7c, + 0x9a, 0x76, 0x02, 0x80, 0xe3, 0xea, 0x71, 0xce, 0x58, 0xae, 0x72, 0x10, + 0x74, 0xa5, 0x07, 0x70, 0x8a, 0x0d, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x76, + 0x02, 0x80, 0xcd, 0xea, 0x71, 0xce, 0x18, 0xa8, 0x72, 0x57, 0x06, 0x14, + 0x04, 0x05, 0x06, 0x4a, 0x80, 0x4f, 0x7d, 0xef, 0xd8, 0x04, 0x12, 0x00, + 0x1b, 0x00, 0x24, 0x00, 0x2c, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x44, 0x00, + 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x62, 0xea, 0x80, 0x4b, 0x72, 0xe0, 0x7f, + 0xd0, 0x82, 0x66, 0xea, 0x80, 0x42, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x6a, + 0xea, 0x39, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x6e, 0xea, 0x31, 0x72, 0xe0, + 0x7f, 0xd0, 0x82, 0x72, 0xea, 0x29, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x76, + 0xea, 0x21, 0x72, 0xe0, 0x7f, 0xd0, 0x82, 0x7a, 0xea, 0x19, 0x72, 0xe0, + 0x7f, 0xd0, 0x82, 0x82, 0xea, 0x11, 0x72, 0xe0, 0xb4, 0xa6, 0x00, 0x81, + 0x60, 0x9a, 0x08, 0x7f, 0xd0, 0x82, 0x8e, 0xea, 0x02, 0x7c, 0xa5, 0xf4, + 0xea, 0x83, 0xae, 0x32, 0x00, 0x82, 0x0f, 0x1e, 0x7d, 0xa3, 0x08, 0x00, + 0x54, 0xa0, 0xda, 0x5c, 0x10, 0x5c, 0x18, 0xe2, 0x06, 0xe2, 0x15, 0x1b, + 0x0a, 0x0d, 0x3c, 0x3c, 0x3c, 0x20, 0x55, 0x6e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x20, 0x54, 0xc0, 0x0c, 0x02, 0xbb, 0x24, 0xe2, 0x15, 0x03, + 0x20, 0x3a, 0x20, 0x67, 0xc0, 0x62, 0xa7, 0xa8, 0x1e, 0xe2, 0x1f, 0xe2, + 0x02, 0xe2, 0x15, 0x05, 0x3e, 0x3e, 0x3e, 0x0a, 0x0d, 0x92, 0xf0, 0x32, + 0x00, 0x62, 0x07, 0x2f, 0xad, 0x80, 0xd0, 0x95, 0xa6, 0x13, 0xe3, 0x82, + 0x9c, 0xce, 0x18, 0xa8, 0x7e, 0x94, 0x06, 0x80, 0xe0, 0x04, 0x05, 0x00, + 0xca, 0x81, 0x65, 0x87, 0xa6, 0x65, 0x76, 0x61, 0x44, 0x80, 0x90, 0x0a, + 0x80, 0x49, 0x97, 0x3e, 0x80, 0xb0, 0x97, 0x36, 0x80, 0xac, 0x97, 0x2e, + 0x80, 0xa8, 0x97, 0x26, 0x80, 0xa4, 0x97, 0x1e, 0x80, 0xa0, 0x97, 0xce, + 0x00, 0x80, 0x9c, 0x97, 0xce, 0x04, 0x80, 0x98, 0x97, 0xce, 0x08, 0x80, + 0x94, 0x97, 0xce, 0x10, 0x80, 0xc0, 0x97, 0xce, 0x14, 0x80, 0xc4, 0x2f, + 0xd4, 0x80, 0xbc, 0xa7, 0xce, 0x14, 0x80, 0xb4, 0x7d, 0xa3, 0x02, 0x00, + 0xaf, 0xd4, 0x80, 0xb8, 0x7d, 0xa1, 0x02, 0x00, 0x2f, 0xd7, 0x80, 0xc8, + 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x7c, 0x94, 0xae, 0x7e, 0x80, 0xe4, 0x9c, + 0x02, 0x0a, 0x81, 0x00, 0x5c, 0x0a, 0x74, 0xa5, 0x07, 0x7c, 0x9a, 0x7c, + 0xd4, 0xad, 0x7e, 0xcc, 0x0f, 0x77, 0x57, 0xbd, 0x80, 0xd0, 0x97, 0xae, + 0x80, 0xd0, 0x81, 0x70, 0x95, 0xee, 0xd8, 0x81, 0x55, 0x82, 0x9c, 0x9c, + 0xd0, 0x81, 0x4c, 0x0a, 0x07, 0x34, 0xa0, 0x00, 0x8a, 0x32, 0x04, 0x05, + 0x06, 0xda, 0x80, 0x72, 0x04, 0x05, 0x04, 0x1a, 0x1b, 0x97, 0xa6, 0x64, + 0x61, 0x6f, 0x4c, 0x81, 0x40, 0x84, 0xa6, 0x01, 0x81, 0x18, 0x1a, 0x0c, + 0x97, 0xd6, 0x81, 0x70, 0x81, 0x10, 0x5c, 0xd0, 0x81, 0x18, 0x74, 0xa5, + 0x07, 0x7c, 0x9a, 0x7c, 0x14, 0xa8, 0x7e, 0xea, 0x80, 0xa6, 0xdf, 0xd0, + 0x81, 0x50, 0x9c, 0x00, 0x0a, 0x2d, 0x9c, 0x01, 0x0a, 0x32, 0x14, 0xa0, + 0x80, 0x1c, 0xa8, 0x7c, 0xca, 0x7d, 0x1c, 0xa8, 0x7e, 0x1c, 0xa8, 0x78, + 0xca, 0x7d, 0x94, 0xae, 0x7a, 0x81, 0x44, 0x0f, 0x09, 0x1c, 0xa8, 0x78, + 0xca, 0x7d, 0x94, 0xae, 0x7a, 0x81, 0x44, 0xcc, 0x07, 0x6a, 0xea, 0x80, + 0x73, 0x95, 0xa6, 0x0e, 0x6d, 0x82, 0x9c, 0xea, 0xbf, 0x97, 0x95, 0xa6, + 0x0e, 0x74, 0x82, 0x9c, 0xea, 0xbf, 0x8e, 0x57, 0xa8, 0x80, 0xd0, 0x14, + 0xa0, 0x80, 0x1c, 0xd3, 0x80, 0xe0, 0x0a, 0x06, 0x1a, 0x30, 0x00, 0x00, + 0x1c, 0xa8, 0x7c, 0xca, 0x7d, 0x1c, 0xa8, 0x7e, 0x1c, 0xa8, 0x78, 0xca, + 0x7d, 0x54, 0x4d, 0x00, 0x7a, 0x0f, 0x09, 0x1c, 0xa8, 0x78, 0xca, 0x7d, + 0x54, 0x4d, 0x7f, 0x7a, 0xcc, 0x07, 0x6c, 0x1c, 0xa8, 0x78, 0xca, 0x7d, + 0x54, 0x05, 0x7a, 0xea, 0x26, 0x00, 0x00, 0x00, 0x1c, 0xa8, 0x7c, 0xca, + 0x7d, 0x1c, 0xa8, 0x7e, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0xaa, 0x7a, + 0x00, 0x0f, 0x09, 0x1c, 0xa8, 0x78, 0xca, 0x7d, 0x54, 0xaa, 0x7a, 0x7f, + 0xcc, 0x07, 0x6c, 0xea, 0x02, 0x72, 0xe0, 0x12, 0x00, 0xdf, 0xd7, 0x00, + 0x7d, 0xa3, 0x08, 0x00, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xa8, + 0x76, 0x67, 0xd0, 0x08, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x94, 0xae, + 0x76, 0x00, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x54, 0xaa, 0x76, 0x00, + 0x8f, 0x08, 0x1c, 0x48, 0x7f, 0x1a, 0x71, 0x8f, 0x0f, 0xa7, 0xd0, 0x08, + 0x63, 0x10, 0x97, 0x0e, 0x04, 0x1f, 0xd0, 0x81, 0x20, 0x0a, 0x19, 0x72, + 0xe0, 0xef, 0xd4, 0x81, 0x24, 0xad, 0xbe, 0xd9, 0xa5, 0x08, 0x00, 0xad, + 0xbf, 0xd7, 0xd5, 0x81, 0x20, 0x5f, 0xd0, 0x81, 0x20, 0x52, 0x72, 0xe0, + 0xe7, 0xad, 0x80, 0xfe, 0x5f, 0xb8, 0xd7, 0xd5, 0x00, 0x7f, 0xd0, 0x82, + 0x7e, 0xea, 0xbd, 0xc8, 0x72, 0xe0, 0xea, 0x81, 0x74, 0x3d, 0x0e, 0x47, + 0x0e, 0x51, 0x0e, 0x5f, 0x0e, 0xe3, 0x13, 0xe3, 0x13, 0xe3, 0x13, 0xe3, + 0x13, 0x54, 0xd5, 0x00, 0x7a, 0x8f, 0xa8, 0x80, 0xd0, 0x42, 0x00, 0x94, + 0xae, 0x7a, 0x00, 0x8f, 0xa8, 0x80, 0xd0, 0x42, 0x00, 0x54, 0xd5, 0x00, + 0x7a, 0x54, 0xd5, 0x01, 0x7a, 0x0f, 0xa9, 0x80, 0xd0, 0x42, 0x00, 0x94, + 0xae, 0x7a, 0x00, 0x94, 0xae, 0x7a, 0x01, 0x0f, 0xa9, 0x80, 0xd0, 0x42, + 0x00, 0x94, 0xae, 0x7a, 0x81, 0x44, 0x42, 0x00, 0x94, 0xae, 0x7a, 0x81, + 0x44, 0x94, 0xae, 0x7a, 0x81, 0x44, 0x42, 0x00, 0xd7, 0x05, 0x0f, 0xc9, + 0x04, 0x74, 0xa6, 0x08, 0x0a, 0x8a, 0x09, 0xce, 0x18, 0x88, 0x04, 0x7f, + 0xea, 0x1a, 0xae, 0x9c, 0x8e, 0x04, 0x7f, 0x81, 0x14, 0xce, 0x18, 0xd0, + 0x81, 0x14, 0xea, 0x0c, 0xd7, 0x05, 0x0f, 0xc9, 0x04, 0xce, 0x18, 0x88, + 0x04, 0x7f, 0xb7, 0x06, 0x82, 0xc2, 0x9a, 0x85, 0x75, 0x9c, 0x07, 0x3c, + 0xb8, 0x00, 0xb8, 0x48, 0xa6, 0x20, 0x0a, 0x7d, 0xef, 0xd8, 0x04, 0x78, + 0x00, 0x0f, 0x01, 0x53, 0x01, 0x2f, 0x03, 0x5b, 0x03, 0x74, 0x03, 0xa8, + 0x03, 0xcf, 0x03, 0xe0, 0x03, 0x68, 0x05, 0xae, 0x04, 0xc3, 0x04, 0xdc, + 0x04, 0xed, 0x04, 0xfe, 0x04, 0x0f, 0x05, 0x68, 0x05, 0x7c, 0x01, 0x68, + 0x05, 0x68, 0x05, 0xb8, 0x02, 0x1d, 0x01, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x32, + 0x02, 0x93, 0x02, 0x3e, 0x01, 0x48, 0x01, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x26, 0x03, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, 0x05, 0x68, + 0x05, 0x68, 0x05, 0x33, 0x01, 0x14, 0x02, 0x73, 0x01, 0x0a, 0x01, 0x1c, + 0x03, 0xc7, 0x02, 0xfb, 0x01, 0x95, 0x01, 0xce, 0x18, 0xc8, 0x00, 0x9c, + 0x07, 0x3c, 0xb8, 0x00, 0xb8, 0x1f, 0x00, 0x0a, 0x84, 0xe4, 0xea, 0xbf, + 0x68, 0x1c, 0xd0, 0x81, 0x5c, 0x1a, 0x04, 0x42, 0x00, 0xb4, 0xa6, 0x00, + 0x81, 0x5c, 0x8a, 0x80, 0x4c, 0xb4, 0xa6, 0x02, 0x81, 0x5c, 0x8a, 0x23, + 0x74, 0xa6, 0x05, 0x06, 0x8a, 0x04, 0x42, 0x00, 0xe7, 0xad, 0x80, 0xfb, + 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xd0, 0x82, 0x8a, 0x7c, 0xa5, 0xf4, 0x42, 0x00, 0x9c, 0xd0, 0x81, + 0x68, 0x0a, 0x3e, 0xe7, 0xad, 0x80, 0xfc, 0xd7, 0xa5, 0x00, 0x00, 0x00, + 0x00, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2c, 0x7f, 0xd0, 0x82, + 0x86, 0x7c, 0xa5, 0xf4, 0x42, 0x00, 0x74, 0xa6, 0x08, 0x06, 0x8a, 0x04, + 0x42, 0x00, 0xe7, 0xad, 0x80, 0xfa, 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, + 0xd7, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xd0, 0x82, 0x92, 0x7c, 0xa5, + 0xf4, 0x42, 0x00, 0x5c, 0xd0, 0x81, 0x68, 0x42, 0x00, 0x17, 0xb8, 0xea, + 0xbf, 0x7e, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x0d, 0x72, 0x17, + 0xb8, 0xea, 0xbf, 0x70, 0xd7, 0x0d, 0xd7, 0x15, 0x57, 0xc8, 0x0c, 0xce, + 0x98, 0x48, 0x00, 0x8f, 0x08, 0x17, 0x08, 0x03, 0x10, 0x57, 0x06, 0x0c, + 0xea, 0x26, 0x95, 0xa6, 0x0e, 0x80, 0x82, 0xac, 0x17, 0xb8, 0xea, 0xbf, + 0x4f, 0x49, 0xa6, 0x01, 0x00, 0x0a, 0x17, 0xb8, 0xea, 0xbf, 0x45, 0x17, + 0xb8, 0x57, 0x06, 0x00, 0x55, 0x0e, 0x04, 0xea, 0x83, 0xe0, 0xd7, 0x0d, + 0xd7, 0x15, 0x1f, 0x10, 0x0a, 0x11, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, + 0x54, 0x4d, 0x00, 0x72, 0x8f, 0x08, 0xcf, 0x17, 0x74, 0x97, 0xb8, 0x57, + 0xb8, 0x17, 0xb8, 0xea, 0xbf, 0x1a, 0x57, 0xd0, 0x81, 0x1c, 0x17, 0xb8, + 0xea, 0xbf, 0x11, 0xd4, 0xa1, 0x09, 0x67, 0xa8, 0x0d, 0x94, 0x38, 0x5f, + 0x18, 0xe2, 0x06, 0x8c, 0x3f, 0x1c, 0x38, 0xda, 0x73, 0x5f, 0xd1, 0x81, + 0x64, 0xea, 0xba, 0x82, 0x04, 0x0d, 0xfa, 0xaa, 0x80, 0x4a, 0x04, 0x0d, + 0xff, 0x0a, 0x80, 0x44, 0x04, 0x0d, 0xfc, 0x7a, 0x1e, 0xce, 0x18, 0x08, + 0x23, 0xa0, 0x00, 0x00, 0x00, 0xfd, 0xb4, 0xa0, 0x00, 0x8a, 0x09, 0x4e, + 0x8b, 0x06, 0x81, 0x60, 0xea, 0x3b, 0x4e, 0x9b, 0x06, 0x81, 0x60, 0xea, + 0x34, 0xce, 0x18, 0x08, 0x23, 0xa0, 0x00, 0x00, 0x00, 0xfa, 0xb4, 0xa0, + 0x00, 0x8a, 0x0d, 0x4e, 0x8b, 0x06, 0x81, 0x5c, 0xdc, 0xd0, 0x81, 0x68, + 0xea, 0x1b, 0x4e, 0x9b, 0x06, 0x81, 0x5c, 0xea, 0x14, 0xa7, 0xde, 0xb0, + 0x31, 0x81, 0x58, 0x02, 0xb1, 0x25, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, + 0xea, 0xbe, 0x99, 0x3f, 0x14, 0x17, 0xb8, 0xea, 0xbe, 0x92, 0x74, 0xa0, + 0x00, 0xce, 0x58, 0xd0, 0x81, 0x48, 0x9a, 0x08, 0xdc, 0xd0, 0x81, 0x48, + 0xea, 0x06, 0x5c, 0xd0, 0x81, 0x48, 0x17, 0xb8, 0xea, 0xbe, 0x79, 0x1f, + 0x08, 0x0a, 0x13, 0x97, 0xa6, 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, 0x97, + 0x0e, 0x81, 0x34, 0x17, 0xb8, 0xea, 0xbe, 0x64, 0x5f, 0xd2, 0x81, 0x64, + 0xdf, 0x09, 0xea, 0xb9, 0xe5, 0xd7, 0x0d, 0xce, 0x58, 0x08, 0x04, 0x0d, + 0x06, 0x4a, 0x15, 0x17, 0xf0, 0xd1, 0x82, 0x62, 0x97, 0x17, 0xd1, 0x82, + 0x62, 0x97, 0x00, 0x57, 0xb8, 0x17, 0xb8, 0xea, 0xbe, 0x3e, 0x1c, 0x0d, + 0x0a, 0x3c, 0x9c, 0x0d, 0x0a, 0x2c, 0x1c, 0x0e, 0x0a, 0x22, 0x9c, 0x0e, + 0x0a, 0x2a, 0x1c, 0x0f, 0x0a, 0x11, 0x9c, 0x0f, 0x0a, 0x11, 0x57, 0xb8, + 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbe, 0x1b, 0xdf, 0x0b, 0xea, + 0x48, 0x67, 0xa8, 0x08, 0xea, 0x43, 0x67, 0xa8, 0x09, 0xea, 0xbf, 0xbe, + 0x67, 0xa8, 0x0a, 0xea, 0xbf, 0xb8, 0x67, 0xa8, 0x0b, 0xea, 0xbf, 0xb2, + 0x67, 0xa8, 0x0c, 0xea, 0xbf, 0xac, 0xd7, 0x0d, 0x87, 0xd0, 0x04, 0x6a, + 0x05, 0x97, 0xd0, 0x04, 0xd7, 0x15, 0x17, 0x10, 0x97, 0x08, 0x67, 0xd0, + 0x08, 0x0e, 0x00, 0x00, 0x5f, 0xd0, 0x04, 0x97, 0xb8, 0x57, 0xb8, 0x17, + 0xb8, 0xd7, 0xd0, 0x00, 0xea, 0xbd, 0xd5, 0x9c, 0xd0, 0x80, 0x88, 0x1a, + 0x06, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbd, 0xc6, 0x74, 0xa6, + 0x08, 0x0a, 0x8a, 0x27, 0x44, 0x00, 0x0a, 0x2e, 0xce, 0x58, 0x08, 0xf7, + 0x0e, 0xaf, 0x1f, 0x9a, 0x30, 0xb4, 0xa0, 0x00, 0x8a, 0x09, 0x4e, 0x8b, + 0x0e, 0x82, 0xc2, 0xea, 0x07, 0x4e, 0x9b, 0x0e, 0x82, 0xc2, 0x3f, 0x0c, + 0x17, 0xb8, 0xea, 0xbd, 0x9b, 0xa7, 0xde, 0xaf, 0x49, 0x81, 0x58, 0x02, + 0xb0, 0x15, 0xea, 0x18, 0xa7, 0xde, 0xaf, 0x5e, 0x81, 0x58, 0x02, 0xb0, + 0x0a, 0xea, 0x0d, 0xa7, 0xde, 0xaf, 0x81, 0x81, 0x58, 0x02, 0xaf, 0xff, + 0xea, 0x02, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbd, 0x71, 0xce, + 0x58, 0xd0, 0x80, 0xd8, 0x17, 0xb8, 0xea, 0xbd, 0x67, 0x97, 0x0e, 0x80, + 0xdc, 0x17, 0xb8, 0xea, 0xbd, 0x5e, 0x44, 0xa0, 0x0d, 0x0a, 0x10, 0x74, + 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0x0d, 0x72, 0x17, 0xb8, 0xea, 0xbd, + 0x4b, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x72, 0x74, + 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x72, 0x17, 0xb8, 0xea, + 0xbd, 0x32, 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0a, 0x72, + 0x74, 0xa5, 0x06, 0x70, 0x9a, 0x7c, 0x54, 0xa5, 0x0d, 0x72, 0x17, 0xb8, + 0xea, 0xbd, 0x19, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, 0x00, + 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0x74, 0xa5, + 0x07, 0x74, 0x9a, 0x7c, 0xce, 0x58, 0xa8, 0x76, 0x34, 0xa0, 0x07, 0x9a, + 0x0f, 0xa7, 0xde, 0xaf, 0x52, 0x81, 0x58, 0x02, 0xaf, 0x71, 0x58, 0xa6, + 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbc, 0xe5, 0x02, 0xaf, 0xb3, 0x9a, 0x09, + 0x57, 0xd0, 0x00, 0x58, 0xa6, 0x20, 0x0a, 0xb4, 0xa6, 0x00, 0x81, 0x54, + 0x8a, 0x0c, 0x4e, 0x48, 0xa6, 0x00, 0x0a, 0x17, 0xb8, 0xea, 0xbc, 0xc8, + 0x4e, 0x58, 0xa6, 0x00, 0x0a, 0x17, 0xb8, 0xea, 0xbc, 0xbe, 0x02, 0xb0, + 0x77, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, + 0xea, 0xbc, 0xad, 0x5f, 0xd0, 0x81, 0x50, 0xdf, 0xd0, 0x81, 0x18, 0x97, + 0xd6, 0x81, 0x48, 0x81, 0x4c, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, + 0xa5, 0x02, 0x76, 0xaf, 0xd4, 0x81, 0x24, 0xa7, 0xde, 0x80, 0xa6, 0x81, + 0x20, 0x1f, 0x10, 0x0a, 0x19, 0x14, 0x48, 0x00, 0x04, 0xa0, 0x0d, 0x0a, + 0x11, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0x05, 0x76, 0x8f, 0x08, + 0x8f, 0x17, 0xea, 0x67, 0x74, 0xa5, 0x06, 0x74, 0x9a, 0x7c, 0x54, 0xa5, + 0x0d, 0x76, 0x74, 0xa5, 0x07, 0x74, 0x9a, 0x7c, 0x14, 0xa8, 0x76, 0xdf, + 0xd0, 0x81, 0x4c, 0x9c, 0xd0, 0x81, 0x50, 0x0a, 0x80, 0x58, 0x04, 0xa0, + 0x80, 0x0a, 0x07, 0x17, 0xb8, 0xea, 0xbc, 0x48, 0x17, 0xd0, 0x81, 0x10, + 0x02, 0xb7, 0x07, 0x9a, 0x32, 0x1f, 0x08, 0x0a, 0x1b, 0x95, 0xce, 0x0a, + 0x81, 0x28, 0x17, 0xb8, 0x7c, 0xa5, 0xf8, 0xd5, 0xd5, 0x81, 0x28, 0xd5, + 0xa5, 0x01, 0x00, 0xd7, 0xd5, 0x81, 0x70, 0xea, 0xbc, 0x22, 0x97, 0xa6, + 0xab, 0xcd, 0xef, 0x01, 0x81, 0x30, 0x97, 0x06, 0x81, 0x34, 0xdf, 0xd1, + 0x81, 0x64, 0xea, 0xb6, 0x64, 0xa7, 0xde, 0xae, 0x56, 0x81, 0x58, 0x02, + 0xae, 0x89, 0x58, 0xa6, 0x20, 0x0a, 0x17, 0xb8, 0xea, 0xbb, 0xfd, 0xa7, + 0xde, 0xae, 0x21, 0x81, 0x58, 0x02, 0xae, 0x77, 0x58, 0xa6, 0x20, 0x0a, + 0x17, 0xb8, 0xea, 0xbb, 0xeb, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, + 0x17, 0xb8, 0xea, 0xbb, 0xdf, 0xd7, 0x15, 0x02, 0xb2, 0x1d, 0x97, 0xb8, + 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, + 0xbb, 0xca, 0xd7, 0x15, 0xd7, 0x1d, 0x02, 0xb1, 0x17, 0xd7, 0xb8, 0x97, + 0xb8, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, + 0xea, 0xbb, 0xb1, 0x02, 0xb1, 0x8e, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, + 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0xa0, 0x02, 0xb0, 0xaa, 0x9a, + 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, + 0x8f, 0x02, 0xb0, 0x5b, 0x9a, 0x09, 0x58, 0xa6, 0x20, 0x0a, 0x57, 0xd0, + 0x00, 0x17, 0xb8, 0xea, 0xbb, 0x7e, 0x02, 0xb2, 0x6f, 0x9a, 0x09, 0x58, + 0xa6, 0x20, 0x0a, 0x57, 0xd0, 0x00, 0x17, 0xb8, 0xea, 0xbb, 0x6d, 0xd7, + 0x05, 0x27, 0xa8, 0x00, 0xea, 0x80, 0x49, 0xd7, 0x05, 0x27, 0xa8, 0x04, + 0xea, 0x80, 0x41, 0xd7, 0x05, 0x27, 0xa8, 0x08, 0xea, 0x39, 0xd7, 0x05, + 0x27, 0xa8, 0x0c, 0xea, 0x32, 0xd7, 0x05, 0x27, 0xa8, 0x10, 0xea, 0x2b, + 0xd7, 0x05, 0x27, 0xa8, 0x18, 0xea, 0x24, 0xd7, 0x05, 0x27, 0xa8, 0x1c, + 0xea, 0x1d, 0xd7, 0x05, 0x27, 0xa8, 0x20, 0xea, 0x16, 0xd7, 0x05, 0x27, + 0xa8, 0x24, 0xea, 0x0f, 0xd7, 0x05, 0x27, 0xa8, 0x28, 0xea, 0x08, 0x0f, + 0xcf, 0x04, 0x27, 0xa8, 0x14, 0x03, 0xd0, 0x80, 0xdc, 0xce, 0xd9, 0x45, + 0x00, 0xce, 0xd9, 0x45, 0x02, 0xc3, 0x8d, 0x04, 0x08, 0x14, 0xc8, 0x12, + 0x08, 0xa0, 0x02, 0x6c, 0x00, 0x17, 0xc8, 0x08, 0x32, 0x04, 0xd7, 0xa5, + 0x49, 0x56, 0x4e, 0x03, 0xea, 0x80, 0x55, 0xd7, 0xa5, 0x49, 0x4d, 0x4e, + 0x03, 0xea, 0x80, 0x4c, 0xd7, 0xa5, 0x54, 0x42, 0x41, 0x03, 0xea, 0x80, + 0x43, 0xd7, 0xa5, 0x55, 0x50, 0x46, 0x03, 0xea, 0x3a, 0xd7, 0xa5, 0x4c, + 0x4c, 0x49, 0x03, 0xea, 0x32, 0xd7, 0xa5, 0x43, 0x56, 0x53, 0x03, 0xea, + 0x2a, 0xd7, 0xa5, 0x5a, 0x56, 0x44, 0x03, 0xea, 0x22, 0xd7, 0xa5, 0x47, + 0x4c, 0x46, 0x03, 0xea, 0x1a, 0xd7, 0xa5, 0x54, 0x50, 0x42, 0x03, 0xea, + 0x12, 0xd7, 0xa5, 0x43, 0x52, 0x54, 0x03, 0xea, 0x0a, 0xd7, 0xa5, 0x44, + 0x4e, 0x55, 0x03, 0xea, 0x02, 0x02, 0xb2, 0x65, 0x0d, 0x0a, 0x0a, 0x2a, + 0x2a, 0x2a, 0x20, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x28, 0x00, 0x67, 0xb8, 0x02, 0xb2, 0x16, 0x02, 0xb2, 0x4a, 0x29, + 0x20, 0x61, 0x74, 0x20, 0x50, 0x43, 0x20, 0x3d, 0x20, 0x00, 0x17, 0xc8, + 0x04, 0x02, 0xb2, 0x85, 0x02, 0xb2, 0x52, 0xea, 0x00, 0xed, 0xa7, 0x00, + 0xc0, 0x6f, 0xad, 0x80, 0xc0, 0x2f, 0x0d, 0xef, 0x0c, 0xe2, 0x15, 0x01, + 0x2a, 0x5f, 0x08, 0xa7, 0xd0, 0x81, 0x08, 0xa7, 0xd2, 0x81, 0x74, 0x00, + 0x94, 0xa2, 0xea, 0x04, 0x94, 0xa2, 0x20, 0x05, 0x94, 0xa2, 0x7f, 0x06, + 0xe2, 0x07, 0x8a, 0x12, 0x7d, 0xa3, 0x02, 0x00, 0xef, 0xd4, 0x80, 0xd4, + 0x7d, 0xa1, 0x02, 0x00, 0x02, 0x20, 0xea, 0x4f, 0x57, 0xa0, 0x00, 0x00, + 0x00, 0x7e, 0xe2, 0x06, 0x67, 0xd0, 0x81, 0x74, 0xa7, 0xa8, 0x80, 0xea, + 0xe2, 0x1f, 0xe2, 0x02, 0xe2, 0x15, 0x02, 0x0a, 0x0d, 0xea, 0xbf, 0xb8, + 0x67, 0xd0, 0x81, 0x74, 0x97, 0x08, 0x7d, 0xa3, 0x08, 0x00, 0x84, 0xa2, + 0x0d, 0x00, 0x0a, 0x06, 0x8f, 0x10, 0xea, 0x78, 0xa3, 0x08, 0x8f, 0x10, + 0xd7, 0x11, 0x97, 0x09, 0x02, 0x80, 0xa1, 0x8a, 0x80, 0x83, 0xc7, 0xa0, + 0x00, 0x00, 0x00, 0x02, 0x1a, 0x22, 0x85, 0xa2, 0x53, 0x47, 0x00, 0x0a, + 0x80, 0x82, 0x85, 0xa2, 0x55, 0x47, 0x00, 0x0a, 0x80, 0x6d, 0x85, 0xa2, + 0x73, 0x67, 0x00, 0x0a, 0x80, 0x72, 0x85, 0xa2, 0x75, 0x67, 0x00, 0x0a, + 0x80, 0x5d, 0x57, 0x30, 0x97, 0x38, 0x7d, 0xa3, 0x03, 0x00, 0xe2, 0x08, + 0x8a, 0x0a, 0xe2, 0x20, 0x7d, 0xa1, 0x02, 0x00, 0x12, 0x00, 0xe2, 0x20, + 0x7d, 0xa1, 0x02, 0x00, 0x67, 0xd0, 0x08, 0x97, 0xd0, 0x04, 0xe2, 0x02, + 0xe2, 0x04, 0x12, 0x00, 0xd5, 0xa5, 0x0b, 0x00, 0xd5, 0xa5, 0x01, 0x00, + 0xd7, 0x05, 0x42, 0x00, 0xd5, 0xa5, 0x0a, 0x00, 0xd5, 0xa5, 0x01, 0x00, + 0xd7, 0x05, 0x42, 0x00, 0x02, 0xb1, 0x61, 0x0a, 0x0d, 0x4d, 0x69, 0x73, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x0a, 0x0d, 0x00, 0x12, 0x00, 0x12, 0x00, 0x57, 0x20, 0x02, 0x17, + 0x8a, 0x7a, 0x02, 0x80, 0x47, 0x8a, 0x5b, 0xea, 0x41, 0x57, 0x20, 0x02, + 0x0a, 0x8a, 0x6d, 0x02, 0x3a, 0x8a, 0x4f, 0xea, 0x41, 0x44, 0xa2, 0x0d, + 0x00, 0x0a, 0x2b, 0x44, 0xa2, 0x20, 0x00, 0x1a, 0x06, 0x8f, 0x08, 0xea, + 0x72, 0x17, 0x09, 0x44, 0xa2, 0x0d, 0x00, 0x0a, 0x0c, 0x44, 0xa2, 0x20, + 0x00, 0x0a, 0x06, 0x8f, 0x08, 0xea, 0x72, 0x97, 0x20, 0x17, 0x09, 0xd7, + 0x08, 0xe3, 0x10, 0x7c, 0xa1, 0x20, 0x12, 0x00, 0x7c, 0xa3, 0x20, 0x12, + 0x00, 0x17, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x84, 0xa2, 0x23, 0x00, 0x1a, + 0x34, 0x8f, 0x10, 0x8f, 0x1f, 0x1f, 0x18, 0x0a, 0x80, 0x65, 0xce, 0x58, + 0x50, 0x00, 0x44, 0xa0, 0x30, 0x4a, 0x80, 0x5b, 0x44, 0xa0, 0x39, 0xaa, + 0x80, 0x55, 0x63, 0xa0, 0x00, 0x00, 0x00, 0x30, 0xce, 0x23, 0xa0, 0x00, + 0x00, 0x00, 0x0a, 0x03, 0x08, 0x8f, 0x10, 0xcf, 0x1f, 0x5f, 0x7c, 0xa1, + 0x20, 0x12, 0x00, 0xce, 0x58, 0x50, 0x00, 0x44, 0xa0, 0x30, 0x4a, 0x32, + 0x44, 0xa0, 0x39, 0xaa, 0x0a, 0x63, 0xa0, 0x00, 0x00, 0x00, 0x30, 0xea, + 0x12, 0x44, 0xa0, 0x41, 0x4a, 0x20, 0x44, 0xa0, 0x46, 0xaa, 0x1b, 0x63, + 0xa0, 0x00, 0x00, 0x00, 0x37, 0xce, 0x23, 0xa0, 0x00, 0x00, 0x00, 0x10, + 0x03, 0x08, 0x8f, 0x10, 0xcf, 0x1f, 0x4f, 0x7c, 0xa1, 0x20, 0x12, 0x00, + 0x7c, 0xa3, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xff, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x18, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x63, 0x00, 0x77, 0x00, 0x7f, 0x00, 0x6b, 0x00, + 0x6b, 0x00, 0x63, 0x00, 0x63, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, + 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x6c, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x6c, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7c, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/src/NS32016/pandora/PandoraV1_00.rom b/src/NS32016/pandora/PandoraV1_00.rom new file mode 100644 index 0000000000000000000000000000000000000000..64f2b63ac90d671f0723ca880eeaf35b493b2e78 GIT binary patch literal 32768 zcmeHPeQ+B^mhTyjr19926(L7LQQ{$dB!rI`W*)7`lAJ zDEbW2A0T}RDWD%k$TW(yko1spAlV>21ZfAPN=P-3>LEP^=>Q}N(sPjh2GYxr{v-4M zPXD!F-PLdYFr{L?)?U}$1OclVQ+-2&(^b=E}g z?`x`KnB_ZmR=2q8y+C$3#oaZ~s!rVFZf+F!wL0A_b4QWK<7{m4h@NJ#vAM2(&jE3k zy?Ku~x4DYBwW8_Crsk)c#GSh~if-o~r`y@I+bPx_n8(L4;+ACZ8k%eB#G0gv1lx|C z8@FxIFiT3IlQrVK`FZzzN33tGaXFVUnoX^{Yg(M&GMSs2>O|1K2fBTg$$Z#(K=jl% zI-B=-;_A505tAyTFF%A()M97-8ZH#$yEF6%IU?qW5qW}|mfrSqwOcNFpcq76Pf$xs z;bg%Cg@D$GPK-;pgf8N@C9x!czke4rmH9bflS?_Nf-c!G`cl~2eoQnX`1pLoq`_x9 zcx95yLI$)H9qOt!7?D4QV@9+#XI8r=C1gh0@)SkqEeZV8s+A=sx=4E__mygj8%mD` z_{4or*jo_L7LH5h2ah4>z`CPLz2&fwwv)iE|A|bwfyXqhiKg73vw<3?M;miZ%l(c#I0Q zp*BP4;@M%Tl0Exz`>Ws^a~Z^ftb5Rlx)Il}>$JAS(d9DKohy4h;gSMLOm)JL5er{`7Z=z>OJS$}Ydo%n42r=KH6oN@yx@P4VQ*v}(8*g2a>>TaV z9HEJxGR;QGp{G2DcP6r z&GscL)t4M^HCy@~4MurjEcc$*wkFFd@#P?$EsduFc05dZuEjgPd{qp8YF>%VYdCX0 zZ@xb(sr1LQN=@E4HE1TvHgQ2c{ zMCC?rC&)GzAx9DCFXH1xS@DP*9P!9JpTM|DsaWdm(c@2DAgbKRIIOH=rN*&FFa`8U zhEMGBs4xX|NyJXry$C|zu|+U%(Zua+^d&np1LkaWa1;1bX3#)0Zfi!acm|b<2*x~h zp^t-^B@sAsY}aZ*2s&@b?B-2&#GcljH}7{(8PS9qZefI)*mu4HH(7a8Kw#gw(#@0l z9GDwn?i}OTDpx7PIc9FRCvMp~9Ry{qDq0y3v-NlLV;qM9d7S#bHtu;9`_3Fc6t^RDe?`UMAae8%4pvkk?IuKTt@mrUBTBH|V@^~!5^PW}ldVuMGcGY3 zk;95qvTQQ)TH@A$c0-)7(^sfTtYo34+$!n|WS9{t^M zNFS^7k$)JUa|}4WHFfQ-vG$O?U2c9=uVP$dvTzRh^>{oqBq1DQhjCd=Q(dz=^&Ip% z-L3V_P2xRw=jG{;Ifl=%!=>Aujm_=@VrzYyQ+z-~rRKnYv%}A`!zJRA^$pFn2RzPJ z9b%=⋘*|;-#2mIru6MGoSnv3?g?TzoXZ5=rdWO z)@Q0%>9IotNGcTYGyVZ%!LI#M-k||3-D#C7o*k&GY2GGnuu5CaG0DK<&R%H)4QGU; zI=@D0@av^@EdH5m@&|dFV^V{V=Zc{#SriKn9&{{};hA4I5fs2D(z?=|0RKG=ng}u| zJ|Q&}BU-r`m=O|upA+9_&kp?J*H;)R&pLvEzd+W+NOi!rj*Pr`iI2XtL8}e1w{KjH ztSiblX!ZtlC4mg9rJBz++NM}R1GDD=)l{)s9&7S+z-F_nS!`$V9u_}pM6StS-Vus* z)ynAVATq$URgfO1!xYdj!9S{s;Un^pMUss={!&cZ2FY$jp^I<5i!Zn)-}(`V_=zkc z6GRx%D!6TiWeG@Upz2+@ikGV{=&KADa;G)XmzGL}MwC1GR*_&^HTl*Zs>!#$%Z}Xb zPnrzgEbt8vg)Tn#?^404$>*l3c{2RB=7=LQeG^1NyDt+yTYQ=1$Un1EJ~?!xJ(yLi zr8Ia(huxeSeYCV7peY>3M;<(9a8QiCF%f)BZbc`w_FgZGza&pZD~H@!^Qo5;RG7Cx z!wm1Qfoci69U2p-)@;Q)=z__JmZ4kFou~j6q7vku>I7F3{IFcuLvXQNc!Jy~=S}1u zId_xW<=jhdlJholqnvkpn*M#wh>ur1vF{y|%~!xrBE{=uH1HmM{# zW43%w`vk$QM+fwcU43N44+Re`yx<7q7;XG7cuLS%^AMURrhGeUOG+u<-r06e+aOCU zSGSSdAi(DH4z{5b?_e7&85;;opKO=nFcZ*ujXt+wso{#H7RE!~6qT;?c$>Y``c!u| zYzlT8{CX}IhMoX{as`(9$A>=*^62;o%o<`f&>wM6!NmP-btFE4AaXj$*)jJNkvtFR zH|zgWU#-7WSInyzQR+P6;_>BO{w;(hq(8+3*7IyZ@FysUUfUO7d|8Gayh5v)RoWvm|f4<=h1J2_Satb zGA6c_5g425SL~mdqfFE?h7!HVMZ%%ql99bOnB=TnF`|R5%7?eTIlw}Gvu8l9@c|ip z`KNf0PQ!^$aH$W5Vljf~+$*ey>aXWk3wHv;U&{>On3ROC=CT08i!uWQ?cQQoDv*(m zb8q7?<#1Jch{Gi9UD$S~W?bXa7+S{#7MNxEnh6NBxQ1-n^u%^j+@~ZRsnJJ(vZC zoP8y9@x&JJ$H^RGf#PGdC=eYKB`BV_O4yW8cnZbvByHn@Rn-Mrc&r3=2XyN|ft7>g z?8B+WkN}IJ#Ih(+k)OJ~w&F&pklzHP-W#cmF&xzPuLTG z*PG#pAxfYlq}-QPY9Ek;@61?fWwJEPo_xADgYp0?bok71n2E|@61KqfY?rpBG_&61 z#%MqiAyjXKb^SH_9=_X5=Iwiu+e47Gtq)`hxRMKCK}(g`VI5>(-`4i#L*y(w8Wp6~ z=16<+eQ!Mx z@D`eL1Q*eqC->1Ti{#VHK<=QKh1^0j8(B^>ku0UzEhL*}s|lZdo?8_*sbcs-^utXE z68qi{Io>p8CU*d2taGHpYV$We=&y{qf+oZCg~J zH@I=vP8C@b4}O1FiHfX@2RCnndMh+2D^?LB)IUC$=r&+Aaz)rvOW9LfZ-Y_Vdt?{cO`2&hgnn2 zhhh>R`iK{hgX=tC^U5zYfW(;r*}j-G=xQe+G+>`S3HpqODo$%ESFTH^a-MuEYHmG;ciI-|B+g zeYk%g&Hu`g=U;d5RTY}%eZn-n_hDg?o5*3tfZ2m?KVZ`u%uFoi)y0qtGiCOT8bPDvTF`Ci&V~03*cq)XLnVQ{t@zQBz98UR0js1r@mCd~UTYBE^_b`Gf=;eScQ86<)PHG`LKrd^ge1kZ8DLRyWnG{Qdbo z@a>;pg`(mAuLtt3T2L0!K(Zj%o}k_6Y1E0Hgljik2=<|SX0AfG-;WxS_YF{nsS-U7 zSG)Y#0r%JbbGglQwJZ3i8-eudSMX1-|I@8q!9U#yq*uR!e|r6&ZtV*G=|&*E`W5`s z>;H6XSMX0a0_oMS;GbUqr(3)7{eQXDI2`pKb)wt6!P_)9e2OHE9d`}^Z&~EfBI8D zMx>nopL?cXIsdPm|5wicE9d`}^Z&~Ef93qY{F@ER`G5Lr2Fm$=<@~>L{vYKj=l|3E zzW+M)%J)ClxnwaBl=J_K3GD@JRlfgUz$uG}q~O1Zz+S*q1^)${vWQ3u{)-6g1x!`& zU%)Agh@{}Zh`?UJR0aP9oU({W3jT`->;+6!@L#|wi-@G)zlgwIz*GhQ1)Q>oNDBUo z2 Date: Tue, 14 Mar 2017 19:52:28 +0000 Subject: [PATCH 019/149] cpu_debug_t added, and dis command now wired up Change-Id: I11f4cd1cbebd5191a6c210e11ec5fc836049ce6a --- src/CMakeLists.txt | 3 + src/NS32016/32016.c | 8 +- src/NS32016/32016.h | 15 +- src/NS32016/NDis.h | 1 - src/NS32016/NSDis.c | 309 ++++++++++++++++----------------------- src/NS32016/NSDis.h | 2 + src/NS32016/Profile.c | 2 - src/NS32016/debug.c | 245 +++++++++++++++++++++++++++++++ src/NS32016/debug.h | 6 + src/NS32016/mem32016.c | 49 +++++-- src/cpu_debug.h | 28 ++++ src/debugger/debugger.c | 315 +++++++++++++++++++++++++--------------- 12 files changed, 642 insertions(+), 341 deletions(-) delete mode 100644 src/NS32016/NDis.h create mode 100644 src/NS32016/NSDis.h create mode 100644 src/NS32016/debug.c create mode 100644 src/NS32016/debug.h create mode 100644 src/cpu_debug.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64489380..54753ba4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -149,6 +149,8 @@ file( GLOB copro_32016_files NS32016/Profile.h NS32016/Trap.c NS32016/Trap.h + NS32016/debug.c + NS32016/debug.h ) # Z80 @@ -246,6 +248,7 @@ file( GLOB copro_arm_files file( GLOB debugger_files debugger/debugger.c debugger/debugger.h + cpu_debug.h ) if( ${DEBUG} ) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index 71b508de..998641be 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -113,6 +113,11 @@ uint32_t n32016_get_pc() return pc; } +void n32016_set_pc(uint32_t value) +{ + pc = value; +} + static void pushd(uint32_t val) { DEC_SP(4); @@ -1255,9 +1260,8 @@ void n32016_exec() } #ifdef PC_SIMULATION - FredSize = OpSize; // Temporary hack :( uint32_t Temp = pc; - ShowInstruction(startpc, &Temp, opcode, Function, OpSize.Op[0]); + n32016_show_instruction(startpc, &Temp, opcode, Function, &OpSize); #endif GetGenPhase2(Regs[0], 0); diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 65276b2d..6098ad55 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -333,6 +333,7 @@ extern void n32016_exec(); extern void n32016_close(); extern void n32016_build_matrix(); extern uint32_t n32016_get_pc(); +extern void n32016_set_pc(uint32_t value); extern void BreakPoint(uint32_t pc, uint32_t opcode); extern int32_t GetDisplacement(uint32_t* pPC); @@ -341,20 +342,6 @@ extern uint32_t r[8]; extern RegLKU Regs[2]; extern OperandSizeType FredSize; -extern void Disassemble(uint32_t Location, uint32_t End); - -#ifdef INSTRUCTION_PROFILING -extern void DisassembleUsingITrace(uint32_t Location, uint32_t End); -extern uint32_t IP[MEG16]; -#endif - - -#ifdef SHOW_INSTRUCTIONS -extern void ShowInstruction(uint32_t pc, uint32_t* pPC, uint32_t opcode, uint32_t Function, uint32_t OperandSize); -#else -#define ShowInstruction(...) -#endif - #if 1 extern void ShowRegisterWrite(RegLKU RegIn, uint32_t Value); #else diff --git a/src/NS32016/NDis.h b/src/NS32016/NDis.h deleted file mode 100644 index baa1f053..00000000 --- a/src/NS32016/NDis.h +++ /dev/null @@ -1 +0,0 @@ -extern const char InstuctionText[InstructionCount][8]; diff --git a/src/NS32016/NSDis.c b/src/NS32016/NSDis.c index a8a9edc8..85761363 100644 --- a/src/NS32016/NSDis.c +++ b/src/NS32016/NSDis.c @@ -2,22 +2,21 @@ #include #include #include +#include #include #include "defs.h" #include "32016.h" #include "mem32016.h" -#include "Profile.h" #include "Trap.h" #include "Decode.h" +#include "NSDis.h" #define HEX24 "x'%06" PRIX32 #define HEX32 "x'%" PRIX32 -uint32_t OpCount = 0; +// #define ADD_ASCII -OperandSizeType FredSize; - -const char LPRLookUp[16][20] = +static const char LPRLookUp[16][20] = { "UPSR", "DCR", @@ -37,56 +36,75 @@ const char LPRLookUp[16][20] = "MOD" }; -#ifdef INSTRUCTION_PROFILING -uint32_t IP[MEG16]; -#endif +static char *str_buf; +static size_t str_bufsize; + +static void StringInit(char *buf, size_t bufsize) { + str_buf = buf; + str_bufsize = bufsize; +} + + +static void StringAppend(const char *fmt, ...) { + int len; + va_list argptr; + va_start(argptr, fmt); + len = vsnprintf(str_buf, str_bufsize, fmt, argptr); + str_buf += len; + str_bufsize -= len; + va_end(argptr); +} + -void PostfixLookup(uint8_t Postfix) +#if 0 +static void PostfixLookup(uint8_t Postfix) { char PostFixLk[] = "BWTD"; if (Postfix) { Postfix--; - PiTRACE("%c", PostFixLk[Postfix & 3]); + StringAppend("%c", PostFixLk[Postfix & 3]); } } +#endif -void AddStringFlags(uint32_t opcode) + +static void AddStringFlags(uint32_t opcode) { if (opcode & (BIT(Backwards) | BIT(UntilMatch) | BIT(WhileMatch))) { - PiTRACE("["); + StringAppend("["); if (opcode & BIT(Backwards)) { - PiTRACE("B"); + StringAppend("B"); } uint32_t Options = (opcode >> 17) & 3; if (Options == 1) // While match { - PiTRACE("W"); + StringAppend("W"); } else if (Options == 3) { - PiTRACE("U"); + StringAppend("U"); } - PiTRACE("]"); + StringAppend("]"); } } -void AddCfgFLags(uint32_t opcode) +static void AddCfgFLags(uint32_t opcode) { - PiTRACE("["); - if (opcode & BIT(15)) PiTRACE("I"); - if (opcode & BIT(16)) PiTRACE("F"); - if (opcode & BIT(17)) PiTRACE("M"); - if (opcode & BIT(18)) PiTRACE("C"); - PiTRACE("]"); + StringAppend("["); + if (opcode & BIT(15)) StringAppend("I"); + if (opcode & BIT(16)) StringAppend("F"); + if (opcode & BIT(17)) StringAppend("M"); + if (opcode & BIT(18)) StringAppend("C"); + StringAppend("]"); } -const char InstuctionText[InstructionCount][8] = +static const char InstuctionText[InstructionCount][8] = { // FORMAT 0 "BEQ", "BNE", "BCS", "BCC", "BH", "BLS", "BGT", "BLE", "BFS", "BFC", "BLO", "BHS", "BLT", "BGE", "BR", "BN", @@ -137,18 +155,18 @@ const char InstuctionText[InstructionCount][8] = "TRAP" }; -void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) +static void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c, OperandSizeType *OperandSize) { const char RegLetter[] = "RFD*****"; if (Pattern.OpType < 8) { - PiTRACE("%c%0" PRId32, RegLetter[Pattern.RegType], Pattern.OpType); + StringAppend("%c%0" PRId32, RegLetter[Pattern.RegType], Pattern.OpType); } else if (Pattern.Whole < 16) { int32_t d = GetDisplacement(pPC); - PiTRACE("%0" PRId32 "(R%u)", d, (Pattern.Whole & 7)); + StringAppend("%0" PRId32 "(R%u)", d, (Pattern.Whole & 7)); } else { @@ -158,7 +176,7 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) { int32_t d1 = GetDisplacement(pPC); int32_t d2 = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(%" PRId32 "(FP))", d2, d1); + StringAppend("%" PRId32 "(%" PRId32 "(FP))", d2, d1); } break; @@ -166,7 +184,7 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) { int32_t d1 = GetDisplacement(pPC); int32_t d2 = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(%" PRId32 "(SP))", d2, d1); + StringAppend("%" PRId32 "(%" PRId32 "(SP))", d2, d1); } break; @@ -174,13 +192,13 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) { int32_t d1 = GetDisplacement(pPC); int32_t d2 = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(%" PRId32 "(SB))", d2 , d1); + StringAppend("%" PRId32 "(%" PRId32 "(SB))", d2 , d1); } break; case IllegalOperand: { - PiTRACE("(reserved)"); + StringAppend("(reserved)"); } break; @@ -190,22 +208,22 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) MultiReg temp3; temp3.u32 = SWAP32(read_x32(*pPC)); - if (FredSize.Op[c] == sz8) + if (OperandSize->Op[c] == sz8) Value = temp3.u8; - else if (FredSize.Op[c] == sz16) + else if (OperandSize->Op[c] == sz16) Value = temp3.u16; else Value = temp3.u32; - (*pPC) += FredSize.Op[c]; - PiTRACE(HEX32, Value); + (*pPC) += OperandSize->Op[c]; + StringAppend(HEX32, Value); } break; case Absolute: { int32_t d = GetDisplacement(pPC); - PiTRACE("@" HEX32, d); + StringAppend("@" HEX32, d); } break; @@ -213,34 +231,34 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) { int32_t d1 = GetDisplacement(pPC); int32_t d2 = GetDisplacement(pPC); - PiTRACE("EXT(" HEX32 ")+" HEX32, d1, d2); + StringAppend("EXT(" HEX32 ")+" HEX32, d1, d2); } break; case TopOfStack: { - PiTRACE("TOS"); + StringAppend("TOS"); } break; case FpRelative: { int32_t d = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(FP)", d); + StringAppend("%" PRId32 "(FP)", d); } break; case SpRelative: { int32_t d = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(SP)", d); + StringAppend("%" PRId32 "(SP)", d); } break; case SbRelative: { int32_t d = GetDisplacement(pPC); - PiTRACE("%" PRId32 "(SB)", d); + StringAppend("%" PRId32 "(SB)", d); } break; @@ -248,10 +266,10 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) { int32_t d = GetDisplacement(pPC); #if 1 - PiTRACE("* + %" PRId32, d); + StringAppend("* + %" PRId32, d); #else - PiTRACE("&06%" PRIX32 "[PC]", Start + d); + StringAppend("&06%" PRIX32 "[PC]", Start + d); #endif } break; @@ -264,15 +282,15 @@ void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32_t c) const char SizeLookup[] = "BWDQ"; RegLKU NewPattern; NewPattern.Whole = Pattern.Whole >> 11; - GetOperandText(Start, pPC, NewPattern, c); // Recurse - PiTRACE("[R%" PRId16 ":%c]", ((Pattern.Whole >> 8) & 3), SizeLookup[Pattern.Whole & 3]); + GetOperandText(Start, pPC, NewPattern, c, OperandSize); // Recurse + StringAppend("[R%" PRId16 ":%c]", ((Pattern.Whole >> 8) & 3), SizeLookup[Pattern.Whole & 3]); } break; } } } -void RegLookUp(uint32_t Start, uint32_t* pPC) +static void RegLookUp(uint32_t Start, uint32_t* pPC, OperandSizeType *OperandSize) { // printf("RegLookUp(%06" PRIX32 ", %06" PRIX32 ")\n", pc, (*pPC)); uint32_t Index; @@ -285,21 +303,21 @@ void RegLookUp(uint32_t Start, uint32_t* pPC) { if (Regs[0].Whole < 0xFFFF) { - PiTRACE(","); + StringAppend(","); } } - GetOperandText(Start, pPC, Regs[Index], Index); + GetOperandText(Start, pPC, Regs[Index], Index, OperandSize); } } } -void ShowRegs(uint8_t Pattern, uint8_t Reverse) +static void ShowRegs(uint8_t Pattern, uint8_t Reverse) { uint32_t Count; uint32_t First = 1; - PiTRACE("["); + StringAppend("["); for (Count = 0; Count < 8; Count++) { @@ -307,29 +325,29 @@ void ShowRegs(uint8_t Pattern, uint8_t Reverse) { if (First == 0) { - PiTRACE(","); + StringAppend(","); } if (Reverse) { - PiTRACE("R%" PRIu32, Count ^ 7); + StringAppend("R%" PRIu32, Count ^ 7); } else { - PiTRACE("R%" PRIu32, Count); + StringAppend("R%" PRIu32, Count); } First = 0; } } - PiTRACE("]"); + StringAppend("]"); } -const char PostFixLk[] = "BWTD"; -const char PostFltLk[] = "123F5678"; -const char EightSpaces[] = " "; +static const char PostFixLk[] = "BWTD"; +static const char PostFltLk[] = "123F5678"; +static const char EightSpaces[] = " "; -void AddInstructionText(uint32_t Function, uint32_t opcode, uint32_t OperandSize) +static void AddInstructionText(uint32_t Function, uint32_t opcode, uint32_t OperandSize) { if (Function < InstructionCount) { @@ -397,12 +415,12 @@ void AddInstructionText(uint32_t Function, uint32_t opcode, uint32_t OperandSize size_t Len = strlen(Str); if (Len < (sizeof(EightSpaces) - 1)) { - PiTRACE("%s%s", Str, &EightSpaces[Len]); + StringAppend("%s%s", Str, &EightSpaces[Len]); } } } -#ifdef SHOW_INSTRUCTIONS +#ifdef ADD_ASCII static void AddASCII(uint32_t opcode, uint32_t Format) { if (Format < sizeof(FormatSizes)) @@ -415,18 +433,19 @@ static void AddASCII(uint32_t opcode, uint32_t Format) if (Count < Len) { uint8_t Data = opcode & 0xFF; - PiTRACE("%c", (Data < 0x20) ? '.' : Data); + StringAppend("%c", (Data < 0x20) ? '.' : Data); opcode >>= 8; } else { - PiTRACE(" "); + StringAppend(" "); } } } } +#endif -void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t Function, uint32_t OperandSize) +void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t Function, OperandSizeType *OperandSize) { static uint32_t old_pc = 0xFFFFFFFF; @@ -450,25 +469,16 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t old_pc = StartPc; -#ifdef WIN32 - if (OpCount > 25000) - { - PiTRACE("25000 Traces done!\n"); - exit(1); - } - OpCount++; - //PiTRACE("#%08"PRIu32" ", OpCount); -#endif - - PiTRACE("&%06" PRIX32 " ", StartPc); - PiTRACE("[%08" PRIX32 "] ", opcode); + StringAppend("&%06" PRIX32 " ", StartPc); + StringAppend("[%08" PRIX32 "] ", opcode); uint32_t Format = Function >> 4; - PiTRACE("F%01" PRIu32 " ", Format); - //AddASCII(opcode, Format); - + StringAppend("F%01" PRIu32 " ", Format); +#ifdef ADD_ASCII + AddASCII(opcode, Format); +#endif if (Function < InstructionCount) { - AddInstructionText(Function, opcode, OperandSize); + AddInstructionText(Function, opcode, OperandSize->Op[0]); switch (Function) { @@ -479,7 +489,7 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t { int32_t Value = (opcode >> 7) & 0xF; NIBBLE_EXTEND(Value); - PiTRACE("%" PRId32 ",", Value); + StringAppend("%" PRId32 ",", Value); } break; @@ -487,21 +497,21 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t case SPR: { int32_t Value = (opcode >> 7) & 0xF; - PiTRACE("%s", LPRLookUp[Value]); + StringAppend("%s", LPRLookUp[Value]); if (Function == LPR) { - PiTRACE(","); + StringAppend(","); } } break; } - RegLookUp(StartPc, pPC); + RegLookUp(StartPc, pPC, OperandSize); if ((Function <= BN) || (Function == BSR)) { int32_t d = GetDisplacement(pPC); - PiTRACE("&%06"PRIX32" ", StartPc + d); + StringAppend("&%06"PRIX32" ", StartPc + d); } switch (Function) @@ -528,7 +538,7 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t { ShowRegs(read_x8((*pPC)++), 0); //Access directly we do not want tube reads! int32_t d = GetDisplacement(pPC); - PiTRACE(" " HEX32 "", d); + StringAppend(" " HEX32 "", d); } break; @@ -537,14 +547,14 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t case RXP: { int32_t d = GetDisplacement(pPC); - PiTRACE(" " HEX32 "", d); + StringAppend(" " HEX32 "", d); } break; case ACB: { int32_t d = GetDisplacement(pPC); - PiTRACE("PC x+'%" PRId32 "", d); + StringAppend("PC x+'%" PRId32 "", d); } break; @@ -552,7 +562,7 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t case CMPM: { int32_t d = GetDisplacement(pPC); - PiTRACE(",%" PRId32, (d / OperandSize) + 1); + StringAppend(",%" PRId32, (d / OperandSize->Op[0]) + 1); } break; @@ -560,7 +570,7 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t case INS: { int32_t d = GetDisplacement(pPC); - PiTRACE(",%" PRId32, d); + StringAppend(",%" PRId32, d); } break; @@ -582,38 +592,11 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t case EXTS: { uint8_t Value = read_x8((*pPC)++); - PiTRACE(",%" PRIu32 ",%" PRIu32, Value >> 5, ((Value & 0x1F) + 1)); + StringAppend(",%" PRIu32 ",%" PRIu32, Value >> 5, ((Value & 0x1F) + 1)); } break; } - - PiTRACE("\n"); - -#ifdef TEST_SUITE - -#if TEST_SUITE == 0 - if ((*pPC == 0x1CA9) || (*pPC == 0x1CB2)) -#else - if ((*pPC == 0x1CA8) || (*pPC == 0x1CBD)) -#endif - { - -#ifdef INSTRUCTION_PROFILING - DisassembleUsingITrace(0, 0x10000); -#endif - - n32016_dumpregs("Test Suite Complete!\n"); - exit(1); - } -#endif - -#ifndef TEST_SUITE - if (OpCount >= 10000) - { - n32016_dumpregs("Lots of trace data here!"); - } -#endif } return; @@ -621,7 +604,6 @@ void ShowInstruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t //PiTRACE("PC is :%08"PRIX32" ?????\n", *pPC); } -#endif void ShowRegisterWrite(RegLKU RegIn, uint32_t Value) { @@ -672,14 +654,16 @@ static void getgen(int gen, int c, uint32_t* pPC) } } -#define SET_FRED_SIZE(in) FredSize.Whole = OpSizeLookup[(in) & 0x03] +#define SET_OPERAND_SIZE(in) OperandSize.Whole = OpSizeLookup[(in) & 0x03] -void Decode(uint32_t* pPC) +static void Decode(uint32_t* pPC) { - //uint32_t StartPc = *pPC; + uint32_t StartPc = *pPC; uint32_t opcode = read_x32(*pPC); uint32_t Function = FunctionLookup[opcode & 0xFF]; uint32_t Format = Function >> 4; + OperandSizeType OperandSize; + Regs[0].Whole = Regs[1].Whole = 0xFFFF; @@ -689,7 +673,7 @@ void Decode(uint32_t* pPC) *pPC += FormatSizes[Format]; // Add the basic number of bytes for a particular instruction } - FredSize.Whole = 0; + OperandSize.Whole = 0; switch (Format) { case Format0: @@ -701,7 +685,7 @@ void Decode(uint32_t* pPC) case Format2: { - SET_FRED_SIZE(opcode); + SET_OPERAND_SIZE(opcode); getgen(opcode >> 11, 0, pPC); } break; @@ -709,14 +693,14 @@ void Decode(uint32_t* pPC) case Format3: { Function += ((opcode >> 7) & 0x0F); - SET_FRED_SIZE(opcode); + SET_OPERAND_SIZE(opcode); getgen(opcode >> 11, 0, pPC); } break; case Format4: { - SET_FRED_SIZE(opcode); + SET_OPERAND_SIZE(opcode); getgen(opcode >> 11, 0, pPC); getgen(opcode >> 6, 1, pPC); } @@ -725,10 +709,10 @@ void Decode(uint32_t* pPC) case Format5: { Function += ((opcode >> 10) & 0x0F); - SET_FRED_SIZE(opcode >> 8); + SET_OPERAND_SIZE(opcode >> 8); if (opcode & BIT(Translation)) { - SET_FRED_SIZE(0); // 8 Bit + SET_OPERAND_SIZE(0); // 8 Bit } } break; @@ -736,7 +720,7 @@ void Decode(uint32_t* pPC) case Format6: { Function += ((opcode >> 10) & 0x0F); - SET_FRED_SIZE(opcode >> 8); + SET_OPERAND_SIZE(opcode >> 8); // Ordering important here, as getgen uses Operand Size switch (Function) @@ -745,7 +729,7 @@ void Decode(uint32_t* pPC) case ASH: case LSH: { - FredSize.Op[0] = sz8; + OperandSize.Op[0] = sz8; } break; } @@ -758,7 +742,7 @@ void Decode(uint32_t* pPC) case Format7: { Function += ((opcode >> 10) & 0x0F); - SET_FRED_SIZE(opcode >> 8); + SET_OPERAND_SIZE(opcode >> 8); getgen(opcode >> 19, 0, pPC); getgen(opcode >> 14, 1, pPC); } @@ -801,11 +785,11 @@ void Decode(uint32_t* pPC) Function += ((opcode >> 6) & 3); } - SET_FRED_SIZE(opcode >> 8); + SET_OPERAND_SIZE(opcode >> 8); if (Function == CVTP) { - SET_FRED_SIZE(3); // 32 Bit + SET_OPERAND_SIZE(3); // 32 Bit } getgen(opcode >> 19, 0, pPC); @@ -838,62 +822,15 @@ void Decode(uint32_t* pPC) break; } - ShowInstruction(StartPc, pPC, opcode, Function, FredSize.Op[0]); + n32016_show_instruction(StartPc, pPC, opcode, Function, &OperandSize); } -#ifdef INSTRUCTION_PROFILING -#define BYTE_COUNT 10 - -void DisassembleUsingITrace(uint32_t Location, uint32_t End) -{ - uint32_t Index; - uint32_t Address = Location; - - PiTRACE("DisassembleUsingITrace(%06" PRIX32 ", %06" PRIX32 ")\n", Location, End); - for (Index = Location; Index < End; Index++) - { - if (IP[Index]) - { - if (Address < Index) - { - uint32_t Temp; - uint32_t Break = 0; - - for (Temp = Address; Temp < Index; Temp++, Break++) - { - if ((Break % BYTE_COUNT) == 0) - { - PiTRACE("\n.byte %u", read_x8(Temp)); - continue; - } - - PiTRACE(",%u", read_x8(Temp)); - } - - PiTRACE("\n"); - } - PiTRACE("#%06" PRId32 ": ", IP[Index]); - Address = Index; - Decode(&Address); - ShowTraps(); - CLEAR_TRAP(); - } - } -} -#endif - -void Disassemble(uint32_t Location, uint32_t End) +uint32_t n32016_disassemble(uint32_t addr, char *buf, size_t bufsize) { - do - { - Decode(&Location); - ShowTraps(); - CLEAR_TRAP(); - } - while (Location < End); - -#ifdef WIN32 - system("pause"); -#endif + StringInit(buf, bufsize); + Decode(&addr); + //ShowTraps(); + //CLEAR_TRAP(); + return addr; } diff --git a/src/NS32016/NSDis.h b/src/NS32016/NSDis.h new file mode 100644 index 00000000..b8348bbf --- /dev/null +++ b/src/NS32016/NSDis.h @@ -0,0 +1,2 @@ +void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t Function, OperandSizeType *OperandSize); +uint32_t n32016_disassemble(uint32_t addr, char *buf, size_t bufsize); diff --git a/src/NS32016/Profile.c b/src/NS32016/Profile.c index 56c05c27..90efee11 100644 --- a/src/NS32016/Profile.c +++ b/src/NS32016/Profile.c @@ -7,8 +7,6 @@ #include "Decode.h" #include "mem32016.h" #include "defs.h" -//#include "Trap.h" -#include "NDis.h" #include "Profile.h" #ifdef PROFILING diff --git a/src/NS32016/debug.c b/src/NS32016/debug.c new file mode 100644 index 00000000..9c8c0e1f --- /dev/null +++ b/src/NS32016/debug.c @@ -0,0 +1,245 @@ +#include +#include +#include + +#include "32016.h" +#include "mem32016.h" +#include "NSDis.h" +#include "debug.h" +#include "../cpu_debug.h" + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + + +int n32016_debug_enabled = 0; + +enum register_numbers { + i_R0, + i_R1, + i_R2, + i_R3, + i_R4, + i_R5, + i_R6, + i_R7, + i_PC, + i_SB, + i_SP0, + i_SP1, + i_FP, + i_INTBASE, + i_MOD, + i_PSR, + i_CFG, +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "PC", + "SB", + "SP0", + "SP1", + "FP", + "INTBASE", + "MOD", + "PSR", + "CFG", + NULL +}; + + +// enable/disable debugging on this CPU, returns previous value. +int dbg_debug_enable(int newvalue) { + int oldvalue = n32016_debug_enabled; + n32016_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +uint32_t dbg_memread(uint32_t addr) { + return read_x8(addr); +}; + +// as above but for instructions. +uint32_t dbg_memfetch(uint32_t addr) { + return read_x8(addr); +}; + +// CPU's usual memory write function. +void dbg_memwrite(uint32_t addr, uint32_t value) { + write_x8(addr, value); +}; + + +uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + return n32016_disassemble(addr, buf, bufsize); +}; + +// Get a register - which is the index into the names above +uint32_t dbg_reg_get(int which) { + switch (which) { + case i_R0: + case i_R1: + case i_R2: + case i_R3: + case i_R4: + case i_R5: + case i_R6: + case i_R7: + return r[which - i_R0]; + case i_PC: + return n32016_get_pc(); + case i_SB: + return PR.SB; + case i_SP0: + return PR.SP; + case i_SP1: + return PR.USP; + case i_FP: + return PR.FP; + case i_INTBASE: + return PR.INTBASE; + case i_MOD: + return PR.MOD.Whole; + case i_PSR: + return PR.PSR.Whole; + case i_CFG: + return PR.CFG.Whole; + default: + return 0; + } +}; + +// Set a register. +void dbg_reg_set(int which, uint32_t value) { + switch (which) { + case i_R0: + case i_R1: + case i_R2: + case i_R3: + case i_R4: + case i_R5: + case i_R6: + case i_R7: + r[which - i_R0] = value; + break; + case i_PC: + n32016_set_pc(value); + break; + case i_SB: + PR.SB = value; + break; + case i_SP0: + PR.SP = value; + break; + case i_SP1: + PR.USP = value; + break; + case i_FP: + PR.FP = value; + break; + case i_INTBASE: + PR.INTBASE = value; + break; + case i_MOD: + PR.MOD.Whole = value; + break; + case i_PSR: + PR.PSR.Whole = value; + break; + case i_CFG: + PR.CFG.Whole = value; + break; + default: + break; + } +}; + +// Print register value in CPU standard form. +size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + int i; + int bit; + char c; + if (which == i_PSR) { + // ! Supervisor Flags ! User Flags ! + // +-------------------------------+-------------------------------+ + // ! x x x x ! I ! P ! S ! U ! N ! Z ! F ! V ! x ! L ! T ! C ! + // !---+---+---+---+---+---+---+---!---+---+---+---+---+---+---+---! + // 15 8 7 0 + bit = 0x8000; + for (i = 0; i < 16 && i < bufsize; i++) { + if (0xF008 & bit) { + c = 'x'; + } else if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + *(buf + i) = c; + bit >>= 1; + } + if (i < bufsize) { + *(buf + i) = '\0'; + i++; + } + return i; + } if (which == i_MOD) { + return snprintf(buf, bufsize, "%04"PRIx32, dbg_reg_get(which) & 0xFFFF); + } else { + return snprintf(buf, bufsize, "%08"PRIx32, dbg_reg_get(which)); + } +}; + +// Parse a value into a register. +void dbg_reg_parse(int which, char *strval) { + uint32_t val = 0; + sscanf(strval, "%"SCNx32, &val); + dbg_reg_set(which, val); +}; + + +cpu_debug_t n32016_cpu_debug = { + .cpu_name = "32016", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memfetch = dbg_memfetch, + .memwrite = dbg_memwrite, + .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 +}; + +#if 0 + +// Name/model of CPU. +static const char *dbg_cpu_name = "32016"; + +cpu_debug_t *n32016_cpu_debug() +{ + cpu_debug.cpu_name = dbg_cpu_name; + cpu_debug.debug_enable = dbg_debug_enable; + cpu_debug.memread = dbg_memread; + cpu_debug.memfetch = dbg_memfetch; + cpu_debug.memwrite = dbg_memwrite; + cpu_debug.disassemble = dbg_disassemble; + cpu_debug.reg_names = dbg_reg_names; + cpu_debug.reg_get = dbg_reg_get; + cpu_debug.reg_set = dbg_reg_set; + cpu_debug.reg_print = dbg_reg_print; + cpu_debug.reg_parse = dbg_reg_parse; + return &cpu_debug; +} +#endif diff --git a/src/NS32016/debug.h b/src/NS32016/debug.h new file mode 100644 index 00000000..21ab508f --- /dev/null +++ b/src/NS32016/debug.h @@ -0,0 +1,6 @@ +#include "../cpu_debug.h" + +extern int n32016_debug_enabled; + +extern cpu_debug_t n32016_cpu_debug; + diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 12919b69..6fd51bc9 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -11,6 +11,9 @@ #include #include "32016.h" #include "mem32016.h" +#include "debug.h" +#include "../cpu_debug.h" + #include "../tube-client.h" #ifdef BEM @@ -72,7 +75,7 @@ void dump_ram(void) // FFFFFC - R4 status // FFFFFE - R4 data -uint8_t read_x8(uint32_t addr) +uint8_t raw_read_x8(uint32_t addr) { addr &= 0xFFFFFF; @@ -95,21 +98,31 @@ uint8_t read_x8(uint32_t addr) return 0; } +uint8_t read_x8(uint32_t addr) +{ + if (n32016_debug_enabled) { + return debug_memread(&n32016_cpu_debug, addr); + } else { + return raw_read_x8(addr); + } +} + uint16_t read_x16(uint32_t addr) { addr &= 0xFFFFFF; + if (!n32016_debug_enabled) { #ifdef NS_FAST_RAM - if (addr < IO_BASE) - { + if (addr < IO_BASE) + { #ifdef USE_MEMORY_POINTER - return *((uint16_t*) (ns32016ram + addr)); + return *((uint16_t*) (ns32016ram + addr)); #else - return *((uint16_t*) ( addr)); + return *((uint16_t*) ( addr)); #endif - - } + } #endif + } return read_x8(addr) | (read_x8(addr + 1) << 8); } @@ -118,16 +131,18 @@ uint32_t read_x32(uint32_t addr) { addr &= 0xFFFFFF; + if (!n32016_debug_enabled) { #ifdef NS_FAST_RAM - if (addr < IO_BASE) - { + if (addr < IO_BASE) + { #ifdef USE_MEMORY_POINTER - return *((uint32_t*) (ns32016ram + addr)); + return *((uint32_t*) (ns32016ram + addr)); #else - return *((uint32_t*) (addr)); + return *((uint32_t*) (addr)); #endif - } + } #endif + } return read_x8(addr) | (read_x8(addr + 1) << 8) | (read_x8(addr + 2) << 16) | (read_x8(addr + 3) << 24); } @@ -150,9 +165,13 @@ uint32_t read_n(uint32_t addr, uint32_t Size) { if ((addr + Size) <= IO_BASE) { - uint32_t Result = 0; - memcpy(&Result, ns32016ram + addr, Size); - return Result; + if (Size == 1) { + return read_x8(addr); + } else if (Size == 2) { + return read_x16(addr); + } else { + return read_x32(addr); + } } PiWARN("Bad read_n() addr @ %06" PRIX32 " size %" PRIX32 "\n", addr, Size); } else { diff --git a/src/cpu_debug.h b/src/cpu_debug.h new file mode 100644 index 00000000..835946f3 --- /dev/null +++ b/src/cpu_debug.h @@ -0,0 +1,28 @@ +// cpu_debug.h + +#ifndef CPU_DEBUG_H +#define CPU_DEBUG_H + +#include +#include + +typedef struct { + const char *cpu_name; // Name/model of CPU. + int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. + uint32_t (*memread)(uint32_t addr); // CPU's usual memory read function for data. + uint32_t (*memfetch)(uint32_t addr); // as above but for instructions. + void (*memwrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. + uint32_t (*disassemble)(uint32_t addr, char *buf, size_t bufsize); // disassemble one line, returns next address + const char **reg_names; // NULL pointer terminated list of register names. + uint32_t (*reg_get)(int which); // Get a register - which is the index into the names above + void (*reg_set)(int which, uint32_t value); // Set a register. + size_t (*reg_print)(int which, char *buf, size_t bufsize); // Print register value in CPU standard form. + void (*reg_parse)(int which, char *strval); // Parse a value into a register. +} cpu_debug_t; + +extern uint32_t debug_memread (cpu_debug_t *cpu, uint32_t addr); +extern uint32_t debug_memfetch(cpu_debug_t *cpu, uint32_t addr); +extern void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value); +extern void debug_preexec (cpu_debug_t *cpu, uint32_t addr); + +#endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 168d232f..4324c19e 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -5,127 +5,200 @@ #include "debugger.h" #include "../rpi-aux.h" +#include "../cpu_debug.h" -#define NUM_CMDS 4 +#define NUM_CMDS 8 // The Atom CRC Polynomial #define CRC_POLY 0x002d +static void doCmdRegs(char *params); +static void doCmdDis(char *params); static void doCmdCrc(char *params); static void doCmdFill(char *params); static void doCmdHelp(char *params); static void doCmdMem(char *params); +static void doCmdReadMem(char *params); +static void doCmdWriteMem(char *params); // The command process accepts abbreviated forms, for example // if h is entered, then help will match. // Must be kept in step with dbgCmdFuncs (just below) static char *dbgCmdStrings[NUM_CMDS] = { - "help", - "fill", - "crc", - "mem", + "help", + "regs", + "dis", + "fill", + "crc", + "mem", + "rdm", + "wrm", }; // Must be kept in step with dbgCmdStrings (just above) static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { - doCmdHelp, - doCmdFill, - doCmdCrc, - doCmdMem, + doCmdHelp, + doCmdRegs, + doCmdDis, + doCmdFill, + doCmdCrc, + doCmdMem, + doCmdReadMem, + doCmdWriteMem, }; +uint32_t debug_memread (cpu_debug_t *cpu, uint32_t addr) { + return cpu->memread(addr); +}; + +uint32_t debug_memfetch(cpu_debug_t *cpu, uint32_t addr) { + if (cpu->memfetch != NULL) { + return cpu->memfetch(addr); + } else { + return cpu->memread(addr); + } +}; + +void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { + cpu->memwrite(addr, value); +}; + +void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { +}; + +// TODO - Fix hardcoded implementation +extern cpu_debug_t n32016_cpu_debug; +cpu_debug_t *getCpu() { + return &n32016_cpu_debug; +} + /******************************************************** * Other global variables ********************************************************/ -char cmd[1000]; +static char strbuf[1000]; +static char cmd[1000]; // The current memory address (e.g. used when disassembling) -unsigned int memAddr = 0; +static unsigned int memAddr = 0; /******************************************* - * Memory accessors + * User Commands *******************************************/ -static void writeMem(uint32_t address, uint8_t data) { - *(uint8_t *)(address) = data; +static void doCmdHelp(char *params) { + cpu_debug_t *cpu = getCpu(); + int i; + printf("PiTubeDirect debugger; cpu = %s\r\n", cpu->cpu_name); + printf("Commands:\r\n"); + for (i = 0; i < NUM_CMDS; i++) { + printf(" %s\r\n", dbgCmdStrings[i]); + } } -static uint8_t readMem(uint32_t address) { - return *(uint8_t *)(address); +void doCmdRegs(char *params) { + cpu_debug_t *cpu = getCpu(); + const char **regs = cpu->reg_names; + int i = 0; + while (*regs) { + cpu->reg_print(i, strbuf, sizeof(strbuf)); + printf("%8s = %s\r\n", *regs, &strbuf[0]); + regs++; + i++; + } } -/******************************************* - * User Commands - *******************************************/ - -static void doCmdHelp(char *params) { - int i; - printf("Commands:\r\n"); - for (i = 0; i < NUM_CMDS; i++) { - printf(" %s\r\n", dbgCmdStrings[i]); - } +void doCmdDis(char *params) { + cpu_debug_t *cpu = getCpu(); + int i; + sscanf(params, "%x", &memAddr); + for (i = 0; i < 10; i++) { + memAddr = cpu->disassemble(memAddr, strbuf, sizeof(strbuf)); + printf("%s\r\n", &strbuf[0]); + } } static void doCmdFill(char *params) { - long i; - unsigned int start; - unsigned int end; - unsigned int data; - sscanf(params, "%x %x %x", &start, &end, &data); - printf("Wr: %04X to %04X = %02X\r\n", start, end, data); - for (i = start; i <= end; i++) { - writeMem(i, data); - } + cpu_debug_t *cpu = getCpu(); + long i; + unsigned int start; + unsigned int end; + unsigned int data; + sscanf(params, "%x %x %x", &start, &end, &data); + + printf("Wr: %04X to %04X = %02X\r\n", start, end, data); + for (i = start; i <= end; i++) { + cpu->memwrite(i, data); + } } static void doCmdCrc(char *params) { - long i; - int j; - unsigned int start; - unsigned int end; - unsigned int data; - unsigned int crc = 0; - sscanf(params, "%x %x", &start, &end); - for (i = start; i <= end; i++) { - data = readMem(i); - for (j = 0; j < 8; j++) { - crc = crc << 1; - crc = crc | (data & 1); - data >>= 1; - if (crc & 0x10000) - crc = (crc ^ CRC_POLY) & 0xFFFF; - } - } - printf("crc: %04X\r\n", crc); + cpu_debug_t *cpu = getCpu(); + long i; + int j; + unsigned int start; + unsigned int end; + unsigned int data; + unsigned int crc = 0; + sscanf(params, "%x %x", &start, &end); + for (i = start; i <= end; i++) { + data = cpu->memread(i); + for (j = 0; j < 8; j++) { + crc = crc << 1; + crc = crc | (data & 1); + data >>= 1; + if (crc & 0x10000) + crc = (crc ^ CRC_POLY) & 0xFFFF; + } + } + printf("crc: %04X\r\n", crc); } static void doCmdMem(char *params) { - int i, j; - unsigned int row[16]; - sscanf(params, "%x", &memAddr); - for (i = 0; i < 0x100; i+= 16) { - for (j = 0; j < 16; j++) { - row[j] = readMem(memAddr + i + j); - } - printf("%04X ", memAddr + i); - for (j = 0; j < 16; j++) { - printf("%02X ", row[j]); - } - printf(" "); - for (j = 0; j < 16; j++) { - unsigned int c = row[j]; - if (c < 32 || c > 126) { - c = '.'; + cpu_debug_t *cpu = getCpu(); + int i, j; + unsigned int row[16]; + sscanf(params, "%x", &memAddr); + for (i = 0; i < 0x100; i+= 16) { + for (j = 0; j < 16; j++) { + row[j] = cpu->memread(memAddr + i + j); + } + printf("%04X ", memAddr + i); + for (j = 0; j < 16; j++) { + printf("%02X ", row[j]); } - printf("%c", c); - } - printf("\r\n"); - } - memAddr += 0x100; + printf(" "); + for (j = 0; j < 16; j++) { + unsigned int c = row[j]; + if (c < 32 || c > 126) { + c = '.'; + } + printf("%c", c); + } + printf("\r\n"); + } + memAddr += 0x100; +} + +void doCmdReadMem(char *params) { + cpu_debug_t *cpu = getCpu(); + unsigned int addr; + unsigned int data; + sscanf(params, "%x", &addr); + data = cpu->memread(addr); + printf("Rd: %04X = %02X\r\n", addr, data); +} + +void doCmdWriteMem(char *params) { + cpu_debug_t *cpu = getCpu(); + unsigned int addr; + unsigned int data; + sscanf(params, "%x %x", &addr, &data); + printf("Wr: %04X = %02X\r\n", addr, data); + cpu->memwrite(addr++, data); } /******************************************************** @@ -133,24 +206,24 @@ static void doCmdMem(char *params) { ********************************************************/ static void dispatchCmd(char *cmd) { - int i; - char *cmdString; - int minLen; - int cmdStringLen; - int cmdLen = 0; - while (cmd[cmdLen] >= 'a' && cmd[cmdLen] <= 'z') { - cmdLen++; - } - for (i = 0; i < NUM_CMDS; i++) { - cmdString = dbgCmdStrings[i]; - cmdStringLen = strlen(cmdString); - minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; - if (strncmp(cmdString, cmd, minLen) == 0) { - (*dbgCmdFuncs[i])(cmd + cmdLen); - return; - } - } - printf("Unknown command %s\r\n", cmd); + int i; + char *cmdString; + int minLen; + int cmdStringLen; + int cmdLen = 0; + while (cmd[cmdLen] >= 'a' && cmd[cmdLen] <= 'z') { + cmdLen++; + } + for (i = 0; i < NUM_CMDS; i++) { + cmdString = dbgCmdStrings[i]; + cmdStringLen = strlen(cmdString); + minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; + if (strncmp(cmdString, cmd, minLen) == 0) { + (*dbgCmdFuncs[i])(cmd + cmdLen); + return; + } + } + printf("Unknown command %s\r\n", cmd); } /******************************************************** @@ -158,35 +231,35 @@ static void dispatchCmd(char *cmd) { ********************************************************/ void debugger_rx_char(char c) { - static int i = 0; - if (c == 8) { - // Handle backspace/delete - if (i > 0) { - i--; - RPI_AuxMiniUartWrite(c); - RPI_AuxMiniUartWrite(32); - RPI_AuxMiniUartWrite(c); - } - } else if (c == 13) { - // Handle return - if (i == 0) { - while (cmd[i]) { - RPI_AuxMiniUartWrite(cmd[i++]); + static int i = 0; + if (c == 8) { + // Handle backspace/delete + if (i > 0) { + i--; + RPI_AuxMiniUartWrite(c); + RPI_AuxMiniUartWrite(32); + RPI_AuxMiniUartWrite(c); + } + } else if (c == 13) { + // Handle return + if (i == 0) { + while (cmd[i]) { + RPI_AuxMiniUartWrite(cmd[i++]); + } + } else { + cmd[i] = 0; } - } else { - cmd[i] = 0; - } - RPI_AuxMiniUartWrite(10); - RPI_AuxMiniUartWrite(13); - dispatchCmd(cmd); - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite(' '); - i = 0; - } else if (c >= 32) { - // Handle any other non-control character - RPI_AuxMiniUartWrite(c); - cmd[i++] = c; - } + RPI_AuxMiniUartWrite(10); + RPI_AuxMiniUartWrite(13); + dispatchCmd(cmd); + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite(' '); + i = 0; + } else if (c >= 32) { + // Handle any other non-control character + RPI_AuxMiniUartWrite(c); + cmd[i++] = c; + } } From e26a3cb7f199668b8ddb4199af40bf56c3912a52 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 11:09:31 +0000 Subject: [PATCH 020/149] Updated cpu_debug_t to use post read/pre write hooks Change-Id: Ibf9eba93febb5f5a76cff8080e39930272bc0a78 --- src/CMakeLists.txt | 3 + src/NS32016/32016.c | 13 +++ src/NS32016/NSDis.c | 20 +++-- src/NS32016/debug.c | 13 +-- src/NS32016/mem32016.c | 193 ++++++++++++++++++---------------------- src/NS32016/mem32016.h | 33 ++++--- src/cpu_debug.h | 8 +- src/debugger/debugger.c | 15 +--- 8 files changed, 143 insertions(+), 155 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54753ba4..a1fddad1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,6 +35,9 @@ cmake_minimum_required( VERSION 2.8 ) # cross-compiler's ability to compile a simple program because that will fail project( tube-client C ASM ) +# By default we include the interactive debugger capability +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DINCLUDE_DEBUGGER" ) + # Add any C compiler flags here. The C flags concerned with processor tuning # are in the toolchain files toolchain-arm-none-eabi-bcm2835.cmake, etc. set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2" ) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index 998641be..b0fb5247 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -18,6 +18,11 @@ #include "Profile.h" #endif +#ifdef INCLUDE_DEBUGGER +#include "debug.h" +#include "../cpu_debug.h" +#endif + #define CXP_UNUSED_WORD 0xAAAA ProcessorRegisters PR; @@ -999,6 +1004,14 @@ void n32016_exec() Regs[1].Whole = 0xFFFF; startpc = pc; + +#ifdef INCLUDE_DEBUGGER + if (n32016_debug_enabled) + { + debug_preexec(&n32016_cpu_debug, pc); + } +#endif + opcode = read_x32(pc); if (pc == PR.BPC) diff --git a/src/NS32016/NSDis.c b/src/NS32016/NSDis.c index 85761363..b1fb2b7a 100644 --- a/src/NS32016/NSDis.c +++ b/src/NS32016/NSDis.c @@ -16,6 +16,10 @@ // #define ADD_ASCII +static inline uint32_t read_x32_internal(uint32_t addr) { + return read_x8(addr) | (read_x8(addr + 1) << 8) | (read_x8(addr + 2) << 16) | (read_x8(addr + 3) << 24); +} + static const char LPRLookUp[16][20] = { "UPSR", @@ -207,7 +211,7 @@ static void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32 int32_t Value; MultiReg temp3; - temp3.u32 = SWAP32(read_x32(*pPC)); + temp3.u32 = SWAP32(read_x32_internal(*pPC)); if (OperandSize->Op[c] == sz8) Value = temp3.u8; else if (OperandSize->Op[c] == sz16) @@ -518,25 +522,25 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u { case SAVE: { - ShowRegs(read_x8((*pPC)++), 0); //Access directly we do not want tube reads! + ShowRegs(read_x8_internal((*pPC)++), 0); //Access directly we do not want tube reads! } break; case RESTORE: { - ShowRegs(read_x8((*pPC)++), 1); //Access directly we do not want tube reads! + ShowRegs(read_x8_internal((*pPC)++), 1); //Access directly we do not want tube reads! } break; case EXIT: { - ShowRegs(read_x8((*pPC)++), 1); //Access directly we do not want tube reads! + ShowRegs(read_x8_internal((*pPC)++), 1); //Access directly we do not want tube reads! } break; case ENTER: { - ShowRegs(read_x8((*pPC)++), 0); //Access directly we do not want tube reads! + ShowRegs(read_x8_internal((*pPC)++), 0); //Access directly we do not want tube reads! int32_t d = GetDisplacement(pPC); StringAppend(" " HEX32 "", d); } @@ -591,7 +595,7 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u case INSS: case EXTS: { - uint8_t Value = read_x8((*pPC)++); + uint8_t Value = read_x8_internal((*pPC)++); StringAppend(",%" PRIu32 ",%" PRIu32, Value >> 5, ((Value & 0x1F) + 1)); } break; @@ -639,7 +643,7 @@ static void getgen(int gen, int c, uint32_t* pPC) if (gen >= EaPlusRn) { - Regs[c].Whole |= read_x8((*pPC)++) << 8; + Regs[c].Whole |= read_x8_internal((*pPC)++) << 8; (*pPC)++; if ((Regs[c].Whole & 0xF800) == (Immediate << 11)) @@ -659,7 +663,7 @@ static void getgen(int gen, int c, uint32_t* pPC) static void Decode(uint32_t* pPC) { uint32_t StartPc = *pPC; - uint32_t opcode = read_x32(*pPC); + uint32_t opcode = read_x32_internal(*pPC); uint32_t Function = FunctionLookup[opcode & 0xFF]; uint32_t Format = Function >> 4; OperandSizeType OperandSize; diff --git a/src/NS32016/debug.c b/src/NS32016/debug.c index 9c8c0e1f..7473ef71 100644 --- a/src/NS32016/debug.c +++ b/src/NS32016/debug.c @@ -67,17 +67,14 @@ int dbg_debug_enable(int newvalue) { // CPU's usual memory read function for data. uint32_t dbg_memread(uint32_t addr) { - return read_x8(addr); -}; - -// as above but for instructions. -uint32_t dbg_memfetch(uint32_t addr) { - return read_x8(addr); + // use the internal version so the debugger doesn't get notified + return read_x8_internal(addr); }; // CPU's usual memory write function. void dbg_memwrite(uint32_t addr, uint32_t value) { - write_x8(addr, value); + // use the internal version so the debugger doesn't get notified + write_x8_internal(addr, value); }; @@ -212,7 +209,6 @@ cpu_debug_t n32016_cpu_debug = { .cpu_name = "32016", .debug_enable = dbg_debug_enable, .memread = dbg_memread, - .memfetch = dbg_memfetch, .memwrite = dbg_memwrite, .disassemble = dbg_disassemble, .reg_names = dbg_reg_names, @@ -232,7 +228,6 @@ cpu_debug_t *n32016_cpu_debug() cpu_debug.cpu_name = dbg_cpu_name; cpu_debug.debug_enable = dbg_debug_enable; cpu_debug.memread = dbg_memread; - cpu_debug.memfetch = dbg_memfetch; cpu_debug.memwrite = dbg_memwrite; cpu_debug.disassemble = dbg_disassemble; cpu_debug.reg_names = dbg_reg_names; diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 6fd51bc9..ae49d6d8 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -11,10 +11,12 @@ #include #include "32016.h" #include "mem32016.h" +#include "../tube-client.h" + +#ifdef INCLUDE_DEBUGGER #include "debug.h" #include "../cpu_debug.h" - -#include "../tube-client.h" +#endif #ifdef BEM #include "../tube.h" @@ -75,17 +77,29 @@ void dump_ram(void) // FFFFFC - R4 status // FFFFFE - R4 data -uint8_t raw_read_x8(uint32_t addr) + +uint8_t read_x8(uint32_t addr) +#ifdef INCLUDE_DEBUGGER +{ + uint8_t val = read_x8_internal(addr); + if (n32016_debug_enabled) + { + debug_memread(&n32016_cpu_debug, addr, val, 1); + } + return val; +} +uint8_t read_x8_internal(uint32_t addr) +#endif { addr &= 0xFFFFFF; if (addr < IO_BASE) { -#ifdef USE_MEMORY_POINTER +#ifdef USE_MEMORY_POINTER return ns32016ram[addr]; #else return *(unsigned char *)(addr); -#endif +#endif } if ((addr & 0xFFFFF1) == 0xFFFFF0) @@ -98,31 +112,28 @@ uint8_t raw_read_x8(uint32_t addr) return 0; } -uint8_t read_x8(uint32_t addr) -{ - if (n32016_debug_enabled) { - return debug_memread(&n32016_cpu_debug, addr); - } else { - return raw_read_x8(addr); - } -} - uint16_t read_x16(uint32_t addr) { addr &= 0xFFFFFF; - if (!n32016_debug_enabled) { #ifdef NS_FAST_RAM - if (addr < IO_BASE) - { -#ifdef USE_MEMORY_POINTER - return *((uint16_t*) (ns32016ram + addr)); + if (addr < IO_BASE) + { + uint16_t val; +#ifdef USE_MEMORY_POINTER + val = *((uint16_t*) (ns32016ram + addr)); #else - return *((uint16_t*) ( addr)); -#endif + val = *((uint16_t*) ( addr)); +#endif +#ifdef INCLUDE_DEBUGGER + if (n32016_debug_enabled) + { + debug_memread(&n32016_cpu_debug, addr, val, 2); } #endif + return val; } +#endif return read_x8(addr) | (read_x8(addr + 1) << 8); } @@ -131,18 +142,24 @@ uint32_t read_x32(uint32_t addr) { addr &= 0xFFFFFF; - if (!n32016_debug_enabled) { #ifdef NS_FAST_RAM - if (addr < IO_BASE) - { -#ifdef USE_MEMORY_POINTER - return *((uint32_t*) (ns32016ram + addr)); + if (addr < IO_BASE) + { + uint32_t val; +#ifdef USE_MEMORY_POINTER + val = *((uint32_t*) (ns32016ram + addr)); #else - return *((uint32_t*) (addr)); -#endif + val = *((uint32_t*) (addr)); +#endif +#ifdef INCLUDE_DEBUGGER + if (n32016_debug_enabled) + { + debug_memread(&n32016_cpu_debug, addr, val, 3); } #endif + return val; } +#endif return read_x8(addr) | (read_x8(addr + 1) << 8) | (read_x8(addr + 2) << 16) | (read_x8(addr + 3) << 24); } @@ -156,46 +173,45 @@ uint64_t read_x64(uint32_t addr) return (((uint64_t) read_x32(addr + 4)) << 32) + read_x32(addr); } - // As this function returns uint32_t it *should* only be used for size 1, 2 or 4 uint32_t read_n(uint32_t addr, uint32_t Size) { addr &= 0xFFFFFF; - if (Size <= sizeof(uint32_t)) + switch (Size) { - if ((addr + Size) <= IO_BASE) - { - if (Size == 1) { - return read_x8(addr); - } else if (Size == 2) { - return read_x16(addr); - } else { - return read_x32(addr); - } - } - PiWARN("Bad read_n() addr @ %06" PRIX32 " size %" PRIX32 "\n", addr, Size); - } else { + case sz8: + return read_x8(addr); + case sz16: + return read_x16(addr); + case sz32: + return read_x32(addr); + default: PiWARN("Bad read_n() size @ %06" PRIX32 " size %" PRIX32 "\n", addr, Size); + return 0; } - - return 0; } void write_x8(uint32_t addr, uint8_t val) +#ifdef INCLUDE_DEBUGGER { - addr &= 0xFFFFFF; - -#ifdef TRACE_WRITEs - PiTRACE(" @%06"PRIX32" = %02"PRIX8"\n", addr, val); + if (n32016_debug_enabled) + { + debug_memwrite(&n32016_cpu_debug, addr, val, 1); + } + write_x8_internal(addr, val); +} +void write_x8_internal(uint32_t addr, uint8_t val) #endif +{ + addr &= 0xFFFFFF; if (addr <= (RAM_SIZE - sizeof(uint8_t))) { -#ifdef USE_MEMORY_POINTER +#ifdef USE_MEMORY_POINTER ns32016ram[addr] = val; #else *(unsigned char *)(addr) = val; -#endif +#endif return; } @@ -228,18 +244,20 @@ void write_x16(uint32_t addr, uint16_t val) { addr &= 0xFFFFFF; -#ifdef TRACE_WRITEs - PiTRACE(" @%06"PRIX32" = %04"PRIX16"\n", addr, val); -#endif - #ifdef NS_FAST_RAM if (addr <= (RAM_SIZE - sizeof(uint16_t))) { -#ifdef USE_MEMORY_POINTER +#ifdef INCLUDE_DEBUGGER + if (n32016_debug_enabled) + { + debug_memwrite(&n32016_cpu_debug, addr, val, 2); + } +#endif +#ifdef USE_MEMORY_POINTER *((uint16_t*) (ns32016ram + addr)) = val; #else *((uint16_t*) (addr)) = val; -#endif +#endif return; } #endif @@ -252,18 +270,20 @@ void write_x32(uint32_t addr, uint32_t val) { addr &= 0xFFFFFF; -#ifdef TRACE_WRITEs - PiTRACE(" @%06"PRIX32" = %06"PRIX32"\n", addr, val); -#endif - #ifdef NS_FAST_RAM if (addr <= (RAM_SIZE - sizeof(uint32_t))) { +#ifdef INCLUDE_DEBUGGER + if (n32016_debug_enabled) + { + debug_memwrite(&n32016_cpu_debug, addr, val, 4); + } +#endif #ifdef USE_MEMORY_POINTER *((uint32_t*) (ns32016ram + addr)) = val; #else *((uint32_t*) (addr)) = val; -#endif +#endif return; } #endif @@ -278,10 +298,6 @@ void write_x64(uint32_t addr, uint64_t val) { addr &= 0xFFFFFF; -#ifdef TRACE_WRITEs - PiTRACE(" @%06"PRIX32" = %016"PRIX64"\n", addr, val); -#endif - #ifdef NS_FAST_RAM if (addr <= (RAM_SIZE - sizeof(uint64_t))) { @@ -308,23 +324,12 @@ void write_Arbitary(uint32_t addr, void* pData, uint32_t Size) { addr &= 0xFFFFFF; -#ifdef TRACE_WRITEs - uint32_t Index; - register uint8_t* pV = (uint8_t*) pData; - - PiTRACE("?@%06"PRIX32" =", addr); - - for (Index = 0; Index < Size; Index++) - { - PiTRACE("%02"PRIX8, pV[Index]); - } - PiTRACE("\n"); -#endif - - //addr &= MEM_MASK; - #ifdef NS_FAST_RAM - if ((addr + Size) <= RAM_SIZE) +#ifdef INCLUDE_DEBUGGER + if ((addr + Size) <= RAM_SIZE && !n32016_debug_enabled) +#else + if ((addr + Size) <= RAM_SIZE) +#endif { memcpy(ns32016ram + addr, pData, Size); return; @@ -337,29 +342,3 @@ void write_Arbitary(uint32_t addr, void* pData, uint32_t Size) write_x8(addr++, *pValue++); } } - -#if 0 -uint32_t LoadBinary(const char *pFileName, uint32_t Location) -{ - FILE* pFile = fopen(pFileName, "rb"); - uint32_t End = 0; - - if (pFile) - { - long FileSize; - - fseek(pFile, 0, SEEK_END); - FileSize = ftell(pFile); - rewind(pFile); - - if ((Location + FileSize) < MEG16) - { - End = fread(ns32016ram + Location, sizeof(uint8_t), FileSize, pFile) + Location; - } - - fclose(pFile); - } - - return End; -} -#endif diff --git a/src/NS32016/mem32016.h b/src/NS32016/mem32016.h index f075fbde..77794039 100644 --- a/src/NS32016/mem32016.h +++ b/src/NS32016/mem32016.h @@ -12,16 +12,23 @@ #define NS_FAST_RAM void init_ram(void); -uint32_t LoadBinary(const char *pFileName, uint32_t Location); - -extern uint8_t read_x8(uint32_t addr); -extern uint16_t read_x16(uint32_t addr); -extern uint32_t read_x32(uint32_t addr); -extern uint64_t read_x64(uint32_t addr); -extern uint32_t read_n(uint32_t addr, uint32_t Size); - -extern void write_x8(uint32_t addr, uint8_t val); -extern void write_x16(uint32_t addr, uint16_t val); -extern void write_x32(uint32_t addr, uint32_t val); -extern void write_x64(uint32_t addr, uint64_t val); -extern void write_Arbitary(uint32_t addr, void* pData, uint32_t Size); + +#ifdef INCLUDE_DEBUGGER +uint8_t read_x8_internal(uint32_t addr); +#endif + +uint8_t read_x8(uint32_t addr); +uint16_t read_x16(uint32_t addr); +uint32_t read_x32(uint32_t addr); +uint64_t read_x64(uint32_t addr); +uint32_t read_n(uint32_t addr, uint32_t Size); + +#ifdef INCLUDE_DEBUGGER +void write_x8_internal(uint32_t addr, uint8_t val); +#endif + +void write_x8(uint32_t addr, uint8_t val); +void write_x16(uint32_t addr, uint16_t val); +void write_x32(uint32_t addr, uint32_t val); +void write_x64(uint32_t addr, uint64_t val); +void write_Arbitary(uint32_t addr, void* pData, uint32_t Size); diff --git a/src/cpu_debug.h b/src/cpu_debug.h index 835946f3..bf8ec1d0 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -10,7 +10,6 @@ typedef struct { const char *cpu_name; // Name/model of CPU. int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. uint32_t (*memread)(uint32_t addr); // CPU's usual memory read function for data. - uint32_t (*memfetch)(uint32_t addr); // as above but for instructions. void (*memwrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. uint32_t (*disassemble)(uint32_t addr, char *buf, size_t bufsize); // disassemble one line, returns next address const char **reg_names; // NULL pointer terminated list of register names. @@ -20,9 +19,8 @@ typedef struct { void (*reg_parse)(int which, char *strval); // Parse a value into a register. } cpu_debug_t; -extern uint32_t debug_memread (cpu_debug_t *cpu, uint32_t addr); -extern uint32_t debug_memfetch(cpu_debug_t *cpu, uint32_t addr); -extern void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value); -extern void debug_preexec (cpu_debug_t *cpu, uint32_t addr); +extern void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); +extern void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); +extern void debug_preexec (cpu_debug_t *cpu, uint32_t addr); #endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 4324c19e..2002e5de 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -48,21 +48,10 @@ static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { doCmdWriteMem, }; - -uint32_t debug_memread (cpu_debug_t *cpu, uint32_t addr) { - return cpu->memread(addr); -}; - -uint32_t debug_memfetch(cpu_debug_t *cpu, uint32_t addr) { - if (cpu->memfetch != NULL) { - return cpu->memfetch(addr); - } else { - return cpu->memread(addr); - } +void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { }; -void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { - cpu->memwrite(addr, value); +void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { }; void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { From d2480440f6fa13a1129e542d33c3a37e7817c539 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 16:57:36 +0000 Subject: [PATCH 021/149] Debugger: changes to PC and PSW presentation Change-Id: Ie1f5b8cc3311a60682050fc0e472556d282fdaad --- src/NS32016/debug.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/NS32016/debug.c b/src/NS32016/debug.c index 7473ef71..a5b409c6 100644 --- a/src/NS32016/debug.c +++ b/src/NS32016/debug.c @@ -16,6 +16,7 @@ int n32016_debug_enabled = 0; enum register_numbers { + i_PC, i_R0, i_R1, i_R2, @@ -24,7 +25,6 @@ enum register_numbers { i_R5, i_R6, i_R7, - i_PC, i_SB, i_SP0, i_SP1, @@ -37,6 +37,7 @@ enum register_numbers { // NULL pointer terminated list of register names. static const char *dbg_reg_names[] = { + "PC", "R0", "R1", "R2", @@ -45,7 +46,6 @@ static const char *dbg_reg_names[] = { "R5", "R6", "R7", - "PC", "SB", "SP0", "SP1", @@ -85,6 +85,8 @@ uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { // Get a register - which is the index into the names above uint32_t dbg_reg_get(int which) { switch (which) { + case i_PC: + return n32016_get_pc(); case i_R0: case i_R1: case i_R2: @@ -94,14 +96,12 @@ uint32_t dbg_reg_get(int which) { case i_R6: case i_R7: return r[which - i_R0]; - case i_PC: - return n32016_get_pc(); case i_SB: return PR.SB; case i_SP0: - return PR.SP; + return sp[0]; case i_SP1: - return PR.USP; + return sp[1]; case i_FP: return PR.FP; case i_INTBASE: @@ -120,6 +120,9 @@ uint32_t dbg_reg_get(int which) { // Set a register. void dbg_reg_set(int which, uint32_t value) { switch (which) { + case i_PC: + n32016_set_pc(value); + break; case i_R0: case i_R1: case i_R2: @@ -130,17 +133,14 @@ void dbg_reg_set(int which, uint32_t value) { case i_R7: r[which - i_R0] = value; break; - case i_PC: - n32016_set_pc(value); - break; case i_SB: PR.SB = value; break; case i_SP0: - PR.SP = value; + sp[0] = value; break; case i_SP1: - PR.USP = value; + sp[1] = value; break; case i_FP: PR.FP = value; @@ -162,11 +162,15 @@ void dbg_reg_set(int which, uint32_t value) { } }; +static const char* flagname = "****IPSUNZFV*LTC"; + // Print register value in CPU standard form. size_t dbg_reg_print(int which, char *buf, size_t bufsize) { int i; int bit; char c; + const char *flagnameptr = flagname; + if (which == i_PSR) { // ! Supervisor Flags ! User Flags ! // +-------------------------------+-------------------------------+ @@ -174,15 +178,17 @@ size_t dbg_reg_print(int which, char *buf, size_t bufsize) { // !---+---+---+---+---+---+---+---!---+---+---+---+---+---+---+---! // 15 8 7 0 bit = 0x8000; - for (i = 0; i < 16 && i < bufsize; i++) { - if (0xF008 & bit) { - c = 'x'; - } else if (psr & bit) { + for (i = 0; i < 16 * 3 && i < bufsize - 3; i += 3) { + if (psr & bit) { c = '1'; } else { c = '0'; } - *(buf + i) = c; + + *(buf + i) = *flagnameptr++; + *(buf + i + 1) = c; + *(buf + i + 2) = ' '; + bit >>= 1; } if (i < bufsize) { From 54a85632a9428135555464c45c13a7c53efd86d5 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 16:59:01 +0000 Subject: [PATCH 022/149] Debugger: break/watch points now implemented Change-Id: Ica6152a79646a20de33e80568e4c79cfca9b3112 --- src/cpu_debug.h | 3 + src/debugger/debugger.c | 442 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 402 insertions(+), 43 deletions(-) diff --git a/src/cpu_debug.h b/src/cpu_debug.h index bf8ec1d0..96c3a2eb 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -6,6 +6,9 @@ #include #include +// Register 0 must be the program counter +#define DBG_REG_PC 0 + typedef struct { const char *cpu_name; // Name/model of CPU. int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 2002e5de..a595e5a0 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -7,55 +7,134 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" -#define NUM_CMDS 8 +#define NUM_CMDS 19 // The Atom CRC Polynomial #define CRC_POLY 0x002d -static void doCmdRegs(char *params); -static void doCmdDis(char *params); +// The space available for address comparators depends on the size of the CPU core +#define MAXBKPTS 8 + +// The number of different watch/breakpoint modes +#define NUM_MODES 3 + +// The following watch/breakpoint modes are defined +#define MODE_LAST 0 +#define MODE_WATCH 1 +#define MODE_BREAK 2 + +// Breakpoint Mode Strings, should match the modes above +static const char *modeStrings[NUM_MODES] = { + "", + "Watch", + "Break" +}; + +typedef struct { + int mode; + uint32_t addr; + uint32_t mask; +} breakpoint_t; + +// Watches/Breakpoints addresses etc, stored sorted +static breakpoint_t exec_breakpoints[MAXBKPTS + 1]; +static breakpoint_t mem_rd_breakpoints[MAXBKPTS + 1]; +static breakpoint_t mem_wr_breakpoints[MAXBKPTS + 1]; + +static void doCmdBreakI(char *params); +static void doCmdBreakRdMem(char *params); +static void doCmdBreakWrMem(char *params); +static void doCmdClear(char *params); +static void doCmdContinue(char *params); static void doCmdCrc(char *params); +static void doCmdDis(char *params); static void doCmdFill(char *params); static void doCmdHelp(char *params); +static void doCmdList(char *params); static void doCmdMem(char *params); static void doCmdReadMem(char *params); +static void doCmdRegs(char *params); +static void doCmdStep(char *params); +static void doCmdTrace(char *params); +static void doCmdWatchI(char *params); +static void doCmdWatchRdMem(char *params); +static void doCmdWatchWrMem(char *params); static void doCmdWriteMem(char *params); + // The command process accepts abbreviated forms, for example // if h is entered, then help will match. // Must be kept in step with dbgCmdFuncs (just below) static char *dbgCmdStrings[NUM_CMDS] = { - "help", - "regs", - "dis", - "fill", - "crc", - "mem", - "rdm", - "wrm", + "help", + "continue", + "step", + "regs", + "dis", + "fill", + "crc", + "mem", + "rdm", + "wrm", + "trace", + "blist", + "breakx", + "watchx", + "breakrm", + "watchrm", + "breakwm", + "watchwm", + "clear" }; // Must be kept in step with dbgCmdStrings (just above) static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { - doCmdHelp, - doCmdRegs, - doCmdDis, - doCmdFill, - doCmdCrc, - doCmdMem, - doCmdReadMem, - doCmdWriteMem, + doCmdHelp, + doCmdContinue, + doCmdStep, + doCmdRegs, + doCmdDis, + doCmdFill, + doCmdCrc, + doCmdMem, + doCmdReadMem, + doCmdWriteMem, + doCmdTrace, + doCmdList, + doCmdBreakI, + doCmdWatchI, + doCmdBreakRdMem, + doCmdWatchRdMem, + doCmdBreakWrMem, + doCmdWatchWrMem, + doCmdClear }; -void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { -}; -void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { -}; +/******************************************************** + * Other global variables + ********************************************************/ + +static char strbuf[1000]; + +static char cmd[1000]; + +static volatile int stopped = 0; + +// When single stepping, trace (i.e. log) event N instructions +// Setting this to 0 will disable logging +static int tracing = 0; + +static int trace_counter = 0; + +static int stepping = 0; + +static int step_counter; + +// The current memory address (e.g. used when disassembling) +static unsigned int memAddr = 0; -void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { -}; // TODO - Fix hardcoded implementation extern cpu_debug_t n32016_cpu_debug; @@ -64,15 +143,150 @@ cpu_debug_t *getCpu() { } /******************************************************** - * Other global variables + * Hooks from CPU Emulation ********************************************************/ -static char strbuf[1000]; +static void cpu_stop() { +// if (!stopped) { +// printf("Stopped\r\n"); +// } + stopped = 1; +} -static char cmd[1000]; +static void cpu_continue() { +// if (stopped) { +// printf("Running\r\n"); +// } + stopped = 0; +} -// The current memory address (e.g. used when disassembling) -static unsigned int memAddr = 0; +static void disassemble_addr(uint32_t addr) { + cpu_debug_t *cpu = getCpu(); + cpu->disassemble(addr, strbuf, sizeof(strbuf)); + printf("%s\r\n", &strbuf[0]); +} + + +static inline breakpoint_t *check_for_breakpoints(uint32_t addr, breakpoint_t *ptr) { + while (ptr->mode != MODE_LAST) { + if ((addr & ptr->mask) == ptr->addr) { + if (ptr->mode == MODE_BREAK) { + cpu_stop(); + } + return ptr; + } + ptr++; + } + return NULL; +} + +// TODO: size should not be ignored! + +static inline void generic_memory_access(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size, + const char *type, breakpoint_t *list) { + breakpoint_t *ptr = check_for_breakpoints(addr, list); + if (ptr) { + uint32_t pc = cpu->reg_get(DBG_REG_PC); + if (ptr->mode == MODE_BREAK) { + printf("%s breakpoint hit at %"PRIx32" : %"PRIX32" = %"PRIX32"\r\n", type, pc, addr, value); + disassemble_addr(pc); + } else { + printf("%s watchpoint hit at %"PRIx32" : %"PRIX32" = %"PRIX32"\r\n", type, pc, addr, value); + } + } +} + +void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { + generic_memory_access(cpu, addr, value, size, "Mem Rd", mem_rd_breakpoints); +}; + +void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { + generic_memory_access(cpu, addr, value, size, "Mem Wr", mem_wr_breakpoints); +}; + +void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { + int show = 0; + + breakpoint_t *ptr = check_for_breakpoints(addr, exec_breakpoints); + + if (ptr) { + if (ptr->mode == MODE_BREAK) { + printf("Exec breakpoint hit at %"PRIx32"\r\n", addr); + show = 1; + + } else { + printf("Exec watchpoint hit at %"PRIx32"\r\n", addr); + } + } + + if (stepping) { + if (tracing) { + if (++trace_counter == tracing) { + trace_counter = 0; + show = 1; + } + } + if (++step_counter == stepping) { + step_counter = 0; + cpu_stop(); + show = 1; + } + } + if (show) { + disassemble_addr(addr); + } + while (stopped); +}; + +/******************************************* + * Helpers + *******************************************/ + +// Set the breakpoint state variables +void setBreakpoint(breakpoint_t *ptr, char *type, unsigned int addr, unsigned int mask, unsigned int mode) { + printf("%s %s set at %04X\r\n", type, modeStrings[mode], addr); + ptr->addr = addr & mask; + ptr->mask = mask; + ptr->mode = mode; +} + +void copyBreakpoint(breakpoint_t *ptr1, breakpoint_t *ptr2) { + ptr1->addr = ptr2->addr; + ptr1->mask = ptr2->mask; + ptr1->mode = ptr2->mode; +} + +// A generic helper that does most of the work of the watch/breakpoint commands +void genericBreakpoint(char *params, char *type, breakpoint_t *list, unsigned int mode) { + int i = 0; + unsigned int addr; + unsigned int mask = 0xFFFFFFFF; + sscanf(params, "%x %x", &addr, &mask); + + while (list[i].mode != MODE_LAST) { + if (list[i].addr == addr) { + setBreakpoint(list + i, type, addr, mask, mode); + return; + } + i++; + } + + if (i == MAXBKPTS) { + printf("All %d %s Breakpoints are already set\r\n", i, type); + return; + } + // Extending the list, so add a new end marker + list[i + 1].mode = MODE_LAST; + while (i >= 0) { + if (i == 0 || list[i - 1].addr < addr) { + setBreakpoint(list + i, type, addr, mask, mode); + return; + } else { + copyBreakpoint(list + i, list + i - 1); + } + i--; + } +} /******************************************* * User Commands @@ -112,12 +326,12 @@ void doCmdDis(char *params) { static void doCmdFill(char *params) { cpu_debug_t *cpu = getCpu(); - long i; + unsigned int i; unsigned int start; unsigned int end; unsigned int data; sscanf(params, "%x %x %x", &start, &end, &data); - + printf("Wr: %04X to %04X = %02X\r\n", start, end, data); for (i = start; i <= end; i++) { cpu->memwrite(i, data); @@ -126,8 +340,8 @@ static void doCmdFill(char *params) { static void doCmdCrc(char *params) { cpu_debug_t *cpu = getCpu(); - long i; - int j; + unsigned int i; + unsigned int j; unsigned int start; unsigned int end; unsigned int data; @@ -190,6 +404,152 @@ void doCmdWriteMem(char *params) { cpu->memwrite(addr++, data); } + +void doCmdStep(char *params) { + int i = 1; + sscanf(params, "%d", &i); + if (i <= 0) { + printf("Number of instuctions must be positive\r\n"); + return; + } + stepping = i; + step_counter = 0; + if (stepping) { + printf("Stepping %d instructions\r\n", i); + } else { + printf("Stepping disabled\r\n"); + } + cpu_continue(); +} + +void doCmdTrace(char *params) { + int i = 1; + sscanf(params, "%d", &i); + if (i <= 0) { + printf("Number of instuctions must be positive\r\n"); + return; + } + tracing = i; + trace_counter = 0; + if (tracing) { + printf("Tracing every %d instructions\r\n", tracing); + } else { + printf("Tracing disabled\r\n"); + } +} + +void genericList(char *type, breakpoint_t *list) { + int i = 0; + printf("%s Breakpoints\r\n", type); + while (list[i].mode != MODE_LAST) { + printf(" addr:%"PRIx32" mask: %"PRIx32" mode:%s\r\n", list[i].addr, list[i].mask, modeStrings[list[i].mode]); + i++; + } + if (i == 0) { + printf(" none\r\n"); + } +} + +void doCmdList(char *params) { + genericList("Exec", exec_breakpoints); + genericList("Mem Rd", mem_rd_breakpoints); + genericList("Mem Wr", mem_wr_breakpoints); +} + +void doCmdBreakI(char *params) { + genericBreakpoint(params, "Exec", exec_breakpoints, MODE_BREAK); +} + +void doCmdWatchI(char *params) { + genericBreakpoint(params, "Exec", exec_breakpoints, MODE_WATCH); +} + +void doCmdBreakRdMem(char *params) { + genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_BREAK); +} + +void doCmdWatchRdMem(char *params) { + genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_WATCH); +} + +void doCmdBreakWrMem(char *params) { + genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_BREAK); +} + +void doCmdWatchWrMem(char *params) { + genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_WATCH); +} + + +int genericClear(uint32_t addr, char *type, breakpoint_t *list) { + + int i = 0; + + // Assume addr is an address, and try to map to an index + while (list[i].mode != MODE_LAST) { + if (list[i].addr == addr) { + break; + } + i++; + } + if (list[i].mode == MODE_LAST) { + if (addr < i) { + i = addr; + } else { + i = -1; + } + } + if (i >= 0) { + printf("Removed %s breakpoint at %"PRIx32"\r\n", type, list[i].addr); + do { + copyBreakpoint(list + i, list + i + 1); + i++; + } while (list[i - 1].mode != MODE_LAST); + return 1; + } + return 0; +} + + +void doCmdClear(char *params) { + int found = 0; + unsigned int addr = 0; + + sscanf(params, "%x", &addr); + found |= genericClear(addr, "Exec", exec_breakpoints); + found |= genericClear(addr, "Mem Rd", mem_rd_breakpoints); + found |= genericClear(addr, "Mem Wr", mem_wr_breakpoints); + if (!found) { + printf("No breakpoints set at %x\r\n", addr); + } +} + +void doCmdContinue(char *params) { + stepping = 0; + cpu_continue(); +} + + +void updateDebugFlag() { + cpu_debug_t *cpu = getCpu(); + int enable = 0; + if (stepping) { + enable = 1; + } + if (exec_breakpoints[0].mode != MODE_LAST) { + enable = 1; + } + if (mem_rd_breakpoints[0].mode != MODE_LAST) { + enable = 1; + } + if (mem_wr_breakpoints[0].mode != MODE_LAST) { + enable = 1; + } + if (cpu->debug_enable(enable) != enable) { + printf("cpu: %s debug enable = %d\r\n", cpu->cpu_name, enable); + } +} + /******************************************************** * User Command Processor ********************************************************/ @@ -209,6 +569,7 @@ static void dispatchCmd(char *cmd) { minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; if (strncmp(cmdString, cmd, minLen) == 0) { (*dbgCmdFuncs[i])(cmd + cmdLen); + updateDebugFlag(); return; } } @@ -231,16 +592,12 @@ void debugger_rx_char(char c) { } } else if (c == 13) { // Handle return - if (i == 0) { - while (cmd[i]) { - RPI_AuxMiniUartWrite(cmd[i++]); - } - } else { - cmd[i] = 0; - } RPI_AuxMiniUartWrite(10); RPI_AuxMiniUartWrite(13); - dispatchCmd(cmd); + if (i > 0) { + cmd[i] = 0; + dispatchCmd(cmd); + } RPI_AuxMiniUartWrite('>'); RPI_AuxMiniUartWrite('>'); RPI_AuxMiniUartWrite(' '); @@ -251,4 +608,3 @@ void debugger_rx_char(char c) { cmd[i++] = c; } } - From 6de82f150fa9c83ca89119fd8cdaf46d1c7a2269 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 17:23:31 +0000 Subject: [PATCH 023/149] 32016: Tweak to disassebler to show correct opcode bytes Change-Id: Ifacf43c0809615dba3751b5a76b538880f2d8635 --- src/NS32016/NSDis.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/NS32016/NSDis.c b/src/NS32016/NSDis.c index b1fb2b7a..4f42a3e4 100644 --- a/src/NS32016/NSDis.c +++ b/src/NS32016/NSDis.c @@ -14,6 +14,8 @@ #define HEX24 "x'%06" PRIX32 #define HEX32 "x'%" PRIX32 +#define MAX_INSTR_SIZE 8 + // #define ADD_ASCII static inline uint32_t read_x32_internal(uint32_t addr) { @@ -451,6 +453,7 @@ static void AddASCII(uint32_t opcode, uint32_t Format) void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, uint32_t Function, OperandSizeType *OperandSize) { + int i; static uint32_t old_pc = 0xFFFFFFFF; if (StartPc < (IO_BASE - 64)) // The code will not work near the IO Space as it will have side effects @@ -474,7 +477,11 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u old_pc = StartPc; StringAppend("&%06" PRIX32 " ", StartPc); - StringAppend("[%08" PRIX32 "] ", opcode); + StringAppend("["); + for (i = 0; i < MAX_INSTR_SIZE; i++) { + StringAppend("%02x", read_x8_internal(StartPc + i)); + } + StringAppend("] "); uint32_t Format = Function >> 4; StringAppend("F%01" PRIu32 " ", Format); #ifdef ADD_ASCII @@ -832,8 +839,16 @@ static void Decode(uint32_t* pPC) uint32_t n32016_disassemble(uint32_t addr, char *buf, size_t bufsize) { + int i; + uint32_t old = addr; + int len; StringInit(buf, bufsize); Decode(&addr); + len = addr - old; + // Nuke the op bytes that are part of next instruction + for (i = 9 + len * 2; i < 9 + MAX_INSTR_SIZE * 2 && i < bufsize - 1; i++) { + buf[i] = ' '; + } //ShowTraps(); //CLEAR_TRAP(); return addr; From cef54fe87a5cadc29e4ba5c1d825d12236e6455c Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 17:43:42 +0000 Subject: [PATCH 024/149] Debugger: added get_instr_addr() to cpu_debug_t Change-Id: I958cda5c2253ef2726eb3144a0c412d0a374ea9e --- src/NS32016/32016.c | 5 ++++ src/NS32016/32016.h | 1 + src/NS32016/debug.c | 61 +++++++++++++++-------------------------- src/cpu_debug.h | 2 ++ src/debugger/debugger.c | 6 ++-- 5 files changed, 33 insertions(+), 42 deletions(-) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index b0fb5247..2c2732ca 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -118,6 +118,11 @@ uint32_t n32016_get_pc() return pc; } +uint32_t n32016_get_startpc() +{ + return startpc; +} + void n32016_set_pc(uint32_t value) { pc = value; diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 6098ad55..58ce038c 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -333,6 +333,7 @@ extern void n32016_exec(); extern void n32016_close(); extern void n32016_build_matrix(); extern uint32_t n32016_get_pc(); +extern uint32_t n32016_get_startpc(); extern void n32016_set_pc(uint32_t value); extern void BreakPoint(uint32_t pc, uint32_t opcode); extern int32_t GetDisplacement(uint32_t* pPC); diff --git a/src/NS32016/debug.c b/src/NS32016/debug.c index a5b409c6..19964580 100644 --- a/src/NS32016/debug.c +++ b/src/NS32016/debug.c @@ -59,31 +59,30 @@ static const char *dbg_reg_names[] = { // enable/disable debugging on this CPU, returns previous value. -int dbg_debug_enable(int newvalue) { +static int dbg_debug_enable(int newvalue) { int oldvalue = n32016_debug_enabled; n32016_debug_enabled = newvalue; return oldvalue; }; // CPU's usual memory read function for data. -uint32_t dbg_memread(uint32_t addr) { +static uint32_t dbg_memread(uint32_t addr) { // use the internal version so the debugger doesn't get notified return read_x8_internal(addr); }; // CPU's usual memory write function. -void dbg_memwrite(uint32_t addr, uint32_t value) { +static void dbg_memwrite(uint32_t addr, uint32_t value) { // use the internal version so the debugger doesn't get notified write_x8_internal(addr, value); }; - -uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { return n32016_disassemble(addr, buf, bufsize); }; // Get a register - which is the index into the names above -uint32_t dbg_reg_get(int which) { +static uint32_t dbg_reg_get(int which) { switch (which) { case i_PC: return n32016_get_pc(); @@ -118,7 +117,7 @@ uint32_t dbg_reg_get(int which) { }; // Set a register. -void dbg_reg_set(int which, uint32_t value) { +static void dbg_reg_set(int which, uint32_t value) { switch (which) { case i_PC: n32016_set_pc(value); @@ -165,7 +164,7 @@ void dbg_reg_set(int which, uint32_t value) { static const char* flagname = "****IPSUNZFV*LTC"; // Print register value in CPU standard form. -size_t dbg_reg_print(int which, char *buf, size_t bufsize) { +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { int i; int bit; char c; @@ -204,43 +203,27 @@ size_t dbg_reg_print(int which, char *buf, size_t bufsize) { }; // Parse a value into a register. -void dbg_reg_parse(int which, char *strval) { +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 n32016_get_startpc(); +} cpu_debug_t n32016_cpu_debug = { - .cpu_name = "32016", - .debug_enable = dbg_debug_enable, - .memread = dbg_memread, - .memwrite = dbg_memwrite, - .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 + .cpu_name = "32016", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .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 }; -#if 0 - -// Name/model of CPU. -static const char *dbg_cpu_name = "32016"; - -cpu_debug_t *n32016_cpu_debug() -{ - cpu_debug.cpu_name = dbg_cpu_name; - cpu_debug.debug_enable = dbg_debug_enable; - cpu_debug.memread = dbg_memread; - cpu_debug.memwrite = dbg_memwrite; - cpu_debug.disassemble = dbg_disassemble; - cpu_debug.reg_names = dbg_reg_names; - cpu_debug.reg_get = dbg_reg_get; - cpu_debug.reg_set = dbg_reg_set; - cpu_debug.reg_print = dbg_reg_print; - cpu_debug.reg_parse = dbg_reg_parse; - return &cpu_debug; -} -#endif diff --git a/src/cpu_debug.h b/src/cpu_debug.h index 96c3a2eb..bea6738f 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -20,6 +20,8 @@ typedef struct { void (*reg_set)(int which, uint32_t value); // Set a register. size_t (*reg_print)(int which, char *buf, size_t bufsize); // Print register value in CPU standard form. 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 + } 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 a595e5a0..494c2252 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -186,12 +186,12 @@ static inline void generic_memory_access(cpu_debug_t *cpu, uint32_t addr, uint32 const char *type, breakpoint_t *list) { breakpoint_t *ptr = check_for_breakpoints(addr, list); if (ptr) { - uint32_t pc = cpu->reg_get(DBG_REG_PC); + uint32_t pc = cpu->get_instr_addr(); if (ptr->mode == MODE_BREAK) { - printf("%s breakpoint hit at %"PRIx32" : %"PRIX32" = %"PRIX32"\r\n", type, pc, addr, value); + printf("%s breakpoint hit at %"PRIx32" : %"PRIx32" = %"PRIx32"\r\n", type, pc, addr, value); disassemble_addr(pc); } else { - printf("%s watchpoint hit at %"PRIx32" : %"PRIX32" = %"PRIX32"\r\n", type, pc, addr, value); + printf("%s watchpoint hit at %"PRIx32" : %"PRIx32" = %"PRIx32"\r\n", type, pc, addr, value); } } } From 2428f1ada922499202b0f87c7ff009b080385503 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 18:52:53 +0000 Subject: [PATCH 025/149] Debugger: improvement to console prompt Change-Id: I3581249554c4819d87c30f39699f14d19a9779c4 --- src/debugger/debugger.c | 74 +++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 494c2252..50497e0c 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -124,7 +124,7 @@ static volatile int stopped = 0; // When single stepping, trace (i.e. log) event N instructions // Setting this to 0 will disable logging -static int tracing = 0; +static int tracing = 1; static int trace_counter = 0; @@ -146,6 +146,16 @@ cpu_debug_t *getCpu() { * Hooks from CPU Emulation ********************************************************/ +static void noprompt() { + RPI_AuxMiniUartWrite(13); +} + +static void prompt() { + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite('>'); + RPI_AuxMiniUartWrite(' '); +} + static void cpu_stop() { // if (!stopped) { // printf("Stopped\r\n"); @@ -163,7 +173,9 @@ static void cpu_continue() { static void disassemble_addr(uint32_t addr) { cpu_debug_t *cpu = getCpu(); cpu->disassemble(addr, strbuf, sizeof(strbuf)); + noprompt(); printf("%s\r\n", &strbuf[0]); + prompt(); } @@ -188,11 +200,16 @@ static inline void generic_memory_access(cpu_debug_t *cpu, uint32_t addr, uint32 if (ptr) { uint32_t pc = cpu->get_instr_addr(); if (ptr->mode == MODE_BREAK) { + noprompt(); printf("%s breakpoint hit at %"PRIx32" : %"PRIx32" = %"PRIx32"\r\n", type, pc, addr, value); + prompt(); disassemble_addr(pc); } else { + noprompt(); printf("%s watchpoint hit at %"PRIx32" : %"PRIx32" = %"PRIx32"\r\n", type, pc, addr, value); + prompt(); } + prompt(); } } @@ -211,11 +228,15 @@ void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { if (ptr) { if (ptr->mode == MODE_BREAK) { + noprompt(); printf("Exec breakpoint hit at %"PRIx32"\r\n", addr); + prompt(); show = 1; } else { + noprompt(); printf("Exec watchpoint hit at %"PRIx32"\r\n", addr); + prompt(); } } @@ -302,7 +323,7 @@ static void doCmdHelp(char *params) { } } -void doCmdRegs(char *params) { +static void doCmdRegs(char *params) { cpu_debug_t *cpu = getCpu(); const char **regs = cpu->reg_names; int i = 0; @@ -314,7 +335,7 @@ void doCmdRegs(char *params) { } } -void doCmdDis(char *params) { +static void doCmdDis(char *params) { cpu_debug_t *cpu = getCpu(); int i; sscanf(params, "%x", &memAddr); @@ -386,7 +407,7 @@ static void doCmdMem(char *params) { memAddr += 0x100; } -void doCmdReadMem(char *params) { +static void doCmdReadMem(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -395,7 +416,7 @@ void doCmdReadMem(char *params) { printf("Rd: %04X = %02X\r\n", addr, data); } -void doCmdWriteMem(char *params) { +static void doCmdWriteMem(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -405,7 +426,7 @@ void doCmdWriteMem(char *params) { } -void doCmdStep(char *params) { +static void doCmdStep(char *params) { int i = 1; sscanf(params, "%d", &i); if (i <= 0) { @@ -422,7 +443,7 @@ void doCmdStep(char *params) { cpu_continue(); } -void doCmdTrace(char *params) { +static void doCmdTrace(char *params) { int i = 1; sscanf(params, "%d", &i); if (i <= 0) { @@ -438,7 +459,7 @@ void doCmdTrace(char *params) { } } -void genericList(char *type, breakpoint_t *list) { +static void genericList(char *type, breakpoint_t *list) { int i = 0; printf("%s Breakpoints\r\n", type); while (list[i].mode != MODE_LAST) { @@ -450,33 +471,33 @@ void genericList(char *type, breakpoint_t *list) { } } -void doCmdList(char *params) { +static void doCmdList(char *params) { genericList("Exec", exec_breakpoints); genericList("Mem Rd", mem_rd_breakpoints); genericList("Mem Wr", mem_wr_breakpoints); } -void doCmdBreakI(char *params) { +static void doCmdBreakI(char *params) { genericBreakpoint(params, "Exec", exec_breakpoints, MODE_BREAK); } -void doCmdWatchI(char *params) { +static void doCmdWatchI(char *params) { genericBreakpoint(params, "Exec", exec_breakpoints, MODE_WATCH); } -void doCmdBreakRdMem(char *params) { +static void doCmdBreakRdMem(char *params) { genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_BREAK); } -void doCmdWatchRdMem(char *params) { +static void doCmdWatchRdMem(char *params) { genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_WATCH); } -void doCmdBreakWrMem(char *params) { +static void doCmdBreakWrMem(char *params) { genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_BREAK); } -void doCmdWatchWrMem(char *params) { +static void doCmdWatchWrMem(char *params) { genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_WATCH); } @@ -511,7 +532,7 @@ int genericClear(uint32_t addr, char *type, breakpoint_t *list) { } -void doCmdClear(char *params) { +static void doCmdClear(char *params) { int found = 0; unsigned int addr = 0; @@ -524,13 +545,14 @@ void doCmdClear(char *params) { } } -void doCmdContinue(char *params) { +static void doCmdContinue(char *params) { stepping = 0; + printf("Running\r\n"); cpu_continue(); } -void updateDebugFlag() { +static void updateDebugFlag() { cpu_debug_t *cpu = getCpu(); int enable = 0; if (stepping) { @@ -592,15 +614,17 @@ void debugger_rx_char(char c) { } } else if (c == 13) { // Handle return + if (i == 0) { + while (cmd[i]) { + RPI_AuxMiniUartWrite(cmd[i++]); + } + } else { + cmd[i] = 0; + } RPI_AuxMiniUartWrite(10); RPI_AuxMiniUartWrite(13); - if (i > 0) { - cmd[i] = 0; - dispatchCmd(cmd); - } - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite(' '); + dispatchCmd(cmd); + prompt(); i = 0; } else if (c >= 32) { // Handle any other non-control character From eda5204e70ee7a22f848fcb4595d2d3dfcd53e98 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 15 Mar 2017 19:06:27 +0000 Subject: [PATCH 026/149] Debugger: minor output formatting Change-Id: I4865707743d800eacf896e4c23b6ab14b27d4e49 --- src/debugger/debugger.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 50497e0c..99661b1f 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -26,8 +26,8 @@ // Breakpoint Mode Strings, should match the modes above static const char *modeStrings[NUM_MODES] = { "", - "Watch", - "Break" + "watchpoint", + "breakpoint" }; typedef struct { @@ -265,7 +265,7 @@ void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { // Set the breakpoint state variables void setBreakpoint(breakpoint_t *ptr, char *type, unsigned int addr, unsigned int mask, unsigned int mode) { - printf("%s %s set at %04X\r\n", type, modeStrings[mode], addr); + printf("%s %s set at %x\r\n", type, modeStrings[mode], addr); ptr->addr = addr & mask; ptr->mask = mask; ptr->mode = mode; @@ -293,7 +293,7 @@ void genericBreakpoint(char *params, char *type, breakpoint_t *list, unsigned in } if (i == MAXBKPTS) { - printf("All %d %s Breakpoints are already set\r\n", i, type); + printf("All %d %s breakpoints are already set\r\n", i, type); return; } // Extending the list, so add a new end marker @@ -316,7 +316,8 @@ void genericBreakpoint(char *params, char *type, breakpoint_t *list, unsigned in static void doCmdHelp(char *params) { cpu_debug_t *cpu = getCpu(); int i; - printf("PiTubeDirect debugger; cpu = %s\r\n", cpu->cpu_name); + printf("PiTubeDirect debugger\r\n"); + printf(" cpu = %s\r\n", cpu->cpu_name); printf("Commands:\r\n"); for (i = 0; i < NUM_CMDS; i++) { printf(" %s\r\n", dbgCmdStrings[i]); @@ -353,7 +354,7 @@ static void doCmdFill(char *params) { unsigned int data; sscanf(params, "%x %x %x", &start, &end, &data); - printf("Wr: %04X to %04X = %02X\r\n", start, end, data); + printf("Wr: %x to %x = %02x\r\n", start, end, data); for (i = start; i <= end; i++) { cpu->memwrite(i, data); } @@ -378,7 +379,7 @@ static void doCmdCrc(char *params) { crc = (crc ^ CRC_POLY) & 0xFFFF; } } - printf("crc: %04X\r\n", crc); + printf("crc: %04x\r\n", crc); } static void doCmdMem(char *params) { @@ -390,9 +391,9 @@ static void doCmdMem(char *params) { for (j = 0; j < 16; j++) { row[j] = cpu->memread(memAddr + i + j); } - printf("%04X ", memAddr + i); + printf("%04x ", memAddr + i); for (j = 0; j < 16; j++) { - printf("%02X ", row[j]); + printf("%02x ", row[j]); } printf(" "); for (j = 0; j < 16; j++) { @@ -413,7 +414,7 @@ static void doCmdReadMem(char *params) { unsigned int data; sscanf(params, "%x", &addr); data = cpu->memread(addr); - printf("Rd: %04X = %02X\r\n", addr, data); + printf("Rd: %x = %02x\r\n", addr, data); } static void doCmdWriteMem(char *params) { @@ -421,7 +422,7 @@ static void doCmdWriteMem(char *params) { unsigned int addr; unsigned int data; sscanf(params, "%x %x", &addr, &data); - printf("Wr: %04X = %02X\r\n", addr, data); + printf("Wr: %x = %02x\r\n", addr, data); cpu->memwrite(addr++, data); } @@ -461,9 +462,9 @@ static void doCmdTrace(char *params) { static void genericList(char *type, breakpoint_t *list) { int i = 0; - printf("%s Breakpoints\r\n", type); + printf("%s\r\n", type); while (list[i].mode != MODE_LAST) { - printf(" addr:%"PRIx32" mask: %"PRIx32" mode:%s\r\n", list[i].addr, list[i].mask, modeStrings[list[i].mode]); + printf(" addr:%"PRIx32"; mask:%"PRIx32"; type:%s\r\n", list[i].addr, list[i].mask, modeStrings[list[i].mode]); i++; } if (i == 0) { From 6e4d30b2cc2a05c16be3f09b2692b66e2d1050a6 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 16 Mar 2017 19:10:37 +0000 Subject: [PATCH 027/149] ARM2: Added debugger support (no memory hooks yet) Change-Id: I2768e5914e916da805010890e53088595c26fe22 --- src/CMakeLists.txt | 2 + src/cpu_debug.h | 3 - src/debugger/debugger.c | 13 ++- src/mame/arm.c | 11 ++ src/mame/arm.h | 2 + src/mame/debug.c | 216 ++++++++++++++++++++++++++++++++++++++++ src/mame/debug.h | 6 ++ 7 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 src/mame/debug.c create mode 100644 src/mame/debug.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1fddad1..adcd97c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -131,6 +131,8 @@ file( GLOB copro_arm2_files tuberom_arm.h mame/arm.c mame/arm.h + mame/debug.c + mame/debug.h ) # 32016 diff --git a/src/cpu_debug.h b/src/cpu_debug.h index bea6738f..094b758a 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -6,9 +6,6 @@ #include #include -// Register 0 must be the program counter -#define DBG_REG_PC 0 - typedef struct { const char *cpu_name; // Name/model of CPU. int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 99661b1f..1efb2d53 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -137,9 +137,14 @@ static unsigned int memAddr = 0; // TODO - Fix hardcoded implementation -extern cpu_debug_t n32016_cpu_debug; +//extern cpu_debug_t n32016_cpu_debug; +//cpu_debug_t *getCpu() { +// return &n32016_cpu_debug; +//} + +extern cpu_debug_t arm2_cpu_debug; cpu_debug_t *getCpu() { - return &n32016_cpu_debug; + return &arm2_cpu_debug; } /******************************************************** @@ -447,8 +452,8 @@ static void doCmdStep(char *params) { static void doCmdTrace(char *params) { int i = 1; sscanf(params, "%d", &i); - if (i <= 0) { - printf("Number of instuctions must be positive\r\n"); + if (i < 0) { + printf("Number of instuctions must be positive or zero\r\n"); return; } tracing = i; diff --git a/src/mame/arm.c b/src/mame/arm.c index e9297ea1..e3e3bb66 100644 --- a/src/mame/arm.c +++ b/src/mame/arm.c @@ -30,6 +30,11 @@ darm_str_t str; int m_trace; #endif +#ifdef INCLUDE_DEBUGGER +#include "debug.h" +#include "../cpu_debug.h" +#endif + //int m_icount; #define CYCLE_COUNT(in) @@ -278,6 +283,12 @@ void arm2_execute_run(int number) /* load instruction */ pc = R15; +#ifdef INCLUDE_DEBUGGER + if (arm2_debug_enabled) + { + debug_preexec(&arm2_cpu_debug, pc & ADDRESS_MASK); + } +#endif insn = cpu_read32( pc & ADDRESS_MASK ); #ifdef TRACE diff --git a/src/mame/arm.h b/src/mame/arm.h index f0d66f42..75088f77 100644 --- a/src/mame/arm.h +++ b/src/mame/arm.h @@ -14,6 +14,8 @@ extern UINT32 copro_arm2_read32(int addr); extern void copro_arm2_write8(int addr, UINT8 data); extern void copro_arm2_write32(int addr, UINT32 data); +extern UINT32 m_sArmRegister[]; + #define cpu_read8 copro_arm2_read8 #define cpu_read32 copro_arm2_read32 #define cpu_write8 copro_arm2_write8 diff --git a/src/mame/debug.c b/src/mame/debug.c new file mode 100644 index 00000000..a1905bad --- /dev/null +++ b/src/mame/debug.c @@ -0,0 +1,216 @@ + #include +#include +#include +#include + +#include "arm.h" +#include "../darm/darm.h" +#include "debug.h" +#include "../cpu_debug.h" + +#define ADDRESS_MASK ((UINT32) 0x03fffffcu) + +static darm_t dis; +static darm_str_t dis_str; + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +int arm2_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_SP, + i_LR, + i_PC, + i_R8_fiq, + i_R9_fiq, + i_R10_fiq, + i_R11_fiq, + i_R12_fiq, + i_SP_fiq, + i_LR_fiq, + i_SP_irq, + i_LR_irq, + i_SP_svc, + i_LR_svc, + i_PSR +}; + +// 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", + "SP", + "LR", + "PC", + "R8_fiq", + "R9_fiq", + "R10_fiq", + "R11_fiq", + "R12_fiq", + "SP_fiq", + "LR_fiq", + "SP_irq", + "LR_irq", + "SP_svc", + "LR_svc", + "PSR", + NULL +}; + +// enable/disable debugging on this CPU, returns previous value. +static int dbg_debug_enable(int newvalue) { + int oldvalue = arm2_debug_enabled; + arm2_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_memread(uint32_t addr) { + // TODO: use the internal version so the debugger doesn't get notified + return copro_arm2_read8(addr); +}; + +// CPU's usual memory write function. +static void dbg_memwrite(uint32_t addr, uint32_t value) { + // TODO: use the internal version so the debugger doesn't get notified + copro_arm2_write8(addr, value); +}; + +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + uint32_t instr = copro_arm2_read32(addr); + int len = snprintf(buf, bufsize, "%08"PRIx32" %08"PRIx32" ", addr, instr); + buf += len; + bufsize -= len; + if(darm_armv7_disasm(&dis, instr) == 0 && darm_str2(&dis, &dis_str, 0) == 0) { + strncpy(buf, dis_str.total, bufsize); + } else { + strncpy(buf, "???", bufsize); + } + return addr + 4; +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + if (which == i_PC) { + return m_sArmRegister[i_PC] & ADDRESS_MASK; + } else if (which == i_PSR) { + return ((m_sArmRegister[i_PC] >> 24) & 0xFC) | (m_sArmRegister[i_PC] & 0x03); + } else { + return m_sArmRegister[which]; + } +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + if (which == i_PC) { + m_sArmRegister[i_PC] &= ~ADDRESS_MASK; + m_sArmRegister[i_PC] |= (value & ADDRESS_MASK); + } else if (which == i_PSR) { + m_sArmRegister[i_PC] &= ADDRESS_MASK; + m_sArmRegister[i_PC] |= ((value & 0xFC) << 24) | (value & 0x03); + } else { + m_sArmRegister[which] = value; + } +}; + +static const char* flagname = "N Z C V I F M1 M0 "; + +// 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); + } + + bit = 0x80; + for (i = 0; i < 8; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + switch (psr & 3) { + case 0: + sprintf(buf, "(USR)"); + break; + case 1: + sprintf(buf, "(FIQ)"); + break; + case 2: + sprintf(buf, "(IRQ)"); + break; + case 3: + sprintf(buf, "(SVC)"); + break; + } + return strlen(buf); + } else { + return snprintf(buf, bufsize, "%08"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_sArmRegister[i_PC]; +} + +cpu_debug_t arm2_cpu_debug = { + .cpu_name = "ARM2", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .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 +}; diff --git a/src/mame/debug.h b/src/mame/debug.h new file mode 100644 index 00000000..3139ff53 --- /dev/null +++ b/src/mame/debug.h @@ -0,0 +1,6 @@ +#include "../cpu_debug.h" + +extern int arm2_debug_enabled; + +extern cpu_debug_t arm2_cpu_debug; + From 0dc61e58680f81e557e7dfbf7233d020c4f08c94 Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 13:13:17 +0000 Subject: [PATCH 028/149] Debugger: added a table of cpu_debug_t Change-Id: I9acb03899e6e6cb773907f0917e4231174ec7554 --- src/debugger/debugger.c | 42 +++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 1efb2d53..60110ffe 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -7,6 +7,30 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" +#include "../mame/debug.h" +#include "../NS32016/debug.h" + +extern unsigned int copro; + +cpu_debug_t *cpu_debug_list[] = { + NULL, // 0 65tube + NULL, // 1 65tube + NULL, // 2 lib6502 + NULL, // 3 lib6502 + NULL, // 4 Z80 + NULL, // 5 Z80 + NULL, // 4 Z80 + NULL, // 7 Z80 + NULL, // 8 80x86 + NULL, // 9 6809 + NULL, // 10 unused + NULL, // 11 unused + &arm2_cpu_debug, // 12 ARM2 + &n32016_cpu_debug, // 13 32016 + NULL, // 14 unsed + NULL, // 15 Native ARM +}; + #define NUM_CMDS 19 // The Atom CRC Polynomial @@ -135,16 +159,9 @@ static int step_counter; // The current memory address (e.g. used when disassembling) static unsigned int memAddr = 0; - -// TODO - Fix hardcoded implementation -//extern cpu_debug_t n32016_cpu_debug; -//cpu_debug_t *getCpu() { -// return &n32016_cpu_debug; -//} - extern cpu_debug_t arm2_cpu_debug; cpu_debug_t *getCpu() { - return &arm2_cpu_debug; + return cpu_debug_list[copro]; } /******************************************************** @@ -596,8 +613,13 @@ static void dispatchCmd(char *cmd) { cmdStringLen = strlen(cmdString); minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; if (strncmp(cmdString, cmd, minLen) == 0) { - (*dbgCmdFuncs[i])(cmd + cmdLen); - updateDebugFlag(); + cpu_debug_t *cpu = getCpu(); + if (cpu == NULL) { + printf("No debugger available for this co pro\r\n"); + } else { + (*dbgCmdFuncs[i])(cmd + cmdLen); + updateDebugFlag(); + } return; } } From 88068eea08b5e3af41228dc4ff10ad5f89d160bf Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 13:41:46 +0000 Subject: [PATCH 029/149] Debugger: extended regs command to allow read/write of single register Change-Id: Ie119a6d26429b8acbf39826fa0decf21c42c514f --- src/debugger/debugger.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 60110ffe..e3e201a8 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -348,13 +348,35 @@ static void doCmdHelp(char *params) { static void doCmdRegs(char *params) { cpu_debug_t *cpu = getCpu(); - const char **regs = cpu->reg_names; - int i = 0; - while (*regs) { - cpu->reg_print(i, strbuf, sizeof(strbuf)); - printf("%8s = %s\r\n", *regs, &strbuf[0]); - regs++; - i++; + const char **reg = cpu->reg_names; + char name[100]; + char value[100]; + int num_params = sscanf(params, "%s %s", name, value); + if (num_params > 0) { + int i = 0; + while (*reg) { + if (strcasecmp(name, *reg) == 0) { + if (num_params == 2) { + // Write the register + cpu->reg_parse(i, value); + } + // Read the register + cpu->reg_print(i, strbuf, sizeof(strbuf)); + printf("%8s = %s\r\n", *reg, &strbuf[0]); + return; + } + reg++; + i++; + } + printf("Register %s does not exist in the %s\r\n", strbuf, cpu->cpu_name); + } else { + int i = 0; + while (*reg) { + cpu->reg_print(i, strbuf, sizeof(strbuf)); + printf("%8s = %s\r\n", *reg, &strbuf[0]); + reg++; + i++; + } } } From 2d8f8ede072d3093056c95808828224bd19f0b37 Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 15:09:18 +0000 Subject: [PATCH 030/149] 32016 Co Pro: Fixed some compatibility issues with b-em Change-Id: I22d254fcd180c87fef7bd95532ead84bf4b38795 --- src/NS32016/mem32016.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index ec490a23..072d3da4 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -11,7 +11,6 @@ #include #include "32016.h" #include "mem32016.h" -#include "../tube-client.h" #ifdef INCLUDE_DEBUGGER #include "debug.h" @@ -19,9 +18,16 @@ #endif #ifdef BEM + #include "../tube.h" +static uint8_t ns32016ram[MEG16]; + #else + +#include "../tube-client.h" #include "../tube-ula.h" +static uint8_t * ns32016ram; + #endif #ifdef TEST_SUITE @@ -41,11 +47,11 @@ #define PANDORA_VERSION PandoraV2_00 #endif -static uint8_t * ns32016ram; - void init_ram(void) { +#ifndef BEM ns32016ram = copro_mem_reset(MEG16); +#endif #ifdef TEST_SUITE memcpy(ns32016ram, ROM, sizeof(ROM)); #elif defined(PANDORA_BASE) From d252cb927e82285c94f090cc5faa51590509cad6 Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 17:10:01 +0000 Subject: [PATCH 031/149] 32016: Updated to use a common logging interface with B-Em Change-Id: Ied8754ca79db893d80624f598a90fab2e61aedc9 --- src/CMakeLists.txt | 2 ++ src/NS32016/32016.c | 78 +++++++++++++++++++++++++----------------- src/NS32016/32016.h | 21 ++++++------ src/NS32016/Decode.c | 4 +-- src/NS32016/NSDis.c | 37 +++++++++++--------- src/NS32016/Trap.c | 9 ++--- src/NS32016/Trap.h | 2 +- src/NS32016/mem32016.c | 10 +++--- src/logging.c | 50 +++++++++++++++++++++++++++ src/logging.h | 20 +++++++++++ 10 files changed, 159 insertions(+), 74 deletions(-) create mode 100644 src/logging.c create mode 100644 src/logging.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index adcd97c2..cc549257 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,6 +86,8 @@ file( GLOB core_files performance.h tubevc.c tubevc.h + logging.c + logging.h ) # 6502 Co Processor using 65tube Implementation diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index 2c2732ca..67e6b8d8 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -2,10 +2,11 @@ // 32016 parasite processor emulation (not working yet) // And Simon R. Ellwood -#include -#include #include #include +#include +#include +#include #include #include #include "32016.h" @@ -44,32 +45,45 @@ OperandSizeType OpSize; const uint32_t IndexLKUP[8] = { 0x0, 0x1, 0x4, 0x5, 0x8, 0x9, 0xC, 0xD }; // See Page 2-3 of the manual! +/* A custom warning logger for n32016 that logs the PC */ + +void n32016_warn(char *fmt, ...) +{ + char buf[1024]; + int len = snprintf(buf, sizeof(buf), "[pc=%"PRIX32"] ", pc); + va_list ap; + va_start(ap, fmt); + vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); + va_end(ap); + log_warn("%s", buf); +} + void n32016_ShowRegs(int Option) { if (Option & BIT(0)) { - TrapTRACE("R0=%08"PRIX32" R1=%08"PRIX32" R2=%08"PRIX32" R3=%08"PRIX32"\n", r[0], r[1], r[2], r[3]); - TrapTRACE("R4=%08"PRIX32" R5=%08"PRIX32" R6=%08"PRIX32" R7=%08"PRIX32"\n", r[4], r[5], r[6], r[7]); + TrapTRACE("R0=%08"PRIX32" R1=%08"PRIX32" R2=%08"PRIX32" R3=%08"PRIX32, r[0], r[1], r[2], r[3]); + TrapTRACE("R4=%08"PRIX32" R5=%08"PRIX32" R6=%08"PRIX32" R7=%08"PRIX32, r[4], r[5], r[6], r[7]); } if (Option & BIT(1)) { - TrapTRACE("PC=%08"PRIX32" SB=%08"PRIX32" SP=%08"PRIX32" TRAP=%08"PRIX32"\n", pc, sb, GET_SP(), TrapFlags); - TrapTRACE("FP=%08"PRIX32" INTBASE=%08"PRIX32" PSR=%04"PRIX32" MOD=%04"PRIX32"\n", fp, intbase, psr, mod); + TrapTRACE("PC=%08"PRIX32" SB=%08"PRIX32" SP=%08"PRIX32" TRAP=%08"PRIX32, pc, sb, GET_SP(), TrapFlags); + TrapTRACE("FP=%08"PRIX32" INTBASE=%08"PRIX32" PSR=%04"PRIX32" MOD=%04"PRIX32, fp, intbase, psr, mod); } if (nscfg.fpu_flag) { if (Option & BIT(2)) { - TrapTRACE("F0=%f F1=%f F2=%f F3=%f\n", FR.fr32[0], FR.fr32[1], FR.fr32[4], FR.fr32[5]); - TrapTRACE("F4=%f F5=%f F6=%f F7=%f\n", FR.fr32[8], FR.fr32[9], FR.fr32[12], FR.fr32[13]); + TrapTRACE("F0=%f F1=%f F2=%f F3=%f", FR.fr32[0], FR.fr32[1], FR.fr32[4], FR.fr32[5]); + TrapTRACE("F4=%f F5=%f F6=%f F7=%f", FR.fr32[8], FR.fr32[9], FR.fr32[12], FR.fr32[13]); } if (Option & BIT(3)) { - TrapTRACE("D0=%lf D1=%lf D2=%lf D3=%lf\n", FR.fr64[0], FR.fr64[1], FR.fr64[2], FR.fr64[3]); - TrapTRACE("D4=%lf D5=%lf D6=%lf D7=%lf\n", FR.fr64[4], FR.fr64[5], FR.fr64[6], FR.fr64[7]); + TrapTRACE("D0=%lf D1=%lf D2=%lf D3=%lf", FR.fr64[0], FR.fr64[1], FR.fr64[2], FR.fr64[3]); + TrapTRACE("D4=%lf D5=%lf D6=%lf D7=%lf", FR.fr64[4], FR.fr64[5], FR.fr64[6], FR.fr64[7]); } } } @@ -371,7 +385,7 @@ static void GetGenPhase2(RegLKU gen, int c) default: { - PiWARN("Illegal RegType value: %u\n", gen.RegType) + PiWARN("Illegal RegType value: %u", gen.RegType); } } @@ -504,7 +518,7 @@ static void GetGenPhase2(RegLKU gen, int c) static uint32_t bcd_add_16(uint32_t a, uint32_t b, uint32_t *carry) { uint32_t t1, t2; // unsigned 32-bit intermediate values - //PiTRACE("bcd_add_16: in %08x %08x %08x\n", a, b, *carry); + //PiTRACE("bcd_add_16: in %08x %08x %08x", a, b, *carry); if (*carry) { b++; // I'm 90% sure its OK to handle carry this way @@ -518,14 +532,14 @@ static uint32_t bcd_add_16(uint32_t a, uint32_t b, uint32_t *carry) t2 = t1 - t2; // corrected BCD sum *carry = (t2 & 0xFFFF0000) ? 1 : 0; t2 &= 0xFFFF; - //PiTRACE("bcd_add_16: out %08x %08x\n", t2, *carry); + //PiTRACE("bcd_add_16: out %08x %08x", t2, *carry); return t2; } static uint32_t bcd_sub_16(uint32_t a, uint32_t b, uint32_t *carry) { uint32_t t1, t2; // unsigned 32-bit intermediate values - //PiTRACE("bcd_sub_16: in %08x %08x %08x\n", a, b, *carry); + //PiTRACE("bcd_sub_16: in %08x %08x %08x", a, b, *carry); if (*carry) { b++; @@ -535,7 +549,7 @@ static uint32_t bcd_sub_16(uint32_t a, uint32_t b, uint32_t *carry) t2 = bcd_add_16(t1, 1, carry); t2 = bcd_add_16(a, t2, carry); *carry = 1 - *carry; - //PiTRACE("bcd_add_16: out %08x %08x\n", t2, *carry); + //PiTRACE("bcd_add_16: out %08x %08x", t2, *carry); return t2; } @@ -590,7 +604,7 @@ static uint32_t AddCommon(uint32_t a, uint32_t b, uint32_t cin) C_FLAG = TEST(sum <= a || sum <= b); F_FLAG = TEST((a ^ sum) & (b ^ sum) & 0x80000000); - //PiTRACE("ADD FLAGS: C=%d F=%d\n", C_FLAG, F_FLAG); + //PiTRACE("ADD FLAGS: C=%d F=%d", C_FLAG, F_FLAG); return sum; } @@ -604,7 +618,7 @@ static uint32_t SubCommon(uint32_t a, uint32_t b, uint32_t cin) C_FLAG = TEST(a <= b); F_FLAG = TEST((a ^ b) & (a ^ diff) & 0x80000000); - //PiTRACE("SUB FLAGS: C=%d F=%d\n", C_FLAG, F_FLAG); + //PiTRACE("SUB FLAGS: C=%d F=%d", C_FLAG, F_FLAG); return diff; } @@ -943,7 +957,7 @@ void WarnIfShiftInvalid(uint32_t shift, uint8_t size) // of this in BBC Basic. if ((shift > size + 1 && shift < 0xFF - size - 1) || (shift > 0xFF)) { - PiWARN("Invalid shift of %08"PRIX32" for size %"PRId8"\n", shift, size); + PiWARN("Invalid shift of %08"PRIX32" for size %"PRId8, shift, size); } } @@ -1238,7 +1252,7 @@ void n32016_exec() default: { - PiWARN("Unexpected Format 9 Decode: Function = %"PRId32"\n", Function); + PiWARN("Unexpected Format 9 Decode: Function = %"PRId32, Function); } break; } @@ -1839,7 +1853,7 @@ void n32016_exec() temp2 = BitPrefix(); if (gentype[1] == TOS) { - PiWARN("TBIT with base==TOS is not yet implemented\n"); + PiWARN("TBIT with base==TOS is not yet implemented"); continue; // with next instruction } temp = ReadGen(1); @@ -2248,7 +2262,7 @@ void n32016_exec() temp3 = (GetDisplacement(&pc) / temp4) + 1; - //PiTRACE("CMP Size = %u Count = %u\n", temp4, temp3); + //PiTRACE("CMP Size = %u Count = %u", temp4, temp3); while (temp3--) { temp = read_n(First, temp4); @@ -2298,7 +2312,7 @@ void n32016_exec() if (gentype[0] == TOS) { - PiWARN("EXTS with base==TOS is not yet implemented\n"); + PiWARN("EXTS with base==TOS is not yet implemented"); continue; // with next instruction } @@ -2326,7 +2340,7 @@ void n32016_exec() { if (OpSize.Op[0] != sz8) { - PiWARN("MOVXiW forcing first Operand Size\n"); + PiWARN("MOVXiW forcing first Operand Size"); } OpSize.Op[0] = sz8; @@ -2340,7 +2354,7 @@ void n32016_exec() { if (OpSize.Op[0] != sz8) { - PiWARN("MOVZiW forcing first Operand Size\n"); + PiWARN("MOVZiW forcing first Operand Size"); } OpSize.Op[0] = sz8; @@ -2404,10 +2418,10 @@ void n32016_exec() temp64.u64 = ((temp64.u64 >> 16) & 0xFFFF0000) | (temp64.u64 & 0xFFFF); break; } - // PiTRACE("temp = %08x\n", temp); - // PiTRACE("temp64.u64 = %016" PRIu64 "\n", temp64.u64); + // PiTRACE("temp = %08x", temp); + // PiTRACE("temp64.u64 = %016" PRIu64 , temp64.u64); temp64.u64 = ((temp64.u64 / temp) << size) | (temp64.u64 % temp); - //PiTRACE("result = %016" PRIu64 "\n", temp64.u64); + //PiTRACE("result = %016" PRIu64 , temp64.u64); // Handle the writing to the upper half of dst locally here handle_mei_dei_upper_write(temp64.u64); // Allow fallthrough write logic to write the lower half of dst @@ -2504,7 +2518,7 @@ void n32016_exec() if (Length < 1 || Length > 32) { - PiWARN("EXT with length %08"PRIx32" is undefined\n", Length); + PiWARN("EXT with length %08"PRIX32" is undefined", Length); continue; // with next instruction } @@ -2518,7 +2532,7 @@ void n32016_exec() // // 2. We potentially need to take account of an offset. // - PiWARN("EXT with base==TOS is not yet implemented; offset = %"PRId32"\n", Offset); + PiWARN("EXT with base==TOS is not yet implemented; offset = %"PRId32, Offset); continue; // with next instruction } else if (gentype[0] == Register) @@ -2567,7 +2581,7 @@ void n32016_exec() if (Length < 1 || Length > 32) { - PiWARN("INS with length %08"PRIx32" is undefined\n", Length); + PiWARN("INS with length %08"PRIX32" is undefined", Length); continue; // with next instruction } @@ -2584,7 +2598,7 @@ void n32016_exec() // is harder as our current TOS read/write doesn't allow // for an offset. It's also not clear what this means. // - PiWARN("INS with base==TOS is not yet implemented; offset = %"PRId32"\n", Offset); + PiWARN("INS with base==TOS is not yet implemented; offset = %"PRId32, Offset); continue; // with next instruction } else if (gentype[1] == Register) @@ -3036,7 +3050,7 @@ void n32016_exec() } } } else { - PiWARN("Bad write size: %d pc=%08"PRIX32" opcode=%08"PRIX32"\n", WriteSize, startpc, opcode); + PiWARN("Bad write size: %d pc=%08"PRIX32" opcode=%08"PRIX32, WriteSize, startpc, opcode); } #if 0 diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 58ce038c..9008cdc0 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -1,3 +1,13 @@ +#include "../logging.h" + +/* A custom warning logger for n32016 that logs the PC */ +void n32016_warn(char * fmt, ...); + +#define PiTRACE(...) log_debug(__VA_ARGS__) + +#define PiWARN(...) n32016_warn(__VA_ARGS__) + + // Some meaningful memory sizes #define K128 0x0020000 #define K256 0x0040000 @@ -353,17 +363,6 @@ extern void ShowRegisterWrite(RegLKU RegIn, uint32_t Value); extern void CloseTrace(void); #endif -#ifdef TRACE_TO_FILE -#define PiTRACE(...) fprintf(pTraceFile, __VA_ARGS__) -extern FILE *pTraceFile; -#elif defined(TRACE_TO_CONSOLE) -#define PiTRACE printf -#else -static inline void PiTRACE(const char *fmt, ...) {} -#endif - -#define PiWARN(...) { printf("pc=%08"PRIX32": ",n32016_get_pc()); printf(__VA_ARGS__); } - extern int tubecycles; extern int tube_irq; extern uint32_t genaddr[2]; diff --git a/src/NS32016/Decode.c b/src/NS32016/Decode.c index a8566bd6..be19d9c3 100644 --- a/src/NS32016/Decode.c +++ b/src/NS32016/Decode.c @@ -90,13 +90,13 @@ void BreakPoint(uint32_t pc, uint32_t opcode) // Exec address of Bas32 if (pc == 0x000200) { - printf("Entering Bas32\n"); + log_debug("Entering Bas32"); ProfileInit(); } // Exec address of Panos if (pc == 0x000400) { - printf("Entering Panos\n"); + log_debug("Entering Panos"); ProfileInit(); } // Address of SVC &11 (OS_EXIT) diff --git a/src/NS32016/NSDis.c b/src/NS32016/NSDis.c index 4f42a3e4..d87ecfa3 100644 --- a/src/NS32016/NSDis.c +++ b/src/NS32016/NSDis.c @@ -18,8 +18,14 @@ // #define ADD_ASCII -static inline uint32_t read_x32_internal(uint32_t addr) { - return read_x8(addr) | (read_x8(addr + 1) << 8) | (read_x8(addr + 2) << 16) | (read_x8(addr + 3) << 24); +#ifdef INCLUDE_DEBUGGER +#define read_mem_8 read_x8_internal +#else +#define read_mem_8 read_x8 +#endif + +static inline uint32_t read_mem_32(uint32_t addr) { + return read_mem_8(addr) | (read_mem_8(addr + 1) << 8) | (read_mem_8(addr + 2) << 16) | (read_mem_8(addr + 3) << 24); } static const char LPRLookUp[16][20] = @@ -213,7 +219,7 @@ static void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32 int32_t Value; MultiReg temp3; - temp3.u32 = SWAP32(read_x32_internal(*pPC)); + temp3.u32 = SWAP32(read_mem_32(*pPC)); if (OperandSize->Op[c] == sz8) Value = temp3.u8; else if (OperandSize->Op[c] == sz16) @@ -298,7 +304,6 @@ static void GetOperandText(uint32_t Start, uint32_t* pPC, RegLKU Pattern, uint32 static void RegLookUp(uint32_t Start, uint32_t* pPC, OperandSizeType *OperandSize) { - // printf("RegLookUp(%06" PRIX32 ", %06" PRIX32 ")\n", pc, (*pPC)); uint32_t Index; for (Index = 0; Index < 2; Index++) @@ -479,7 +484,7 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u StringAppend("&%06" PRIX32 " ", StartPc); StringAppend("["); for (i = 0; i < MAX_INSTR_SIZE; i++) { - StringAppend("%02x", read_x8_internal(StartPc + i)); + StringAppend("%02x", read_mem_8(StartPc + i)); } StringAppend("] "); uint32_t Format = Function >> 4; @@ -529,25 +534,25 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u { case SAVE: { - ShowRegs(read_x8_internal((*pPC)++), 0); //Access directly we do not want tube reads! + ShowRegs(read_mem_8((*pPC)++), 0); //Access directly we do not want tube reads! } break; case RESTORE: { - ShowRegs(read_x8_internal((*pPC)++), 1); //Access directly we do not want tube reads! + ShowRegs(read_mem_8((*pPC)++), 1); //Access directly we do not want tube reads! } break; case EXIT: { - ShowRegs(read_x8_internal((*pPC)++), 1); //Access directly we do not want tube reads! + ShowRegs(read_mem_8((*pPC)++), 1); //Access directly we do not want tube reads! } break; case ENTER: { - ShowRegs(read_x8_internal((*pPC)++), 0); //Access directly we do not want tube reads! + ShowRegs(read_mem_8((*pPC)++), 0); //Access directly we do not want tube reads! int32_t d = GetDisplacement(pPC); StringAppend(" " HEX32 "", d); } @@ -602,7 +607,7 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u case INSS: case EXTS: { - uint8_t Value = read_x8_internal((*pPC)++); + uint8_t Value = read_mem_8((*pPC)++); StringAppend(",%" PRIu32 ",%" PRIu32, Value >> 5, ((Value & 0x1F) + 1)); } break; @@ -613,7 +618,7 @@ void n32016_show_instruction(uint32_t StartPc, uint32_t* pPC, uint32_t opcode, u return; } - //PiTRACE("PC is :%08"PRIX32" ?????\n", *pPC); + //PiTRACE("PC is :%08"PRIX32" ?????", *pPC); } void ShowRegisterWrite(RegLKU RegIn, uint32_t Value) @@ -623,19 +628,19 @@ void ShowRegisterWrite(RegLKU RegIn, uint32_t Value) #ifdef SHOW_REG_WRITES if (RegIn.RegType == Integer) { - PiTRACE(" R%u = %"PRIX32"\n", RegIn.OpType, Value); + PiTRACE(" R%u = %"PRIX32, RegIn.OpType, Value); } #endif #ifdef TEST_SUITE if (RegIn.OpType == 7) { - PiTRACE("*** TEST = %u\n", Value); + PiTRACE("*** TEST = %u", Value); #if 0 if (Value == 137) { - PiTRACE("*** BREAKPOINT\n"); + PiTRACE("*** BREAKPOINT"); } #endif } @@ -650,7 +655,7 @@ static void getgen(int gen, int c, uint32_t* pPC) if (gen >= EaPlusRn) { - Regs[c].Whole |= read_x8_internal((*pPC)++) << 8; + Regs[c].Whole |= read_mem_8((*pPC)++) << 8; (*pPC)++; if ((Regs[c].Whole & 0xF800) == (Immediate << 11)) @@ -670,7 +675,7 @@ static void getgen(int gen, int c, uint32_t* pPC) static void Decode(uint32_t* pPC) { uint32_t StartPc = *pPC; - uint32_t opcode = read_x32_internal(*pPC); + uint32_t opcode = read_mem_32(*pPC); uint32_t Function = FunctionLookup[opcode & 0xFF]; uint32_t Format = Function >> 4; OperandSizeType OperandSize; diff --git a/src/NS32016/Trap.c b/src/NS32016/Trap.c index ec3a42c0..64191441 100644 --- a/src/NS32016/Trap.c +++ b/src/NS32016/Trap.c @@ -37,7 +37,7 @@ void ShowTraps(void) { if (TrapFlags & Pattern) { - TrapTRACE("%s\n", TrapText[Count]); + TrapTRACE("%s", TrapText[Count]); } } } @@ -47,20 +47,15 @@ void Dump(void) { n32016_ShowRegs(0xFF); ShowTraps(); - TrapTRACE("\n"); - ProfileDump(); } void n32016_dumpregs(char* pMessage) { - TrapTRACE("%s\n", pMessage); + TrapTRACE("%s", pMessage); Dump(); #ifdef PC_SIMULATION -#ifdef TRACE_TO_FILE - printf("\n"); -#endif #ifdef WIN32 system("pause"); diff --git a/src/NS32016/Trap.h b/src/NS32016/Trap.h index b4e01e73..891e05c5 100644 --- a/src/NS32016/Trap.h +++ b/src/NS32016/Trap.h @@ -1,4 +1,4 @@ -#define TrapTRACE printf +#define TrapTRACE log_info enum TrapTypes { diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 072d3da4..46558763 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -118,7 +118,7 @@ uint8_t read_x8_internal(uint32_t addr) return tube_parasite_read(addr >> 1); } - PiWARN("Bad Read @ %06" PRIX32 "\n", addr); + PiWARN("Bad Read @ %06x", addr); return 0; } @@ -197,7 +197,7 @@ uint32_t read_n(uint32_t addr, uint32_t Size) case sz32: return read_x32(addr); default: - PiWARN("Bad read_n() size @ %06" PRIX32 " size %" PRIX32 "\n", addr, Size); + PiWARN("Bad read_n() size @ %06x size %x", addr, Size); return 0; } } @@ -235,10 +235,10 @@ void write_x8_internal(uint32_t addr, uint8_t val) if (addr == 0xF90000) { #ifdef PANDORA_ROM_PAGE_OUT - PiTRACE("Pandora ROM no longer occupying the entire memory space!\n") + PiTRACE("Pandora ROM no longer occupying the entire memory space!") memset(ns32016ram, 0, RAM_SIZE); #else - PiTRACE("Pandora ROM writes to 0xF90000\n"); + PiTRACE("Pandora ROM write to 0xF90000"); #endif return; @@ -247,7 +247,7 @@ void write_x8_internal(uint32_t addr, uint8_t val) // Silently ignore writing one word beyond end of RAM // as Pandora RAM test does this if (addr >= RAM_SIZE + 4) { - PiWARN("Writing outside of RAM @%06"PRIX32" %02"PRIX8"\n", addr, val); + PiWARN("Writing outside of RAM @ %06X = %02X", addr, val); } } diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 00000000..5a7e2a24 --- /dev/null +++ b/src/logging.c @@ -0,0 +1,50 @@ +#include +#include +#include "logging.h" + +#ifdef DEBUG +void log_debug(const char *fmt, ...) { + va_list ap; + printf("DEBUG: "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\r\n"); +} +#endif + +void log_info(const char *fmt, ...) { + va_list ap; + printf("INFO: "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\r\n"); +} + +void log_warn(const char *fmt, ...) { + va_list ap; + printf("WARN: "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\r\n"); +} + +void log_error(const char *fmt, ...) { + va_list ap; + printf("ERROR: "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\r\n"); +} + +void log_fatal(const char *fmt, ...) { + va_list ap; + printf("FATAL: "); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\r\n"); +} diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 00000000..ea45d40a --- /dev/null +++ b/src/logging.h @@ -0,0 +1,20 @@ +// logging.h + +#ifndef LOGGING_H +#define LOGGING_H + +#ifdef DEBUG +extern void log_debug(const char *format, ...); +#else +static inline void log_debug(const char *format, ...) {} +#endif + +extern void log_info(const char *fmt, ...); + +extern void log_warn(const char *fmt, ...); + +extern void log_error(const char *fmt, ...); + +extern void log_fatal(const char *fmt, ...); + +#endif From 1297dfaffa240a0d41ddff508d77c696371996a6 Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 17:40:47 +0000 Subject: [PATCH 032/149] Debugger: Rename cpu_debug implementations Change-Id: I7c67e7198bc569fa0c4a585296ae565a202d4d16 --- src/CMakeLists.txt | 8 ++++---- src/NS32016/32016.c | 2 +- src/NS32016/{debug.c => 32016_debug.c} | 5 +++-- src/NS32016/{debug.h => 32016_debug.h} | 0 src/NS32016/mem32016.c | 2 +- src/debugger/debugger.c | 4 ++-- src/mame/arm.c | 2 +- src/mame/{debug.c => arm_debug.c} | 7 ++++--- src/mame/{debug.h => arm_debug.h} | 0 9 files changed, 16 insertions(+), 14 deletions(-) rename src/NS32016/{debug.c => 32016_debug.c} (99%) rename src/NS32016/{debug.h => 32016_debug.h} (100%) rename src/mame/{debug.c => arm_debug.c} (99%) rename src/mame/{debug.h => arm_debug.h} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc549257..cc580ca7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -133,8 +133,8 @@ file( GLOB copro_arm2_files tuberom_arm.h mame/arm.c mame/arm.h - mame/debug.c - mame/debug.h + mame/arm_debug.c + mame/arm_debug.h ) # 32016 @@ -143,6 +143,8 @@ file( GLOB copro_32016_files copro-32016.h NS32016/32016.c NS32016/32016.h + NS32016/32016_debug.c + NS32016/32016_debug.h NS32016/Decode.c NS32016/Decode.h NS32016/defs.h @@ -156,8 +158,6 @@ file( GLOB copro_32016_files NS32016/Profile.h NS32016/Trap.c NS32016/Trap.h - NS32016/debug.c - NS32016/debug.h ) # Z80 diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index 67e6b8d8..fc19d4fa 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -20,7 +20,7 @@ #endif #ifdef INCLUDE_DEBUGGER -#include "debug.h" +#include "32016_debug.h" #include "../cpu_debug.h" #endif diff --git a/src/NS32016/debug.c b/src/NS32016/32016_debug.c similarity index 99% rename from src/NS32016/debug.c rename to src/NS32016/32016_debug.c index 19964580..09fb6630 100644 --- a/src/NS32016/debug.c +++ b/src/NS32016/32016_debug.c @@ -2,11 +2,12 @@ #include #include +#include "../cpu_debug.h" + #include "32016.h" +#include "32016_debug.h" #include "mem32016.h" #include "NSDis.h" -#include "debug.h" -#include "../cpu_debug.h" /***************************************************** * CPU Debug Interface diff --git a/src/NS32016/debug.h b/src/NS32016/32016_debug.h similarity index 100% rename from src/NS32016/debug.h rename to src/NS32016/32016_debug.h diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 46558763..42471344 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -13,8 +13,8 @@ #include "mem32016.h" #ifdef INCLUDE_DEBUGGER -#include "debug.h" #include "../cpu_debug.h" +#include "32016_debug.h" #endif #ifdef BEM diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index e3e201a8..414f7d2c 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -7,8 +7,8 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" -#include "../mame/debug.h" -#include "../NS32016/debug.h" +#include "../mame/arm_debug.h" +#include "../NS32016/32016_debug.h" extern unsigned int copro; diff --git a/src/mame/arm.c b/src/mame/arm.c index e3e3bb66..d949976c 100644 --- a/src/mame/arm.c +++ b/src/mame/arm.c @@ -31,7 +31,7 @@ int m_trace; #endif #ifdef INCLUDE_DEBUGGER -#include "debug.h" +#include "arm_debug.h" #include "../cpu_debug.h" #endif diff --git a/src/mame/debug.c b/src/mame/arm_debug.c similarity index 99% rename from src/mame/debug.c rename to src/mame/arm_debug.c index a1905bad..0434f478 100644 --- a/src/mame/debug.c +++ b/src/mame/arm_debug.c @@ -1,12 +1,13 @@ - #include +#include #include #include #include +#include "../cpu_debug.h" + #include "arm.h" +#include "arm_debug.h" #include "../darm/darm.h" -#include "debug.h" -#include "../cpu_debug.h" #define ADDRESS_MASK ((UINT32) 0x03fffffcu) diff --git a/src/mame/debug.h b/src/mame/arm_debug.h similarity index 100% rename from src/mame/debug.h rename to src/mame/arm_debug.h From f54cac5b0c00f4aa43f05d89cd43a05a6ccf9d1c Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 17 Mar 2017 18:18:14 +0000 Subject: [PATCH 033/149] Build fixes to remove debugger from normal build Change-Id: Ic85ab6c927dc5b964558c1f3c47d1e094e6a79da --- src/CMakeLists.txt | 103 +++++++++++++++++++++++---------------------- src/rpi-aux.c | 8 ++++ 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc580ca7..9e01ac49 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,8 +35,7 @@ cmake_minimum_required( VERSION 2.8 ) # cross-compiler's ability to compile a simple program because that will fail project( tube-client C ASM ) -# By default we include the interactive debugger capability -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DINCLUDE_DEBUGGER" ) +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" ) # Add any C compiler flags here. The C flags concerned with processor tuning # are in the toolchain files toolchain-arm-none-eabi-bcm2835.cmake, etc. @@ -133,8 +132,6 @@ file( GLOB copro_arm2_files tuberom_arm.h mame/arm.c mame/arm.h - mame/arm_debug.c - mame/arm_debug.h ) # 32016 @@ -143,8 +140,6 @@ file( GLOB copro_32016_files copro-32016.h NS32016/32016.c NS32016/32016.h - NS32016/32016_debug.c - NS32016/32016_debug.h NS32016/Decode.c NS32016/Decode.h NS32016/defs.h @@ -169,30 +164,6 @@ file( GLOB copro_z80_files yaze/mem_mmu.h ) -# 6809 (version based on xroar emulator) -#file( GLOB copro_6809_files -# copro-mc6809.h -# copro-mc6809.c -# mc6809/config.h -# mc6809/pl-endian.h -# mc6809/delegate.c -# mc6809/delegate.h -# mc6809/xalloc.h -# mc6809/xmalloc.c -# mc6809/mc6809.c -# mc6809/mc6809.h -# mc6809/hd6309.c -# mc6809/hd6309.h -#) - -# 6809 (version based on Sean Conner emulator) -#file( GLOB copro_6809sc_files -# copro-mc6809sc.h -# copro-mc6809sc.c -# mc6809sc/mc6809.c -# mc6809sc/mc6809.h -#) - # 6809 (version based on Neal Crook emulator) file( GLOB copro_6809nc_files copro-mc6809nc.h @@ -251,50 +222,80 @@ file( GLOB copro_arm_files darm/thumb-tbl.h ) -# Interactive debugger +# Interactive debugger files file( GLOB debugger_files debugger/debugger.c debugger/debugger.h cpu_debug.h + NS32016/32016_debug.c + NS32016/32016_debug.h + mame/arm_debug.c + mame/arm_debug.h ) if( ${DEBUG} ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG=1" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG=1 " ) + + if( NOT ( ${MINIMAL_BUILD} ) ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DINCLUDE_DEBUGGER=1 " ) + endif() endif() if( ${MINIMAL_BUILD} ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMINIMAL_BUILD=1" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMINIMAL_BUILD=1" ) add_executable( tube-client ${core_files} - ${debugger_files} ${copro_65tube_files} ${shared_6502_files} ) else() - add_executable( tube-client - ${core_files} - ${debugger_files} - ${copro_65tube_files} - ${copro_lib6502_files} - ${shared_6502_files} - ${copro_80186_files} - ${copro_arm2_files} - ${copro_32016_files} - ${copro_z80_files} - ${copro_6809_files} - ${copro_6809sc_files} - ${copro_6809nc_files} - ${shared_6809_files} - ${copro_null_files} - ${copro_arm_files} - ) + if( ${DEBUG} ) + + add_executable( tube-client + ${core_files} + ${copro_65tube_files} + ${copro_lib6502_files} + ${shared_6502_files} + ${copro_80186_files} + ${copro_arm2_files} + ${copro_32016_files} + ${copro_z80_files} + ${copro_6809_files} + ${copro_6809sc_files} + ${copro_6809nc_files} + ${shared_6809_files} + ${copro_null_files} + ${copro_arm_files} + ${debugger_files} + ) + + else() + + add_executable( tube-client + ${core_files} + ${copro_65tube_files} + ${copro_lib6502_files} + ${shared_6502_files} + ${copro_80186_files} + ${copro_arm2_files} + ${copro_32016_files} + ${copro_z80_files} + ${copro_6809_files} + ${copro_6809sc_files} + ${copro_6809nc_files} + ${shared_6809_files} + ${copro_null_files} + ${copro_arm_files} + ) + + endif() endif() diff --git a/src/rpi-aux.c b/src/rpi-aux.c index 18825ba8..df78e009 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -3,7 +3,10 @@ #include "rpi-base.h" #include "rpi-gpio.h" #include "info.h" + +#ifdef INCLUDE_DEBUGGER #include "debugger/debugger.h" +#endif /* Define the system clock frequency in MHz for the baud rate calculation. This is clearly defined on the BCM2835 datasheet errata page: @@ -45,8 +48,13 @@ static void __attribute__((interrupt("IRQ"))) RPI_AuxMiniUartIRQHandler() { /* Handle RxReady interrupt */ if (iir & AUX_MUIIR_INT_IS_RX) { +#ifdef INCLUDE_DEBUGGER /* Forward all received characters to the debugger */ debugger_rx_char(auxillary->MU_IO & 0xFF); +#else + /* Else just exho characters */ + RPI_AuxMiniUartWrite(auxillary->MU_IO & 0xFF); +#endif } /* Handle TxEmpty interrupt */ From d859c4bbb28b904bf1ea0fa8ba053a3df2d5ee54 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 09:16:26 +0000 Subject: [PATCH 034/149] Remove old code --- src/tube.S | 461 ++--------------------------------------------------- 1 file changed, 17 insertions(+), 444 deletions(-) diff --git a/src/tube.S b/src/tube.S index cf733086..2c50f83d 100644 --- a/src/tube.S +++ b/src/tube.S @@ -1,11 +1,5 @@ #include "rpi-base.h" #include "tube-defs.h" -#include "cache.h" - -#define DETECT_DUMMY_READ -// #define DEBUG_OVERRUN -// #define DEBUG_LATE -// #define ON_READS_SPIN_FOR_PHI2_HIGH #define instrREG r7 @@ -14,423 +8,18 @@ .global tube_mailbox_block .global arm_irq_handler .global arm_fiq_handler -.global arm_fiq_handler_flag0 -#ifndef USE_MULTICORE + .global arm_fiq_handler_flag1 -#endif -.global lock_isr + + .global gpfsel_data_idle .global gpfsel_data_driving -// This FIQ handler is only installed: -// - When the GPU Mailbox is being used -// - And when Co Pro 0/1 are selected -// - And when we are running on a single core pi - -#ifdef USE_HW_MAILBOX -.macro FIQ_MAILBOX_HANDLER - - // Disable the FIQ interrupt (the C code will re-enable) - // This is necessary because we don't want the FIQ handler to have to read - // the mailbox, so the FIQ condition will not be cleared until later - ldr r8, =FIQCTRL - mov r9, #0 - str r9, [r8] - - orr instrREG, instrREG, #1024 // signal event to 6502 instruction flow - - subs pc, lr, #4 - -.endm -#endif - - - -.macro FIQ_HANDLER flag_using_ip - - //r8-r11 are shadowed in FIQ mode, so no need to push - //push {r8-r11} - -#ifdef HAS_40PINS - mov r9, #TEST_MASK - ldr r8, =GPSET0 - str r9, [r8] -#endif - - ldr r8, =GPEDS0 - mov r9, #-1 - str r9, [r8] // clear all Pin events - - ldr r8, =GPLEV0 - ldr r9, [r8] // *** very expensive but necessary *** - - tst r9, #NRST_MASK // test for reset - beq post_mail\@ - - tst r9, #NTUBE_MASK // test for glitches - bne exit\@ - - tst r9, #RNW_MASK - beq wr_cycle\@ - -// READ_CYCLE - mov r10, #0 - tst r9, #A0_MASK - orrne r10, #1 - tst r9, #A1_MASK - orrne r10, #2 - tst r9, #A2_MASK - orrne r10, #4 - - ldr r8, =tube_regs_block - ldrb r10, [r8, r10] - - mov r11, r10, LSL #D0_BASE // low nibble now aligned to GPIO - and r11, r11, #D30_MASK - mov r10, r10, LSL #D4_BASE-4 - and r10, r10, #D74_MASK // high nibble in the right place - orr r10, r10, r11 - - ldr r8, =GPSET0 - str r10, [r8] // *** expensive but necessary *** - eor r10, r10, #D30_MASK - eor r10, r10, #D74_MASK - ldr r8, =GPCLR0 - str r10, [r8] // *** expensive but necessary *** - - ldr r8, =GPFSEL0 - ldr r11, =(gpfsel_data_driving) - ldr r10, [r11] - str r10, [r8] // *** expensive but necessary *** - ldr r10, [r11, #4] - str r10, [r8, #4] // *** expensive but necessary *** - ldr r10, [r11, #8] - str r10, [r8, #8] // *** expensive but necessary *** - - ldr r8, =GPLEV0 - -#ifdef ON_READS_SPIN_FOR_PHI2_HIGH -rd_wait_for_phi2_high1\@: - ldr r10, [r8] // ** very expensive but necessary *** - tst r10, #PHI2_MASK - beq rd_wait_for_phi2_high1\@ -#endif - -rd_wait_for_phi2_low\@: - ldr r10, [r8] // ** very expensive but necessary *** - tst r10, #PHI2_MASK - movne r9, r10 - bne rd_wait_for_phi2_low\@ - - ldr r8, =GPFSEL0 - ldr r11, =(gpfsel_data_idle) - ldr r10, [r11] - str r10, [r8] // *** expensive but necessary *** - ldr r10, [r11, #4] - str r10, [r8, #4] // *** expensive but necessary *** - ldr r10, [r11, #8] - str r10, [r8, #8] // *** expensive but necessary *** - -// In some rare cases, a read may be immediately followed by a write -// A concrete case of this is *FX 151,230,N which uses STA &FEE0,X -// To detect this case, on reads we wait for one more edge of Phi2 -// and the re-check the nTUBE and RNW lines for a possible write - -#ifdef DETECT_DUMMY_READ - ldr r8, =GPLEV0 -rd_wait_for_phi2_high2\@: - ldr r10, [r8] // ** very expensive but necessary *** - tst r10, #PHI2_MASK - beq rd_wait_for_phi2_high2\@ - tst r10, #(NTUBE_MASK | RNW_MASK) - beq wr_wait_for_phi2_low\@ -#endif - - tst r9, #A0_MASK // don't bother emulator with status reads - bne post_mail\@ - b exit\@ - -// WRITE_CYCLE -wr_cycle\@: - -wr_wait_for_phi2_high\@: - ldr r9, [r8] - tst r9, #PHI2_MASK - beq wr_wait_for_phi2_high\@ - -wr_wait_for_phi2_low\@: - ldr r10, [r8] - tst r10, #PHI2_MASK - movne r9, r10 - bne wr_wait_for_phi2_low\@ - -// At this point, cache misses will no longer disrupt the 6502 bus timings -post_mail\@: - ldr r10, =PINS_MASK - and r9, r9, r10 - -post_mail2\@: - orr r9, r9, #ATTN_MASK - - ldr r10, tube_mailbox_block - tst r10, #ATTN_MASK // if previous message not acknowledged, then flag overrun - orrne r9, r9, #OVERRUN_MASK - str r9, tube_mailbox_block - -// Update TEST2 Pin to reflect overun state -#if defined(DEBUG_OVERRUN) && defined(HAS_40PINS) - mov r10, #TEST2_MASK - ldrne r8, =GPSET0 - ldreq r8, =GPCLR0 - str r10, [r8] -#endif - -// Update TEST3 Pin to reflect late state -#if defined(DEBUG_LATE) && defined(HAS_40PINS) - mov r10, #TEST3_MASK - tst r9, #NTUBE_MASK - ldrne r8, =GPSET0 - ldreq r8, =GPCLR0 - str r10, [r8] -#endif - -.if \flag_using_ip - // Switch back to irq mode so ip is not shadowed - mrs r8, cpsr - bic r8, r8, #0x1F - orr r8, r8, #0x12 - msr cpsr_c, r8 - - orr instrREG, instrREG, #1024 // signal event to 6502 instruction flow - - // Switch back to fiq mode, so we return correctly - // lr is used here because its shadowed in IRQ mode, so doesn't corrupt the normal lr - mrs lr, cpsr - bic lr, lr, #0x1F - orr lr, lr, #0x11 - msr cpsr_c, lr - - // Note, the above mode switching could be avoided if we reworked the register assignment - // in the 6502 emulator to use a register r0..r7 for signalling. - // I did do this as an experiment, and it's parked in a branch. - // I'd like to avoid making big changes to that code for now. -.endif - -exit\@: - -#ifdef HAS_40PINS - mov r9, #TEST_MASK - ldr r8, =GPCLR0 - str r9, [r8] -#endif - - //r8-r11 are shadowed in FIQ mode, so no need to pop - //pop {r8-r11} - subs pc, lr, #4 - -glitch\@: - ldr r10, =PINS_MASK - and r9, r9, r10 - orr r9, r9, #GLITCH_MASK - b post_mail2\@ - -.endm - -// ================================================= -// LOCK the ISR CODE into cache -// ================================================= -CACHELINE_ALIGN = 5 -#if !defined(RPI2) && !defined(RPI3) && !defined(USE_GPU) -lock_isr: - push {lr} - - // Copy locking code into un-cached memory - ldr r0, =lock_isr_into_cache_start - ldr r1, =UNCACHED_MEM_BASE - mov r2, #(lock_isr_into_cache_end - lock_isr_into_cache_start) -copy_loop: - ldr r3, [r0], #4 - str r3, [r1], #4 - subs r2, r2, #4 - bne copy_loop - - // disable interrupts (so handler doesn't get accidentally executed - bl _disable_interrupts - - // execute locking code - ldr r0, =UNCACHED_MEM_BASE - blx r0 - - // enable interrupts - bl _enable_interrupts - - pop {lr} - mov pc, lr - -// This code must only be executed from uncachable memory -// and must be position independant - -// Cache ways are 4KB, and contain 128 x 32 byte lines - -// I Cache Locked Way - -// 0x00000000-0x0000001f - cache line 0 - (vectors) -// 0x01f01180-0x01f012ff - cache lines 12-23 - (ISR code) - -// D Cache Locked Way - -// 0x?????000-0x?????01f - cache line 0 - (vector TLBs) -// 0x00000020-0x0000003f - cache line 1 - (vectors) -// 0x?????060-0x?????07f - cache line 3 - (code/data/stack TLBs) -// 0x01f01300-0x01f01380 - cache lines 24-27 - (ISR data) -// 0x?????800-0x?????81f - cache line 64 - (IO TLB) -// 0x01edff00-0x01edffff - cache lines 120-127 - (FIQ stack, not currently used) - -.align CACHELINE_ALIGN -lock_isr_into_cache_start: - - // invalidate entire instruction cache (page 3-74) - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 - // clean and invalidate the entire data cache (page 3-74) - mov r0, #0 - mcr p15, 0, r0, c7, c14, 0 - - // data synchronization barrier to ensure all outstanding memory transactions are complete - mov r0, #0 - mcr p15, 0, r0, c7, c10, 4 - - // Set the fast interrupt mode bit - // This is commented out because - // 1. It costs in overall performance - // 2. It did not make an observable different to tube read latency - - // mrc p15, 0, r0, c1, c0, 0 - // orr r0, r0, #(1<<21) - // mcr p15, 0, r0, c1, c0, 0 - - // data synchronization barrier to ensure all outstanding memory transactions are complete - mov r0, #0 - mcr p15, 0, r0, c7, c10, 4 - - // enable d-cache way 0, lock ways 1, 2, 3 (page 3-89) - mov r0, #0xfffffffe - mcr p15, 0, r0, c9, c0, 0 - - // enable i-cache way 0, lock ways 1, 2, 3 (page 3-89) - mov r0, #0xfffffffe - mcr p15, 0, r0, c9, c0, 1 - - // bring the isr code into i-cache - // these loads are relative references, so should relocate - ldr r0, isr_code_start_ptr - ldr r1, isr_code_end_ptr -lock_code_loop: - // prefetch cache line into instruction cache (page 3-76) - // r0 is the virtual address, with bits 4..0 set to zero - mcr p15, 0, r0, c7, c13, 1 - // move to the next cache line - add r0, r0, #32 - cmp r0, r1 - bne lock_code_loop - - // prefetch the vector instructions (8 words starting at 0x00000000) into the i-cache - mov r0, #0x00 - mcr p15, 0, r0, c7, c13, 1 - - // any data prefetched is actually used by accumulating into r3 - // don't think this is actually necessary, but lets be really - // sure the ARM doesn't abort the transactions - mov r3, #0x00 - - // bring the isr data into d-cache - // these loads are relative references, so should relocate - ldr r0, isr_data_start_ptr - ldr r1, isr_data_end_ptr -lock_data_loop: - // load from the cache line to prefetch it - ldr r2, [r0] - add r3, r3, r2 - // move to the next cache line - add r0, r0, #32 - cmp r0, r1 - bne lock_data_loop - - // prefetch the vector data (8 words starting at 0x00000020) into the d-cache - mov r0, #0x20 - ldr r2, [r0] - add r3, r3, r2 - - // prefetch the used page table (TLB) entries - // The complete table is 4K words (16K bytes) with one work per 1MB of virtual memory - // It is aligned on a 4KB boundary - // Each cache line contains 8 words representing 8MB of memory - ldr r0, page_table_ptr - ldr r2, [r0, #(0x000 * 4)] // 0x00000000-0x000fffff (vectors) - add r3, r3, r2 - ldr r2, [r0, #(0x018 * 4)] // 0x01800000-0x01ffffff (stacks, code and data) - add r3, r3, r2 - ldr r2, [r0, #(0x200 * 4)] // 0x20000000-0x027fffff (IO - todo should use PERIPHERAL_BASE here) - add r3, r3, r2 - - // bring the isr stack into d-cache - // these loads are relative references, so should relocate - ldr r0, isr_stack_start_ptr - ldr r1, isr_stack_end_ptr -lock_stack_loop: - // load from the cache line to prefetch it - ldr r2, [r0] - add r3, r3, r2 - // move to the next cache line - add r0, r0, #32 - cmp r0, r1 - bne lock_stack_loop - - // data synchronization barrier to ensure all outstanding memory transactions are complete - mov r0, #0 - mcr p15, 0, r0, c7, c10, 4 - - // lock d-cache way 0, enable ways 1, 2, 3 (page 3-89) - mov r0, #0xfffffff1 - mcr p15, 0, r0, c9, c0, 0 - - // lock i-cache way 0, enable ways 1, 2, 3 (page 3-89) - mov r0, #0xfffffff1 - mcr p15, 0, r0, c9, c0, 1 - - mov pc, lr - -isr_code_start_ptr: -.word isr_code_start - -isr_code_end_ptr: -.word isr_code_end - -isr_data_start_ptr: -.word isr_data_start - -isr_data_end_ptr: -.word isr_data_end - -page_table_ptr: -.word PageTable - -// TODO these should be somehow imported from arm-startup.S - -isr_stack_start_ptr: -.word 0x01EE0000 - 0x100 - -isr_stack_end_ptr: -.word 0x01EE0000 - - -.align CACHELINE_ALIGN -lock_isr_into_cache_end: -#endif // ================================================= // ISR CODE // ================================================= +CACHELINE_ALIGN = 5 .align CACHELINE_ALIGN isr_code_start: @@ -441,22 +30,20 @@ arm_fiq_handler: arm_irq_handler: subs pc, lr, #4 -// ARM FIQ handler (two versions) - -#ifndef USE_MULTICORE +// ARM FIQ handler arm_fiq_handler_flag1: -#ifdef USE_HW_MAILBOX -FIQ_MAILBOX_HANDLER -#else -FIQ_HANDLER 1 -#endif -#endif -#ifndef USE_GPU -arm_fiq_handler_flag0: -FIQ_HANDLER 0 -#endif -.align CACHELINE_ALIGN -isr_code_end: + + // Disable the FIQ interrupt (the C code will re-enable) + // This is necessary because we don't want the FIQ handler to have to read + // the mailbox, so the FIQ condition will not be cleared until later + ldr r8, =FIQCTRL + mov r9, #0 + str r9, [r8] + + orr instrREG, instrREG, #1024 // signal event to 6502 instruction flow + + subs pc, lr, #4 + // ================================================= // ISR DATA @@ -465,7 +52,6 @@ isr_code_end: .align CACHELINE_ALIGN isr_data_start: -#ifdef USE_GPU tube_regs_block: .word (0xf << D4_BASE) | (0xe << D0_BASE) .word (0xe << D4_BASE) | (0xd << D0_BASE) @@ -475,17 +61,6 @@ tube_regs_block: .word (0xa << D4_BASE) | (0x9 << D0_BASE) .word (0x9 << D4_BASE) | (0x8 << D0_BASE) .word (0x8 << D4_BASE) | (0x7 << D0_BASE) -#else -tube_regs_block: - .byte 0xfe - .byte 0xed - .byte 0xdc - .byte 0xcb - .byte 0xba - .byte 0xa9 - .byte 0x98 - .byte 0x87 -#endif .align CACHELINE_ALIGN // Some constants for controlling the data bus @@ -505,5 +80,3 @@ tube_mailbox_block: // Insert the current literal pool, so these get locked in the cache .ltorg -.align CACHELINE_ALIGN -isr_data_end: From c0deec2e95442427528f5da280716a2f7895695b Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 09:28:43 +0000 Subject: [PATCH 035/149] Move definition of gpfsel_data_idle to tube-ula.c and tidy --- src/tube-ula.c | 8 ++++---- src/tube.S | 42 ------------------------------------------ 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index dabb7bc5..fbadf28d 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -87,8 +87,8 @@ static volatile uint8_t *tube_regs; #endif -extern volatile uint32_t gpfsel_data_idle[3]; -extern volatile uint32_t gpfsel_data_driving[3]; +volatile uint32_t gpfsel_data_idle[6]; + const static uint32_t magic[3] = {MAGIC_C0, MAGIC_C1, MAGIC_C2 | MAGIC_C3 }; static char copro_command =0; static perf_counters_t pct; @@ -751,8 +751,8 @@ void tube_init_hardware() // to set the data bus GPIOs as inputs (idle) and output (driving) for (i = 0; i < 3; i++) { gpfsel_data_idle[i] = (uint32_t) RPI_GpioBase->GPFSEL[i]; - gpfsel_data_driving[i] = gpfsel_data_idle[i] | magic[i]; - LOG_DEBUG("%d %010o %010o\r\n", i, (unsigned int) gpfsel_data_idle[i], (unsigned int) gpfsel_data_driving[i]); + gpfsel_data_idle[i+3] = gpfsel_data_idle[i] | magic[i]; + LOG_DEBUG("%d %010o %010o\r\n", i, (unsigned int) gpfsel_data_idle[i], (unsigned int) gpfsel_data_idle[i+3]); } // Print the GPIO numbers of A0, A1 and A2 diff --git a/src/tube.S b/src/tube.S index 2c50f83d..c290d1ba 100644 --- a/src/tube.S +++ b/src/tube.S @@ -4,17 +4,11 @@ #define instrREG r7 .text -.global tube_regs_block .global tube_mailbox_block .global arm_irq_handler .global arm_fiq_handler .global arm_fiq_handler_flag1 - - -.global gpfsel_data_idle -.global gpfsel_data_driving - // ================================================= // ISR CODE @@ -43,40 +37,4 @@ arm_fiq_handler_flag1: orr instrREG, instrREG, #1024 // signal event to 6502 instruction flow subs pc, lr, #4 - - -// ================================================= -// ISR DATA -// ================================================= - -.align CACHELINE_ALIGN -isr_data_start: - -tube_regs_block: - .word (0xf << D4_BASE) | (0xe << D0_BASE) - .word (0xe << D4_BASE) | (0xd << D0_BASE) - .word (0xd << D4_BASE) | (0xc << D0_BASE) - .word (0xc << D4_BASE) | (0xb << D0_BASE) - .word (0xb << D4_BASE) | (0xa << D0_BASE) - .word (0xa << D4_BASE) | (0x9 << D0_BASE) - .word (0x9 << D4_BASE) | (0x8 << D0_BASE) - .word (0x8 << D4_BASE) | (0x7 << D0_BASE) - -.align CACHELINE_ALIGN -// Some constants for controlling the data bus -gpfsel_data_idle: - .word 0 - .word 0 - .word 0 - -gpfsel_data_driving: - .word 0 - .word 0 - .word 0 - -// Mailbox between tube isr and events handler (in C) -tube_mailbox_block: - .word 0 - // Insert the current literal pool, so these get locked in the cache -.ltorg From d689f1f95ab7486de1b9dbe16d3a8255f01d52ea Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 09:40:07 +0000 Subject: [PATCH 036/149] Move 6502 Event handler setup to copro65tube --- src/copro-65tube.c | 13 +++++++++++++ src/tube-client.c | 16 ---------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index 5a9be2b4..61d93294 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -56,12 +56,25 @@ static void copro_65tube_reset(unsigned char mpu_memory[]) { tube_wait_for_rst_release(); } +#define FIQ_VECTOR (HIGH_VECTORS_BASE + 0x3C) + void copro_65tube_emulator() { // Remember the current copro so we can exit if it changes int last_copro = copro; // unsigned char *addr; //__attribute__ ((aligned (64*1024))) unsigned char mpu_memory[64*1024]; // allocate the amount of ram unsigned char * mpu_memory; // now the arm vectors have moved we can set the core memory to start at 0 + + // When the 65tube co pro on a single core system, switch to the alternative FIQ handler + // that flag events from the ISR using the ip register + { + int i; + for (i = 0; i < 256; i++) { + Event_Handler_Dispatch_Table[i] = (uint32_t) (copro == COPRO_65TUBE_1 ? Event_Handler_Single_Core_Slow : Event_Handler); + } + *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; + } + mpu_memory = copro_65tube_poweron_reset(); copro_65tube_reset(mpu_memory); diff --git a/src/tube-client.c b/src/tube-client.c index 1f74ba61..b58cd702 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -109,22 +109,6 @@ unsigned char * copro_mem_reset(int length) void init_emulator() { _disable_interrupts(); -#if !defined(USE_GPU) - // Default to the normal FIQ handler - *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag0; -#endif - -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) - // When the 65tube co pro on a single core system, switch to the alternative FIQ handler - // that flag events from the ISR using the ip register - if (copro == COPRO_65TUBE_0 || copro == COPRO_65TUBE_1) { - int i; - for (i = 0; i < 256; i++) { - Event_Handler_Dispatch_Table[i] = (uint32_t) (copro == COPRO_65TUBE_1 ? Event_Handler_Single_Core_Slow : Event_Handler); - } - *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; - } -#endif #ifndef MINIMAL_BUILD if (copro == COPRO_ARMNATIVE) { *((uint32_t *) SWI_VECTOR) = (uint32_t) copro_armnative_swi_handler; From 9a3a293c2518d1c9628b68ff5fd9676ca97f51f8 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 09:51:45 +0000 Subject: [PATCH 037/149] remove old code --- src/copro-65tubeasm.S | 94 +++---------------------------------------- 1 file changed, 5 insertions(+), 89 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index b4b6359b..72ef8d2a 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1389,11 +1389,6 @@ exec_65tube: // This is very strange, because flags bit 7 is not used! // To reproduce, initialize flags to 0x80 -#if defined(USE_MULTICORE) || !defined(USE_HW_MAILBOX) - tst r1, #1 // Copy the slowdown bit into flags - orrne flags, flags, #SLOW_FLAG - -#endif tst r1, #1 // test slow down bit beq noslowsetup // setup ARM cycle counter @@ -1411,19 +1406,13 @@ exec_65tube: str r0,targettime noslowsetup: -#if defined(USE_HW_MAILBOX) mov r0, #MBOX0_DATAIRQEN // if the slow flag is not set, then enable mailbox hardware ldr r1, =MBOX0_CONFIG // to generate interrupts when data is present str r0, [r1] mov r0, #0x80 + 65 // route that to FIQ ldr r1, =FIQCTRL str r0, [r1] -#else - mov r0, #0 // initialize tube mailbox (between isr and event handler) - ldr r1, =tube_mailbox - ldr r1, [r1] - str r0, [r1] -#endif + mrs r0, CPSR // Enable ARM IRQs and FIQs bic r0, r0, #ARM_INT_MASK @@ -1444,84 +1433,26 @@ handle_rst: FETCH_NEXT_3B_MERGED SUBPC // Start executing instructions exec_65tube_exit: // We get here from the Event handler when RST is detected -#if defined(USE_HW_MAILBOX) + mov r0, #0 // disable mailbox hardware to generate interrupts ldr r1, =MBOX0_CONFIG // when data is present str r0, [r1] mov r0, #0 // disable FIQ ldr r1, =FIQCTRL str r0, [r1] -#endif + msr CPSR, r2 // re-enable ARM interrupts pop {r4-r11,pc} - -#if defined(USE_MULTICORE) || !defined(USE_HW_MAILBOX) -fetch_next_i: - sub regPC, regPC, #1 - -fetch_next: - mrs r2, CPSR // Preserve the 6502 flags - - tst flags, #SLOW_FLAG // Check the slowdown bit - bne waste_time // forward branch will predict as not taken - -fetch_next_check_event: -#if defined(USE_HW_MAILBOX) - ldr r0, =MBOX0_STATUS // Check the tube mailbox for "events" (e.g. tube irq) - ldr r0, [r0] - tst r0, #MBOX0_EMPTY - beq Event_Handler -#else - ldr r0, =tube_mailbox // Check the tube mailbox for "events" (e.g. tube irq) - ldr r0, [r0] - ldr r0, [r0] - tst r0, #ATTN_MASK - bne Event_Handler -#endif - msr CPSR_flg, r2 // Restore the 6502 flags - - ldrb r2, [regPC, #1] - ldrb r0, [regPC, #2]! - -#ifdef HISTOGRAM - HISTOGRAM_65TUBE -#endif - - ldr pc, [instt, r2, lsl #2] - -fetch_next_check_irq: - ldr r0, =tube_irq - mrs r2, CPSR // Preserve the 6502 flags - tst flags, #4 // Test whether interrupts are enabled (bit 2 = 0) - ldreq r0, [r0] - eoreq r0, r0, #1 - tsteq r0, #1 // Test for IRQ - beq handle_irq_adjust_regPC - msr CPSR_flg, r2 // Restore the 6502 flags - b fetch_next - -waste_time: - mov r0, #250 // TODO: Recalibrate -waste_time_loop: - subs r0, r0, #1 - bne waste_time_loop - b fetch_next_check_event - -#endif // 6502 Event handler // if USE_MULTICORE is defined, we have come here only from fetch_next above. // if USE_MULTICORE is not defined, we have come here via a branch from the second instruction table Event_Handler: -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) mrs r2, CPSR // preserve the 6502 flags -#endif orr r1, r2, #ARM_INT_MASK // disable ARM IRQs and FIQs msr CPSR_c, r1 -#if defined(USE_HW_MAILBOX) - //ldr r1, =FIQCTRL //mov r0, #0 //str r0, [r1] @@ -1531,20 +1462,9 @@ Event_Handler: str r0, [r1] // As ARM FIQ interrupts currently disabled ldr r1, =MBOX0_READ ldr r0, [r1] - //lsr r0, r0, #4 -#else - ldr r1, =tube_mailbox - ldr r1, [r1] - ldr r0, [r1] -#endif -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) + bic instt, instt, #1024 // ack events sub regPC, regPC, #2 // set the instruction back as we haven't executed it -#endif -#if !defined(USE_HW_MAILBOX) - bic r0, r0, #ATTN_MASK // the attention bit - str r0, [r1] // ack the attention bit -#endif push {r2-r3,r12} // r0 contains the tube mailbox value bl tube_io_handler @@ -1578,8 +1498,6 @@ handle_nmi: INTR -6, 0 FETCH_NEXT_3B_MERGED SUBPC -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) - lastPC: .word 0 targettime: @@ -1710,9 +1628,7 @@ handle_nmi2: msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 b execute_one_instruction - -#endif - + decimal_mode_adc: and r0, regA, #0xf000000 and r2, r1, #15 From 073cae816b08e8406141728910b83b164a050c67 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:10:37 +0000 Subject: [PATCH 038/149] tidy up --- src/copro-65tube.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index 61d93294..b5704c0a 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -67,13 +67,13 @@ void copro_65tube_emulator() { // When the 65tube co pro on a single core system, switch to the alternative FIQ handler // that flag events from the ISR using the ip register - { - int i; - for (i = 0; i < 256; i++) { - Event_Handler_Dispatch_Table[i] = (uint32_t) (copro == COPRO_65TUBE_1 ? Event_Handler_Single_Core_Slow : Event_Handler); - } - *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; + + int i; + for (i = 0; i < 256; i++) { + Event_Handler_Dispatch_Table[i] = (uint32_t) (copro == COPRO_65TUBE_1 ? Event_Handler_Single_Core_Slow : Event_Handler); } + *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; + mpu_memory = copro_65tube_poweron_reset(); copro_65tube_reset(mpu_memory); @@ -95,11 +95,9 @@ void copro_65tube_emulator() { } // restore memory mapping - { - int i; - for ( i= 0 ; i<17; i++ ) - map_4k_page(i, i); - } + + for ( i= 0 ; i<16; i++ ) + map_4k_page(i, i); } From 112f8e885ec267702410d1c1419f9feab38706cb Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:18:47 +0000 Subject: [PATCH 039/149] Tidy up --- src/copro-65tubeasm.S | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 72ef8d2a..3b0e146a 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -87,11 +87,9 @@ .text .global exec_65tube -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) .global Event_Handler_Dispatch_Table .global Event_Handler .global Event_Handler_Single_Core_Slow -#endif .equ N_FLAG, 0x80000000 .equ Z_FLAG, 0x40000000 @@ -1538,7 +1536,6 @@ Event_Handler_Single_Core_Slow: bic instt, instt, #1024 // ack any events sub regPC, regPC, #2 // set the instruction back as we haven't executed it -#if defined(USE_HW_MAILBOX) ldr r1, =MBOX0_STATUS // poll the hardware mailbox status ldr r0, [r1] tst r0, #MBOX0_EMPTY // test if there are any messages @@ -1546,17 +1543,8 @@ Event_Handler_Single_Core_Slow: ldr r1, =MBOX0_READ // read the top message off the mailbox ldr r0, [r1] - lsr r0, r0, #4 -#else - ldr r1, =tube_mailbox - ldr r1, [r1] - ldr r0, [r1] - tst r0, #ATTN_MASK - beq noirq2 - bic r0, r0, #ATTN_MASK // the attention bit - str r0, [r1] // ack the attention bit -#endif + push {r2-r3,r12} // r0 contains the tube mailbox value bl tube_io_handler From 99ab2eccbdf67b7bba9d8a60e37e7391564ed016 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:22:59 +0000 Subject: [PATCH 040/149] Remove old code --- src/tube-client.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/tube-client.c b/src/tube-client.c index b58cd702..9903dd49 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -208,11 +208,10 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) copro = get_copro_number(); get_copro_speed(); -#ifdef USE_GPU + LOG_DEBUG("Staring VC ULA\r\n"); start_vc_ula(); LOG_DEBUG("Done\r\n"); -#endif enable_MMU_and_IDCaches(); _enable_unaligned_access(); @@ -225,9 +224,6 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) init_emulator(); // Lock the Tube Interrupt handler into cache for BCM2835 based Pis -#if !defined(RPI2) && !defined(RPI3) && !defined(USE_GPU) - lock_isr(); -#endif #ifdef HAS_MULTICORE From 4ec3c575af3cc415faa73a6911792421f4a14253 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:28:23 +0000 Subject: [PATCH 041/149] Tidy up --- src/tube-defs.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/tube-defs.h b/src/tube-defs.h index 21d2b699..b7949a6c 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -69,10 +69,6 @@ // Indicate the platform has multiple cores #define HAS_MULTICORE -#define USE_GPU - -#define USE_HW_MAILBOX - // Indicates we want to make active use of multiple cores //#define USE_MULTICORE @@ -82,23 +78,24 @@ // Include instruction histogram in multi core 65tube //#define HISTOGRAM -#else +#endif #define USE_GPU #define USE_HW_MAILBOX -#endif + #include "rpi-base.h" -#ifdef USE_HW_MAILBOX + #define MBOX0_READ (PERIPHERAL_BASE + 0x00B880) #define MBOX0_STATUS (PERIPHERAL_BASE + 0x00B898) #define MBOX0_CONFIG (PERIPHERAL_BASE + 0x00B89C) #define MBOX0_EMPTY (0x40000000) #define MBOX0_DATAIRQEN (0x00000001) -#endif +#define FIQCTRL (PERIPHERAL_BASE + 0x00B20C) + #ifdef __ASSEMBLER__ From 218b44b60e776cf308ea0d934921247abcf1bffa Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:35:12 +0000 Subject: [PATCH 042/149] Tidy up --- src/tube-ula.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index fbadf28d..32ae4465 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -41,16 +41,8 @@ #define GPU_TUBE_REG_ADDR 0x7e0000a0 #define ARM_TUBE_REG_ADDR ((GPU_TUBE_REG_ADDR & 0x00FFFFFF) | PERIPHERAL_BASE) -#ifdef USE_GPU #include "tubevc.h" #include "startup.h" -#endif - -#ifndef USE_HW_MAILBOX -volatile uint32_t *tube_mailbox; -#endif - -#ifdef USE_GPU extern volatile uint32_t tube_regs_block[8]; static volatile uint32_t *tube_regs; @@ -67,27 +59,8 @@ static volatile uint32_t *tube_regs; #define BYTE_TO_WORD(data) ((((data) & 0x0F) << 8) | (((data) & 0xF0) << 18)) #define WORD_TO_BYTE(data) ((((data) >> 8) & 0x0F) | (((data) << 18) & 0xF0)) -#else - -extern volatile uint8_t tube_regs_block[8]; -static volatile uint8_t *tube_regs; - -#define HBIT_7 (1 << 7) -#define HBIT_6 (1 << 6) -#define HBIT_5 (1 << 5) -#define HBIT_4 (1 << 4) -#define HBIT_3 (1 << 3) -#define HBIT_2 (1 << 2) -#define HBIT_1 (1 << 1) -#define HBIT_0 (1 << 0) - -#define BYTE_TO_WORD(data) (data) -#define WORD_TO_BYTE(data) (data) - -#endif - -volatile uint32_t gpfsel_data_idle[6]; +static volatile uint32_t gpfsel_data_idle[6]; const static uint32_t magic[3] = {MAGIC_C0, MAGIC_C1, MAGIC_C2 | MAGIC_C3 }; static char copro_command =0; @@ -96,8 +69,8 @@ static perf_counters_t pct; uint8_t ph1[24],ph3_1; uint8_t hp1,hp2,hp3[2],hp4; uint8_t pstat[4]; -int ph3pos,hp3pos; -int ph1rdpos,ph1wrpos,ph1len; +uint8_t ph3pos,hp3pos; +uint8_t ph1rdpos,ph1wrpos,ph1len; // Host end of the fifos are the ones read by the tube isr #define PH1_0 tube_regs[1] From 35ea51b66152cf810fca09818d0284ce4bb93db7 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:39:42 +0000 Subject: [PATCH 043/149] Tidyup plus disable IRQs for parasite access inadvance of new FIQ handler method --- src/tube-ula.c | 53 +++++++++----------------------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 32ae4465..50dab53c 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -362,6 +362,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) uint8_t tube_parasite_read(uint32_t addr) { + int cpsr = _disable_interrupts(); uint8_t temp ; switch (addr & 7) { @@ -436,6 +437,9 @@ uint8_t tube_parasite_read(uint32_t addr) tube_index &= 0xffff; } #endif + if ((cpsr & 0xc0) != 0xc0) { + _enable_interrupts(); + } return temp; } @@ -463,6 +467,7 @@ void tube_parasite_write_banksel(uint32_t addr, uint8_t val) void tube_parasite_write(uint32_t addr, uint8_t val) { + int cpsr = _disable_interrupts(); #ifdef DEBUG_TUBE if (addr & 1) { tube_buffer[tube_index++] = TUBE_WRITE_MARKER | ((addr & 7) << 8) | val; @@ -535,6 +540,9 @@ void tube_parasite_write(uint32_t addr, uint8_t val) // tube_updateints_IRQ(); // the above can't change IRQ flag break; } + if ((cpsr & 0xc0) != 0xc0) { + _enable_interrupts(); + } } // Returns bit 0 set if IRQ is asserted by the tube @@ -686,30 +694,6 @@ void tube_init_hardware() RPI_SetGpioPinFunction(TEST3_PIN, FS_OUTPUT); #endif - // Configure GPIO to detect a rising edge of NRST - // Current code does not reqire this, as emulators poll for NRST to be released - // RPI_GpioBase->GPREN0 |= NRST_MASK; - -#ifndef USE_GPU - // Configure GPIO to detect a falling edge of NRST - RPI_GpioBase->GPFEN0 |= NRST_MASK; - // Make sure there are no pending detections - RPI_GpioBase->GPEDS0 = NRST_MASK; - - // Configure GPIO to detect a falling edge of NTUBE - RPI_GpioBase->GPFEN0 |= NTUBE_MASK; - // Make sure there are no pending detections - RPI_GpioBase->GPEDS0 = NTUBE_MASK; - - // This line enables IRQ interrupts - // Enable gpio_int[0] which is IRQ 49 - //RPI_GetIrqController()->Enable_IRQs_2 = (1 << (49 - 32)); - - // This line enables FIQ interrupts - // Enable gpio_int[0] which is IRQ 49 as FIQ - RPI_GetIrqController()->FIQ_control = 0x80 + 49; -#endif - // Initialise the UART to 57600 baud RPI_AuxMiniUartInit( 115200, 8 ); @@ -756,19 +740,8 @@ void tube_init_hardware() pct.counter[1] = 0; #endif -#ifdef USE_GPU tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; -#else - tube_regs = &tube_regs_block[0]; -#endif -#ifndef USE_HW_MAILBOX -#ifdef USE_GPU - tube_mailbox = (uint32_t *)(L2_CACHED_MEM_BASE + 0x20); -#else - tube_mailbox = &tube_mailbox_block; -#endif -#endif hp1 = hp2 = hp4 = hp3[0]= hp3[1]=0; @@ -823,11 +796,6 @@ void tube_wait_for_rst_release() { //#endif // Reset all the TUBE ULA registers tube_reset(); -#ifndef USE_HW_MAILBOX - // Clear any mailbox events that occurred during reset - // Omit this and you sometimes see a second reset logged on reset release (65tube Co Pro) - *tube_mailbox = 0; -#endif } void tube_reset_performance_counters() { @@ -873,11 +841,8 @@ void start_vc_ula() func = (int) &tubevc_asm[0]; r0 = (int) GPU_TUBE_REG_ADDR; // address of tube register block in IO space r1 = (int) &gpfsel_data_idle; // gpfsel_data_idle -#ifdef USE_HW_MAILBOX r2 = 0; -#else - r2 = (int) tube_mailbox; // tube mailbox to be replaced later with VC->ARM mailbox -#endif + r3 = (A2_PIN << 16) | (A1_PIN << 8) | (A0_PIN); // address bus GPIO mapping r4 = 0; #ifdef HAS_40PINS From 020f31bc85701c54af52d77126279ca059012d07 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:41:38 +0000 Subject: [PATCH 044/149] Fix page remapping on exit --- src/copro-65tube.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index b5704c0a..16442cd7 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -96,7 +96,7 @@ void copro_65tube_emulator() { // restore memory mapping - for ( i= 0 ; i<16; i++ ) + for ( i= 0 ; i<=16; i++ ) map_4k_page(i, i); } From bc64dd22f2d1002de09127675033149a39e607c6 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 18 Mar 2017 11:18:20 +0000 Subject: [PATCH 045/149] Debugger: Added linenoise command line editing (breaks compilation) Change-Id: Idbe29609e58daafdbb3c6667e5f440a75696ee07 --- src/CMakeLists.txt | 2 + src/debugger/linenoise.c | 1199 ++++++++++++++++++++++++++++++++++++++ src/debugger/linenoise.h | 73 +++ 3 files changed, 1274 insertions(+) create mode 100644 src/debugger/linenoise.c create mode 100644 src/debugger/linenoise.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e01ac49..23275b7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -226,6 +226,8 @@ file( GLOB copro_arm_files file( GLOB debugger_files debugger/debugger.c debugger/debugger.h + debugger/linenoise.c + debugger/linenoise.h cpu_debug.h NS32016/32016_debug.c NS32016/32016_debug.h diff --git a/src/debugger/linenoise.c b/src/debugger/linenoise.c new file mode 100644 index 00000000..fce14a7c --- /dev/null +++ b/src/debugger/linenoise.c @@ -0,0 +1,1199 @@ +/* linenoise.c -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * You can find the latest source code at: + * + * http://github.com/antirez/linenoise + * + * Does a number of crazy assumptions that happen to be true in 99.9999% of + * the 2010 UNIX computers around. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010-2016, Salvatore Sanfilippo + * Copyright (c) 2010-2013, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------------------------ + * + * References: + * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html + * + * Todo list: + * - Filter bogus Ctrl+ combinations. + * - Win32 support + * + * Bloat: + * - History search like Ctrl+r in readline? + * + * List of escape sequences used by this program, we do everything just + * with three sequences. In order to be so cheap we may have some + * flickering effect with some slow terminal, but the lesser sequences + * the more compatible. + * + * EL (Erase Line) + * Sequence: ESC [ n K + * Effect: if n is 0 or missing, clear from cursor to end of line + * Effect: if n is 1, clear from beginning of line to cursor + * Effect: if n is 2, clear entire line + * + * CUF (CUrsor Forward) + * Sequence: ESC [ n C + * Effect: moves cursor forward n chars + * + * CUB (CUrsor Backward) + * Sequence: ESC [ n D + * Effect: moves cursor backward n chars + * + * The following is used to get the terminal width if getting + * the width with the TIOCGWINSZ ioctl fails + * + * DSR (Device Status Report) + * Sequence: ESC [ 6 n + * Effect: reports the current cusor position as ESC [ n ; m R + * where n is the row and m is the column + * + * When multi line mode is enabled, we also use an additional escape + * sequence. However multi line editing is disabled by default. + * + * CUU (Cursor Up) + * Sequence: ESC [ n A + * Effect: moves cursor up of n chars. + * + * CUD (Cursor Down) + * Sequence: ESC [ n B + * Effect: moves cursor down of n chars. + * + * When linenoiseClearScreen() is called, two additional escape sequences + * are used in order to clear the screen and position the cursor at home + * position. + * + * CUP (Cursor position) + * Sequence: ESC [ H + * Effect: moves the cursor to upper left corner + * + * ED (Erase display) + * Sequence: ESC [ 2 J + * Effect: clear the whole screen + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linenoise.h" + +#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 +#define LINENOISE_MAX_LINE 4096 +static char *unsupported_term[] = {"dumb","cons25","emacs",NULL}; +static linenoiseCompletionCallback *completionCallback = NULL; +static linenoiseHintsCallback *hintsCallback = NULL; +static linenoiseFreeHintsCallback *freeHintsCallback = NULL; + +static struct termios orig_termios; /* In order to restore at exit.*/ +static int rawmode = 0; /* For atexit() function to check if restore is needed*/ +static int mlmode = 0; /* Multi line mode. Default is single line. */ +static int atexit_registered = 0; /* Register atexit just 1 time. */ +static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; +static int history_len = 0; +static char **history = NULL; + +/* The linenoiseState structure represents the state during line editing. + * We pass this state to functions implementing specific editing + * functionalities. */ +struct linenoiseState { + int ifd; /* Terminal stdin file descriptor. */ + int ofd; /* Terminal stdout file descriptor. */ + char *buf; /* Edited line buffer. */ + size_t buflen; /* Edited line buffer size. */ + const char *prompt; /* Prompt to display. */ + size_t plen; /* Prompt length. */ + size_t pos; /* Current cursor position. */ + size_t oldpos; /* Previous refresh cursor position. */ + size_t len; /* Current edited line length. */ + size_t cols; /* Number of columns in terminal. */ + size_t maxrows; /* Maximum num of rows used so far (multiline mode) */ + int history_index; /* The history index we are currently editing. */ +}; + +enum KEY_ACTION{ + KEY_NULL = 0, /* NULL */ + CTRL_A = 1, /* Ctrl+a */ + CTRL_B = 2, /* Ctrl-b */ + CTRL_C = 3, /* Ctrl-c */ + CTRL_D = 4, /* Ctrl-d */ + CTRL_E = 5, /* Ctrl-e */ + CTRL_F = 6, /* Ctrl-f */ + CTRL_H = 8, /* Ctrl-h */ + TAB = 9, /* Tab */ + CTRL_K = 11, /* Ctrl+k */ + CTRL_L = 12, /* Ctrl+l */ + ENTER = 13, /* Enter */ + CTRL_N = 14, /* Ctrl-n */ + CTRL_P = 16, /* Ctrl-p */ + CTRL_T = 20, /* Ctrl-t */ + CTRL_U = 21, /* Ctrl+u */ + CTRL_W = 23, /* Ctrl+w */ + ESC = 27, /* Escape */ + BACKSPACE = 127 /* Backspace */ +}; + +static void linenoiseAtExit(void); +int linenoiseHistoryAdd(const char *line); +static void refreshLine(struct linenoiseState *l); + +/* Debugging macro. */ +#if 0 +FILE *lndebug_fp = NULL; +#define lndebug(...) \ + do { \ + if (lndebug_fp == NULL) { \ + lndebug_fp = fopen("/tmp/lndebug.txt","a"); \ + fprintf(lndebug_fp, \ + "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \ + (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \ + (int)l->maxrows,old_rows); \ + } \ + fprintf(lndebug_fp, ", " __VA_ARGS__); \ + fflush(lndebug_fp); \ + } while (0) +#else +#define lndebug(fmt, ...) +#endif + +/* ======================= Low level terminal handling ====================== */ + +/* Set if to use or not the multi line mode. */ +void linenoiseSetMultiLine(int ml) { + mlmode = ml; +} + +/* Return true if the terminal name is in the list of terminals we know are + * not able to understand basic escape sequences. */ +static int isUnsupportedTerm(void) { + char *term = getenv("TERM"); + int j; + + if (term == NULL) return 0; + for (j = 0; unsupported_term[j]; j++) + if (!strcasecmp(term,unsupported_term[j])) return 1; + return 0; +} + +/* Raw mode: 1960 magic shit. */ +static int enableRawMode(int fd) { + struct termios raw; + + if (!isatty(STDIN_FILENO)) goto fatal; + if (!atexit_registered) { + atexit(linenoiseAtExit); + atexit_registered = 1; + } + if (tcgetattr(fd,&orig_termios) == -1) goto fatal; + + raw = orig_termios; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + /* output modes - disable post processing */ + raw.c_oflag &= ~(OPOST); + /* control modes - set 8 bit chars */ + raw.c_cflag |= (CS8); + /* local modes - choing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal; + rawmode = 1; + return 0; + +fatal: + errno = ENOTTY; + return -1; +} + +static void disableRawMode(int fd) { + /* Don't even check the return value as it's too late. */ + if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1) + rawmode = 0; +} + +/* Use the ESC [6n escape sequence to query the horizontal cursor position + * and return it. On error -1 is returned, on success the position of the + * cursor. */ +static int getCursorPosition(int ifd, int ofd) { + char buf[32]; + int cols, rows; + unsigned int i = 0; + + /* Report cursor location */ + if (write(ofd, "\x1b[6n", 4) != 4) return -1; + + /* Read the response: ESC [ rows ; cols R */ + while (i < sizeof(buf)-1) { + if (read(ifd,buf+i,1) != 1) break; + if (buf[i] == 'R') break; + i++; + } + buf[i] = '\0'; + + /* Parse it. */ + if (buf[0] != ESC || buf[1] != '[') return -1; + if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1; + return cols; +} + +/* Try to get the number of columns in the current terminal, or assume 80 + * if it fails. */ +static int getColumns(int ifd, int ofd) { + struct winsize ws; + + if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { + /* ioctl() failed. Try to query the terminal itself. */ + int start, cols; + + /* Get the initial position so we can restore it later. */ + start = getCursorPosition(ifd,ofd); + if (start == -1) goto failed; + + /* Go to right margin and get position. */ + if (write(ofd,"\x1b[999C",6) != 6) goto failed; + cols = getCursorPosition(ifd,ofd); + if (cols == -1) goto failed; + + /* Restore position. */ + if (cols > start) { + char seq[32]; + snprintf(seq,32,"\x1b[%dD",cols-start); + if (write(ofd,seq,strlen(seq)) == -1) { + /* Can't recover... */ + } + } + return cols; + } else { + return ws.ws_col; + } + +failed: + return 80; +} + +/* Clear the screen. Used to handle ctrl+l */ +void linenoiseClearScreen(void) { + if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) { + /* nothing to do, just to avoid warning. */ + } +} + +/* Beep, used for completion when there is nothing to complete or when all + * the choices were already shown. */ +static void linenoiseBeep(void) { + fprintf(stderr, "\x7"); + fflush(stderr); +} + +/* ============================== Completion ================================ */ + +/* Free a list of completion option populated by linenoiseAddCompletion(). */ +static void freeCompletions(linenoiseCompletions *lc) { + size_t i; + for (i = 0; i < lc->len; i++) + free(lc->cvec[i]); + if (lc->cvec != NULL) + free(lc->cvec); +} + +/* This is an helper function for linenoiseEdit() and is called when the + * user types the key in order to complete the string currently in the + * input. + * + * The state of the editing is encapsulated into the pointed linenoiseState + * structure as described in the structure definition. */ +static int completeLine(struct linenoiseState *ls) { + linenoiseCompletions lc = { 0, NULL }; + int nread, nwritten; + char c = 0; + + completionCallback(ls->buf,&lc); + if (lc.len == 0) { + linenoiseBeep(); + } else { + size_t stop = 0, i = 0; + + while(!stop) { + /* Show completion or original buffer */ + if (i < lc.len) { + struct linenoiseState saved = *ls; + + ls->len = ls->pos = strlen(lc.cvec[i]); + ls->buf = lc.cvec[i]; + refreshLine(ls); + ls->len = saved.len; + ls->pos = saved.pos; + ls->buf = saved.buf; + } else { + refreshLine(ls); + } + + nread = read(ls->ifd,&c,1); + if (nread <= 0) { + freeCompletions(&lc); + return -1; + } + + switch(c) { + case 9: /* tab */ + i = (i+1) % (lc.len+1); + if (i == lc.len) linenoiseBeep(); + break; + case 27: /* escape */ + /* Re-show original buffer */ + if (i < lc.len) refreshLine(ls); + stop = 1; + break; + default: + /* Update buffer and return */ + if (i < lc.len) { + nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]); + ls->len = ls->pos = nwritten; + } + stop = 1; + break; + } + } + } + + freeCompletions(&lc); + return c; /* Return last read character */ +} + +/* Register a callback function to be called for tab-completion. */ +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { + completionCallback = fn; +} + +/* Register a hits function to be called to show hits to the user at the + * right of the prompt. */ +void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) { + hintsCallback = fn; +} + +/* Register a function to free the hints returned by the hints callback + * registered with linenoiseSetHintsCallback(). */ +void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) { + freeHintsCallback = fn; +} + +/* This function is used by the callback function registered by the user + * in order to add completion options given the input string when the + * user typed . See the example.c source code for a very easy to + * understand example. */ +void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { + size_t len = strlen(str); + char *copy, **cvec; + + copy = malloc(len+1); + if (copy == NULL) return; + memcpy(copy,str,len+1); + cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1)); + if (cvec == NULL) { + free(copy); + return; + } + lc->cvec = cvec; + lc->cvec[lc->len++] = copy; +} + +/* =========================== Line editing ================================= */ + +/* We define a very simple "append buffer" structure, that is an heap + * allocated string where we can append to. This is useful in order to + * write all the escape sequences in a buffer and flush them to the standard + * output in a single call, to avoid flickering effects. */ +struct abuf { + char *b; + int len; +}; + +static void abInit(struct abuf *ab) { + ab->b = NULL; + ab->len = 0; +} + +static void abAppend(struct abuf *ab, const char *s, int len) { + char *new = realloc(ab->b,ab->len+len); + + if (new == NULL) return; + memcpy(new+ab->len,s,len); + ab->b = new; + ab->len += len; +} + +static void abFree(struct abuf *ab) { + free(ab->b); +} + +/* Helper of refreshSingleLine() and refreshMultiLine() to show hints + * to the right of the prompt. */ +void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) { + char seq[64]; + if (hintsCallback && plen+l->len < l->cols) { + int color = -1, bold = 0; + char *hint = hintsCallback(l->buf,&color,&bold); + if (hint) { + int hintlen = strlen(hint); + int hintmaxlen = l->cols-(plen+l->len); + if (hintlen > hintmaxlen) hintlen = hintmaxlen; + if (bold == 1 && color == -1) color = 37; + if (color != -1 || bold != 0) + snprintf(seq,64,"\033[%d;%d;49m",bold,color); + abAppend(ab,seq,strlen(seq)); + abAppend(ab,hint,hintlen); + if (color != -1 || bold != 0) + abAppend(ab,"\033[0m",4); + /* Call the function to free the hint returned. */ + if (freeHintsCallback) freeHintsCallback(hint); + } + } +} + +/* Single line low level line refresh. + * + * Rewrite the currently edited line accordingly to the buffer content, + * cursor position, and number of columns of the terminal. */ +static void refreshSingleLine(struct linenoiseState *l) { + char seq[64]; + size_t plen = strlen(l->prompt); + int fd = l->ofd; + char *buf = l->buf; + size_t len = l->len; + size_t pos = l->pos; + struct abuf ab; + + while((plen+pos) >= l->cols) { + buf++; + len--; + pos--; + } + while (plen+len > l->cols) { + len--; + } + + abInit(&ab); + /* Cursor to left edge */ + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + /* Write the prompt and the current buffer content */ + abAppend(&ab,l->prompt,strlen(l->prompt)); + abAppend(&ab,buf,len); + /* Show hits if any. */ + refreshShowHints(&ab,l,plen); + /* Erase to right */ + snprintf(seq,64,"\x1b[0K"); + abAppend(&ab,seq,strlen(seq)); + /* Move cursor to original position. */ + snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen)); + abAppend(&ab,seq,strlen(seq)); + if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ + abFree(&ab); +} + +/* Multi line low level line refresh. + * + * Rewrite the currently edited line accordingly to the buffer content, + * cursor position, and number of columns of the terminal. */ +static void refreshMultiLine(struct linenoiseState *l) { + char seq[64]; + int plen = strlen(l->prompt); + int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */ + int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */ + int rpos2; /* rpos after refresh. */ + int col; /* colum position, zero-based. */ + int old_rows = l->maxrows; + int fd = l->ofd, j; + struct abuf ab; + + /* Update maxrows if needed. */ + if (rows > (int)l->maxrows) l->maxrows = rows; + + /* First step: clear all the lines used before. To do so start by + * going to the last row. */ + abInit(&ab); + if (old_rows-rpos > 0) { + lndebug("go down %d", old_rows-rpos); + snprintf(seq,64,"\x1b[%dB", old_rows-rpos); + abAppend(&ab,seq,strlen(seq)); + } + + /* Now for every row clear it, go up. */ + for (j = 0; j < old_rows-1; j++) { + lndebug("clear+up"); + snprintf(seq,64,"\r\x1b[0K\x1b[1A"); + abAppend(&ab,seq,strlen(seq)); + } + + /* Clean the top line. */ + lndebug("clear"); + snprintf(seq,64,"\r\x1b[0K"); + abAppend(&ab,seq,strlen(seq)); + + /* Write the prompt and the current buffer content */ + abAppend(&ab,l->prompt,strlen(l->prompt)); + abAppend(&ab,l->buf,l->len); + + /* Show hits if any. */ + refreshShowHints(&ab,l,plen); + + /* If we are at the very end of the screen with our prompt, we need to + * emit a newline and move the prompt to the first column. */ + if (l->pos && + l->pos == l->len && + (l->pos+plen) % l->cols == 0) + { + lndebug(""); + abAppend(&ab,"\n",1); + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + rows++; + if (rows > (int)l->maxrows) l->maxrows = rows; + } + + /* Move cursor to right position. */ + rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */ + lndebug("rpos2 %d", rpos2); + + /* Go up till we reach the expected positon. */ + if (rows-rpos2 > 0) { + lndebug("go-up %d", rows-rpos2); + snprintf(seq,64,"\x1b[%dA", rows-rpos2); + abAppend(&ab,seq,strlen(seq)); + } + + /* Set column. */ + col = (plen+(int)l->pos) % (int)l->cols; + lndebug("set col %d", 1+col); + if (col) + snprintf(seq,64,"\r\x1b[%dC", col); + else + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + + lndebug("\n"); + l->oldpos = l->pos; + + if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ + abFree(&ab); +} + +/* Calls the two low level functions refreshSingleLine() or + * refreshMultiLine() according to the selected mode. */ +static void refreshLine(struct linenoiseState *l) { + if (mlmode) + refreshMultiLine(l); + else + refreshSingleLine(l); +} + +/* Insert the character 'c' at cursor current position. + * + * On error writing to the terminal -1 is returned, otherwise 0. */ +int linenoiseEditInsert(struct linenoiseState *l, char c) { + if (l->len < l->buflen) { + if (l->len == l->pos) { + l->buf[l->pos] = c; + l->pos++; + l->len++; + l->buf[l->len] = '\0'; + if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) { + /* Avoid a full update of the line in the + * trivial case. */ + if (write(l->ofd,&c,1) == -1) return -1; + } else { + refreshLine(l); + } + } else { + memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos); + l->buf[l->pos] = c; + l->len++; + l->pos++; + l->buf[l->len] = '\0'; + refreshLine(l); + } + } + return 0; +} + +/* Move cursor on the left. */ +void linenoiseEditMoveLeft(struct linenoiseState *l) { + if (l->pos > 0) { + l->pos--; + refreshLine(l); + } +} + +/* Move cursor on the right. */ +void linenoiseEditMoveRight(struct linenoiseState *l) { + if (l->pos != l->len) { + l->pos++; + refreshLine(l); + } +} + +/* Move cursor to the start of the line. */ +void linenoiseEditMoveHome(struct linenoiseState *l) { + if (l->pos != 0) { + l->pos = 0; + refreshLine(l); + } +} + +/* Move cursor to the end of the line. */ +void linenoiseEditMoveEnd(struct linenoiseState *l) { + if (l->pos != l->len) { + l->pos = l->len; + refreshLine(l); + } +} + +/* Substitute the currently edited line with the next or previous history + * entry as specified by 'dir'. */ +#define LINENOISE_HISTORY_NEXT 0 +#define LINENOISE_HISTORY_PREV 1 +void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) { + if (history_len > 1) { + /* Update the current history entry before to + * overwrite it with the next one. */ + free(history[history_len - 1 - l->history_index]); + history[history_len - 1 - l->history_index] = strdup(l->buf); + /* Show the new entry */ + l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1; + if (l->history_index < 0) { + l->history_index = 0; + return; + } else if (l->history_index >= history_len) { + l->history_index = history_len-1; + return; + } + strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen); + l->buf[l->buflen-1] = '\0'; + l->len = l->pos = strlen(l->buf); + refreshLine(l); + } +} + +/* Delete the character at the right of the cursor without altering the cursor + * position. Basically this is what happens with the "Delete" keyboard key. */ +void linenoiseEditDelete(struct linenoiseState *l) { + if (l->len > 0 && l->pos < l->len) { + memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1); + l->len--; + l->buf[l->len] = '\0'; + refreshLine(l); + } +} + +/* Backspace implementation. */ +void linenoiseEditBackspace(struct linenoiseState *l) { + if (l->pos > 0 && l->len > 0) { + memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos); + l->pos--; + l->len--; + l->buf[l->len] = '\0'; + refreshLine(l); + } +} + +/* Delete the previosu word, maintaining the cursor at the start of the + * current word. */ +void linenoiseEditDeletePrevWord(struct linenoiseState *l) { + size_t old_pos = l->pos; + size_t diff; + + while (l->pos > 0 && l->buf[l->pos-1] == ' ') + l->pos--; + while (l->pos > 0 && l->buf[l->pos-1] != ' ') + l->pos--; + diff = old_pos - l->pos; + memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1); + l->len -= diff; + refreshLine(l); +} + +/* This function is the core of the line editing capability of linenoise. + * It expects 'fd' to be already in "raw mode" so that every key pressed + * will be returned ASAP to read(). + * + * The resulting string is put into 'buf' when the user type enter, or + * when ctrl+d is typed. + * + * The function returns the length of the current buffer. */ +static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) +{ + struct linenoiseState l; + + /* Populate the linenoise state that we pass to functions implementing + * specific editing functionalities. */ + l.ifd = stdin_fd; + l.ofd = stdout_fd; + l.buf = buf; + l.buflen = buflen; + l.prompt = prompt; + l.plen = strlen(prompt); + l.oldpos = l.pos = 0; + l.len = 0; + l.cols = getColumns(stdin_fd, stdout_fd); + l.maxrows = 0; + l.history_index = 0; + + /* Buffer starts empty. */ + l.buf[0] = '\0'; + l.buflen--; /* Make sure there is always space for the nulterm */ + + /* The latest history entry is always our current buffer, that + * initially is just an empty string. */ + linenoiseHistoryAdd(""); + + if (write(l.ofd,prompt,l.plen) == -1) return -1; + while(1) { + char c; + int nread; + char seq[3]; + + nread = read(l.ifd,&c,1); + if (nread <= 0) return l.len; + + /* Only autocomplete when the callback is set. It returns < 0 when + * there was an error reading from fd. Otherwise it will return the + * character that should be handled next. */ + if (c == 9 && completionCallback != NULL) { + c = completeLine(&l); + /* Return on errors */ + if (c < 0) return l.len; + /* Read next character when 0 */ + if (c == 0) continue; + } + + switch(c) { + case ENTER: /* enter */ + history_len--; + free(history[history_len]); + if (mlmode) linenoiseEditMoveEnd(&l); + if (hintsCallback) { + /* Force a refresh without hints to leave the previous + * line as the user typed it after a newline. */ + linenoiseHintsCallback *hc = hintsCallback; + hintsCallback = NULL; + refreshLine(&l); + hintsCallback = hc; + } + return (int)l.len; + case CTRL_C: /* ctrl-c */ + errno = EAGAIN; + return -1; + case BACKSPACE: /* backspace */ + case 8: /* ctrl-h */ + linenoiseEditBackspace(&l); + break; + case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the + line is empty, act as end-of-file. */ + if (l.len > 0) { + linenoiseEditDelete(&l); + } else { + history_len--; + free(history[history_len]); + return -1; + } + break; + case CTRL_T: /* ctrl-t, swaps current character with previous. */ + if (l.pos > 0 && l.pos < l.len) { + int aux = buf[l.pos-1]; + buf[l.pos-1] = buf[l.pos]; + buf[l.pos] = aux; + if (l.pos != l.len-1) l.pos++; + refreshLine(&l); + } + break; + case CTRL_B: /* ctrl-b */ + linenoiseEditMoveLeft(&l); + break; + case CTRL_F: /* ctrl-f */ + linenoiseEditMoveRight(&l); + break; + case CTRL_P: /* ctrl-p */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); + break; + case CTRL_N: /* ctrl-n */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); + break; + case ESC: /* escape sequence */ + /* Read the next two bytes representing the escape sequence. + * Use two calls to handle slow terminals returning the two + * chars at different times. */ + if (read(l.ifd,seq,1) == -1) break; + if (read(l.ifd,seq+1,1) == -1) break; + + /* ESC [ sequences. */ + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + /* Extended escape, read additional byte. */ + if (read(l.ifd,seq+2,1) == -1) break; + if (seq[2] == '~') { + switch(seq[1]) { + case '3': /* Delete key. */ + linenoiseEditDelete(&l); + break; + } + } + } else { + switch(seq[1]) { + case 'A': /* Up */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); + break; + case 'B': /* Down */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); + break; + case 'C': /* Right */ + linenoiseEditMoveRight(&l); + break; + case 'D': /* Left */ + linenoiseEditMoveLeft(&l); + break; + case 'H': /* Home */ + linenoiseEditMoveHome(&l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(&l); + break; + } + } + } + + /* ESC O sequences. */ + else if (seq[0] == 'O') { + switch(seq[1]) { + case 'H': /* Home */ + linenoiseEditMoveHome(&l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(&l); + break; + } + } + break; + default: + if (linenoiseEditInsert(&l,c)) return -1; + break; + case CTRL_U: /* Ctrl+u, delete the whole line. */ + buf[0] = '\0'; + l.pos = l.len = 0; + refreshLine(&l); + break; + case CTRL_K: /* Ctrl+k, delete from current to end of line. */ + buf[l.pos] = '\0'; + l.len = l.pos; + refreshLine(&l); + break; + case CTRL_A: /* Ctrl+a, go to the start of the line */ + linenoiseEditMoveHome(&l); + break; + case CTRL_E: /* ctrl+e, go to the end of the line */ + linenoiseEditMoveEnd(&l); + break; + case CTRL_L: /* ctrl+l, clear screen */ + linenoiseClearScreen(); + refreshLine(&l); + break; + case CTRL_W: /* ctrl+w, delete previous word */ + linenoiseEditDeletePrevWord(&l); + break; + } + } + return l.len; +} + +/* This special mode is used by linenoise in order to print scan codes + * on screen for debugging / development purposes. It is implemented + * by the linenoise_example program using the --keycodes option. */ +void linenoisePrintKeyCodes(void) { + char quit[4]; + + printf("Linenoise key codes debugging mode.\n" + "Press keys to see scan codes. Type 'quit' at any time to exit.\n"); + if (enableRawMode(STDIN_FILENO) == -1) return; + memset(quit,' ',4); + while(1) { + char c; + int nread; + + nread = read(STDIN_FILENO,&c,1); + if (nread <= 0) continue; + memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */ + quit[sizeof(quit)-1] = c; /* Insert current char on the right. */ + if (memcmp(quit,"quit",sizeof(quit)) == 0) break; + + printf("'%c' %02x (%d) (type quit to exit)\n", + isprint(c) ? c : '?', (int)c, (int)c); + printf("\r"); /* Go left edge manually, we are in raw mode. */ + fflush(stdout); + } + disableRawMode(STDIN_FILENO); +} + +/* This function calls the line editing function linenoiseEdit() using + * the STDIN file descriptor set in raw mode. */ +static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { + int count; + + if (buflen == 0) { + errno = EINVAL; + return -1; + } + + if (enableRawMode(STDIN_FILENO) == -1) return -1; + count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt); + disableRawMode(STDIN_FILENO); + printf("\n"); + return count; +} + +/* This function is called when linenoise() is called with the standard + * input file descriptor not attached to a TTY. So for example when the + * program using linenoise is called in pipe or with a file redirected + * to its standard input. In this case, we want to be able to return the + * line regardless of its length (by default we are limited to 4k). */ +static char *linenoiseNoTTY(void) { + char *line = NULL; + size_t len = 0, maxlen = 0; + + while(1) { + if (len == maxlen) { + if (maxlen == 0) maxlen = 16; + maxlen *= 2; + char *oldval = line; + line = realloc(line,maxlen); + if (line == NULL) { + if (oldval) free(oldval); + return NULL; + } + } + int c = fgetc(stdin); + if (c == EOF || c == '\n') { + if (c == EOF && len == 0) { + free(line); + return NULL; + } else { + line[len] = '\0'; + return line; + } + } else { + line[len] = c; + len++; + } + } +} + +/* The high level function that is the main API of the linenoise library. + * This function checks if the terminal has basic capabilities, just checking + * for a blacklist of stupid terminals, and later either calls the line + * editing function or uses dummy fgets() so that you will be able to type + * something even in the most desperate of the conditions. */ +char *linenoise(const char *prompt) { + char buf[LINENOISE_MAX_LINE]; + int count; + + if (!isatty(STDIN_FILENO)) { + /* Not a tty: read from file / pipe. In this mode we don't want any + * limit to the line size, so we call a function to handle that. */ + return linenoiseNoTTY(); + } else if (isUnsupportedTerm()) { + size_t len; + + printf("%s",prompt); + fflush(stdout); + if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL; + len = strlen(buf); + while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) { + len--; + buf[len] = '\0'; + } + return strdup(buf); + } else { + count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt); + if (count == -1) return NULL; + return strdup(buf); + } +} + +/* This is just a wrapper the user may want to call in order to make sure + * the linenoise returned buffer is freed with the same allocator it was + * created with. Useful when the main program is using an alternative + * allocator. */ +void linenoiseFree(void *ptr) { + free(ptr); +} + +/* ================================ History ================================= */ + +/* Free the history, but does not reset it. Only used when we have to + * exit() to avoid memory leaks are reported by valgrind & co. */ +static void freeHistory(void) { + if (history) { + int j; + + for (j = 0; j < history_len; j++) + free(history[j]); + free(history); + } +} + +/* At exit we'll try to fix the terminal to the initial conditions. */ +static void linenoiseAtExit(void) { + disableRawMode(STDIN_FILENO); + freeHistory(); +} + +/* This is the API call to add a new entry in the linenoise history. + * It uses a fixed array of char pointers that are shifted (memmoved) + * when the history max length is reached in order to remove the older + * entry and make room for the new one, so it is not exactly suitable for huge + * histories, but will work well for a few hundred of entries. + * + * Using a circular buffer is smarter, but a bit more complex to handle. */ +int linenoiseHistoryAdd(const char *line) { + char *linecopy; + + if (history_max_len == 0) return 0; + + /* Initialization on first call. */ + if (history == NULL) { + history = malloc(sizeof(char*)*history_max_len); + if (history == NULL) return 0; + memset(history,0,(sizeof(char*)*history_max_len)); + } + + /* Don't add duplicated lines. */ + if (history_len && !strcmp(history[history_len-1], line)) return 0; + + /* Add an heap allocated copy of the line in the history. + * If we reached the max length, remove the older line. */ + linecopy = strdup(line); + if (!linecopy) return 0; + if (history_len == history_max_len) { + free(history[0]); + memmove(history,history+1,sizeof(char*)*(history_max_len-1)); + history_len--; + } + history[history_len] = linecopy; + history_len++; + return 1; +} + +/* Set the maximum length for the history. This function can be called even + * if there is already some history, the function will make sure to retain + * just the latest 'len' elements if the new history length value is smaller + * than the amount of items already inside the history. */ +int linenoiseHistorySetMaxLen(int len) { + char **new; + + if (len < 1) return 0; + if (history) { + int tocopy = history_len; + + new = malloc(sizeof(char*)*len); + if (new == NULL) return 0; + + /* If we can't copy everything, free the elements we'll not use. */ + if (len < tocopy) { + int j; + + for (j = 0; j < tocopy-len; j++) free(history[j]); + tocopy = len; + } + memset(new,0,sizeof(char*)*len); + memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy); + free(history); + history = new; + } + history_max_len = len; + if (history_len > history_max_len) + history_len = history_max_len; + return 1; +} + +/* Save the history in the specified file. On success 0 is returned + * otherwise -1 is returned. */ +int linenoiseHistorySave(const char *filename) { + mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO); + FILE *fp; + int j; + + fp = fopen(filename,"w"); + umask(old_umask); + if (fp == NULL) return -1; + chmod(filename,S_IRUSR|S_IWUSR); + for (j = 0; j < history_len; j++) + fprintf(fp,"%s\n",history[j]); + fclose(fp); + return 0; +} + +/* Load the history from the specified file. If the file does not exist + * zero is returned and no operation is performed. + * + * If the file exists and the operation succeeded 0 is returned, otherwise + * on error -1 is returned. */ +int linenoiseHistoryLoad(const char *filename) { + FILE *fp = fopen(filename,"r"); + char buf[LINENOISE_MAX_LINE]; + + if (fp == NULL) return -1; + + while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { + char *p; + + p = strchr(buf,'\r'); + if (!p) p = strchr(buf,'\n'); + if (p) *p = '\0'; + linenoiseHistoryAdd(buf); + } + fclose(fp); + return 0; +} diff --git a/src/debugger/linenoise.h b/src/debugger/linenoise.h new file mode 100644 index 00000000..ed20232c --- /dev/null +++ b/src/debugger/linenoise.h @@ -0,0 +1,73 @@ +/* linenoise.h -- VERSION 1.0 + * + * Guerrilla line editing library against the idea that a line editing lib + * needs to be 20,000 lines of C code. + * + * See linenoise.c for more information. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010-2014, Salvatore Sanfilippo + * Copyright (c) 2010-2013, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINENOISE_H +#define __LINENOISE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct linenoiseCompletions { + size_t len; + char **cvec; +} linenoiseCompletions; + +typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); +typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); +typedef void(linenoiseFreeHintsCallback)(void *); +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); +void linenoiseSetHintsCallback(linenoiseHintsCallback *); +void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); +void linenoiseAddCompletion(linenoiseCompletions *, const char *); + +char *linenoise(const char *prompt); +void linenoiseFree(void *ptr); +int linenoiseHistoryAdd(const char *line); +int linenoiseHistorySetMaxLen(int len); +int linenoiseHistorySave(const char *filename); +int linenoiseHistoryLoad(const char *filename); +void linenoiseClearScreen(void); +void linenoiseSetMultiLine(int ml); +void linenoisePrintKeyCodes(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LINENOISE_H */ From f406379f6eb49998dc1fba5609f237299eb89692 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 18 Mar 2017 12:49:38 +0000 Subject: [PATCH 046/149] Debugger: reworked linenoise to suite a character based invocation model Change-Id: If2c16a60b4096281986bf188973927c35ded6375 --- src/debugger/debugger.c | 33 +++- src/debugger/linenoise.c | 331 +++++++++++++++++++++++++-------------- src/debugger/linenoise.h | 2 + 3 files changed, 247 insertions(+), 119 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 414f7d2c..4562b6ac 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -4,12 +4,18 @@ #include #include "debugger.h" +#include "linenoise.h" + #include "../rpi-aux.h" #include "../cpu_debug.h" #include "../mame/arm_debug.h" #include "../NS32016/32016_debug.h" +#define USE_LINENOISE + +static const char * prompt_str = ">> "; + extern unsigned int copro; cpu_debug_t *cpu_debug_list[] = { @@ -142,7 +148,7 @@ static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { static char strbuf[1000]; -static char cmd[1000]; +//static char cmd[1000]; static volatile int stopped = 0; @@ -173,9 +179,10 @@ static void noprompt() { } static void prompt() { - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite('>'); - RPI_AuxMiniUartWrite(' '); + int i; + for (i = 0; i < strlen(prompt_str); i++) { + RPI_AuxMiniUartWrite(prompt_str[i]); + } } static void cpu_stop() { @@ -652,6 +659,22 @@ static void dispatchCmd(char *cmd) { * External interface ********************************************************/ + +#ifdef USE_LINENOISE + +void debugger_rx_char(char c) { + char *buf = linenoise_async_rxchar(c, prompt_str); + if (buf) { + printf("\r\n"); + if (buf[0]) { + dispatchCmd(buf); + } + prompt(); + } +} + +#else + void debugger_rx_char(char c) { static int i = 0; if (c == 8) { @@ -682,3 +705,5 @@ void debugger_rx_char(char c) { cmd[i++] = c; } } + +#endif diff --git a/src/debugger/linenoise.c b/src/debugger/linenoise.c index fce14a7c..9e8c198d 100644 --- a/src/debugger/linenoise.c +++ b/src/debugger/linenoise.c @@ -103,7 +103,10 @@ * */ +#ifdef DMB_DISABLE #include +#endif + #include #include #include @@ -113,7 +116,11 @@ #include #include #include + +#ifdef DMB_DISABLE #include +#endif + #include #include "linenoise.h" @@ -124,10 +131,12 @@ static linenoiseCompletionCallback *completionCallback = NULL; static linenoiseHintsCallback *hintsCallback = NULL; static linenoiseFreeHintsCallback *freeHintsCallback = NULL; +#ifdef DMB_DISABLE static struct termios orig_termios; /* In order to restore at exit.*/ static int rawmode = 0; /* For atexit() function to check if restore is needed*/ -static int mlmode = 0; /* Multi line mode. Default is single line. */ static int atexit_registered = 0; /* Register atexit just 1 time. */ +#endif +static int mlmode = 0; /* Multi line mode. Default is single line. */ static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; static int history_len = 0; static char **history = NULL; @@ -172,7 +181,10 @@ enum KEY_ACTION{ BACKSPACE = 127 /* Backspace */ }; +#ifdef DMB_DISABLE static void linenoiseAtExit(void); +#endif + int linenoiseHistoryAdd(const char *line); static void refreshLine(struct linenoiseState *l); @@ -215,6 +227,7 @@ static int isUnsupportedTerm(void) { } /* Raw mode: 1960 magic shit. */ +#ifdef DMB_DISABLE static int enableRawMode(int fd) { struct termios raw; @@ -315,6 +328,7 @@ static int getColumns(int ifd, int ofd) { failed: return 80; } +#endif /* Clear the screen. Used to handle ctrl+l */ void linenoiseClearScreen(void) { @@ -765,77 +779,134 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) { * when ctrl+d is typed. * * The function returns the length of the current buffer. */ -static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) -{ - struct linenoiseState l; +static int linenoiseInitLine(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) { /* Populate the linenoise state that we pass to functions implementing * specific editing functionalities. */ - l.ifd = stdin_fd; - l.ofd = stdout_fd; - l.buf = buf; - l.buflen = buflen; - l.prompt = prompt; - l.plen = strlen(prompt); - l.oldpos = l.pos = 0; - l.len = 0; - l.cols = getColumns(stdin_fd, stdout_fd); - l.maxrows = 0; - l.history_index = 0; + l->ifd = stdin_fd; + l->ofd = stdout_fd; + l->buf = buf; + l->buflen = buflen; + l->prompt = prompt; + l->plen = strlen(prompt); + l->oldpos = l->pos = 0; + l->len = 0; +#ifdef DMB_DISABLE + l->cols = getColumns(stdin_fd, stdout_fd); +#else + l->cols = 80; +#endif + l->maxrows = 0; + l->history_index = 0; /* Buffer starts empty. */ - l.buf[0] = '\0'; - l.buflen--; /* Make sure there is always space for the nulterm */ + l->buf[0] = '\0'; + l->buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); - if (write(l.ofd,prompt,l.plen) == -1) return -1; - while(1) { - char c; - int nread; - char seq[3]; + if (write(l->ofd,prompt,l->plen) == -1) return -1; - nread = read(l.ifd,&c,1); - if (nread <= 0) return l.len; + return 0; +} - /* Only autocomplete when the callback is set. It returns < 0 when - * there was an error reading from fd. Otherwise it will return the - * character that should be handled next. */ - if (c == 9 && completionCallback != NULL) { - c = completeLine(&l); - /* Return on errors */ - if (c < 0) return l.len; - /* Read next character when 0 */ - if (c == 0) continue; - } +static int linenoiseProcessChar(struct linenoiseState *l, char c) { + + static int esc_state = 0; + static char seq[3]; + + if (esc_state) { + + /* Read the next two bytes representing the escape sequence. + * Use two calls to handle slow terminals returning the two + * chars at different times. */ + + seq[esc_state - 1] = c; + + if (esc_state == 1) { + esc_state = 2; + + } else if (esc_state == 2) { + esc_state = 0; + + /* ESC [ sequences. */ + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + /* Extended escape, read additional byte. */ + esc_state = 3; + } else { + switch(seq[1]) { + case 'A': /* Up */ + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); + break; + case 'B': /* Down */ + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); + break; + case 'C': /* Right */ + linenoiseEditMoveRight(l); + break; + case 'D': /* Left */ + linenoiseEditMoveLeft(l); + break; + case 'H': /* Home */ + linenoiseEditMoveHome(l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(l); + break; + } + } + /* ESC O sequences. */ + } else if (seq[0] == 'O') { + switch(seq[1]) { + case 'H': /* Home */ + linenoiseEditMoveHome(l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(l); + break; + } + } + + } else if (esc_state == 3) { + esc_state = 0; + if (seq[2] == '~') { + switch(seq[1]) { + case '3': /* Delete key. */ + linenoiseEditDelete(l); + break; + } + } + } + } else { switch(c) { case ENTER: /* enter */ history_len--; free(history[history_len]); - if (mlmode) linenoiseEditMoveEnd(&l); + if (mlmode) linenoiseEditMoveEnd(l); if (hintsCallback) { /* Force a refresh without hints to leave the previous * line as the user typed it after a newline. */ linenoiseHintsCallback *hc = hintsCallback; hintsCallback = NULL; - refreshLine(&l); + refreshLine(l); hintsCallback = hc; } - return (int)l.len; + return (int)l->len; case CTRL_C: /* ctrl-c */ errno = EAGAIN; return -1; case BACKSPACE: /* backspace */ case 8: /* ctrl-h */ - linenoiseEditBackspace(&l); + linenoiseEditBackspace(l); break; case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the line is empty, act as end-of-file. */ - if (l.len > 0) { - linenoiseEditDelete(&l); + if (l->len > 0) { + linenoiseEditDelete(l); } else { history_len--; free(history[history_len]); @@ -843,115 +914,101 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, } break; case CTRL_T: /* ctrl-t, swaps current character with previous. */ - if (l.pos > 0 && l.pos < l.len) { - int aux = buf[l.pos-1]; - buf[l.pos-1] = buf[l.pos]; - buf[l.pos] = aux; - if (l.pos != l.len-1) l.pos++; - refreshLine(&l); + if (l->pos > 0 && l->pos < l->len) { + int aux = l->buf[l->pos-1]; + l->buf[l->pos-1] = l->buf[l->pos]; + l->buf[l->pos] = aux; + if (l->pos != l->len-1) l->pos++; + refreshLine(l); } break; case CTRL_B: /* ctrl-b */ - linenoiseEditMoveLeft(&l); + linenoiseEditMoveLeft(l); break; case CTRL_F: /* ctrl-f */ - linenoiseEditMoveRight(&l); + linenoiseEditMoveRight(l); break; case CTRL_P: /* ctrl-p */ - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); break; case CTRL_N: /* ctrl-n */ - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); break; case ESC: /* escape sequence */ - /* Read the next two bytes representing the escape sequence. - * Use two calls to handle slow terminals returning the two - * chars at different times. */ - if (read(l.ifd,seq,1) == -1) break; - if (read(l.ifd,seq+1,1) == -1) break; - - /* ESC [ sequences. */ - if (seq[0] == '[') { - if (seq[1] >= '0' && seq[1] <= '9') { - /* Extended escape, read additional byte. */ - if (read(l.ifd,seq+2,1) == -1) break; - if (seq[2] == '~') { - switch(seq[1]) { - case '3': /* Delete key. */ - linenoiseEditDelete(&l); - break; - } - } - } else { - switch(seq[1]) { - case 'A': /* Up */ - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); - break; - case 'B': /* Down */ - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); - break; - case 'C': /* Right */ - linenoiseEditMoveRight(&l); - break; - case 'D': /* Left */ - linenoiseEditMoveLeft(&l); - break; - case 'H': /* Home */ - linenoiseEditMoveHome(&l); - break; - case 'F': /* End*/ - linenoiseEditMoveEnd(&l); - break; - } - } - } - - /* ESC O sequences. */ - else if (seq[0] == 'O') { - switch(seq[1]) { - case 'H': /* Home */ - linenoiseEditMoveHome(&l); - break; - case 'F': /* End*/ - linenoiseEditMoveEnd(&l); - break; - } - } - break; + esc_state = 1; + break; default: - if (linenoiseEditInsert(&l,c)) return -1; + if (linenoiseEditInsert(l,c)) return -1; break; case CTRL_U: /* Ctrl+u, delete the whole line. */ - buf[0] = '\0'; - l.pos = l.len = 0; - refreshLine(&l); + l->buf[0] = '\0'; + l->pos = l->len = 0; + refreshLine(l); break; case CTRL_K: /* Ctrl+k, delete from current to end of line. */ - buf[l.pos] = '\0'; - l.len = l.pos; - refreshLine(&l); + l->buf[l->pos] = '\0'; + l->len = l->pos; + refreshLine(l); break; case CTRL_A: /* Ctrl+a, go to the start of the line */ - linenoiseEditMoveHome(&l); + linenoiseEditMoveHome(l); break; case CTRL_E: /* ctrl+e, go to the end of the line */ - linenoiseEditMoveEnd(&l); + linenoiseEditMoveEnd(l); break; case CTRL_L: /* ctrl+l, clear screen */ linenoiseClearScreen(); - refreshLine(&l); + refreshLine(l); break; case CTRL_W: /* ctrl+w, delete previous word */ - linenoiseEditDeletePrevWord(&l); + linenoiseEditDeletePrevWord(l); break; } } + + return -2; +} + +static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) +{ + + struct linenoiseState l; + + if (linenoiseInitLine(&l, stdin_fd, stdout_fd, buf, buflen, prompt) == -1) return -1; + + while(1) { + char c; + int nread; + int ret; + + nread = read(l.ifd,&c,1); + if (nread <= 0) return l.len; + + /* Only autocomplete when the callback is set. It returns < 0 when + * there was an error reading from fd. Otherwise it will return the + * character that should be handled next. */ + if (c == 9 && completionCallback != NULL) { + c = completeLine(&l); + /* Return on errors */ + if (c < 0) return l.len; + /* Read next character when 0 */ + if (c == 0) continue; + } + + ret = linenoiseProcessChar(&l, c); + + if (ret != -2) { + return ret; + } + + } return l.len; } /* This special mode is used by linenoise in order to print scan codes * on screen for debugging / development purposes. It is implemented * by the linenoise_example program using the --keycodes option. */ +#ifdef DMB_DISABLE void linenoisePrintKeyCodes(void) { char quit[4]; @@ -976,6 +1033,7 @@ void linenoisePrintKeyCodes(void) { } disableRawMode(STDIN_FILENO); } +#endif /* This function calls the line editing function linenoiseEdit() using * the STDIN file descriptor set in raw mode. */ @@ -987,9 +1045,13 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { return -1; } +#ifdef DMB_DISABLE if (enableRawMode(STDIN_FILENO) == -1) return -1; +#endif count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt); +#ifdef DMB_DISABLE disableRawMode(STDIN_FILENO); +#endif printf("\n"); return count; } @@ -1074,6 +1136,7 @@ void linenoiseFree(void *ptr) { /* Free the history, but does not reset it. Only used when we have to * exit() to avoid memory leaks are reported by valgrind & co. */ +#ifdef DMB_DISABLE static void freeHistory(void) { if (history) { int j; @@ -1083,12 +1146,15 @@ static void freeHistory(void) { free(history); } } +#endif /* At exit we'll try to fix the terminal to the initial conditions. */ +#ifdef DMB_DISABLE static void linenoiseAtExit(void) { disableRawMode(STDIN_FILENO); freeHistory(); } +#endif /* This is the API call to add a new entry in the linenoise history. * It uses a fixed array of char pointers that are shifted (memmoved) @@ -1197,3 +1263,38 @@ int linenoiseHistoryLoad(const char *filename) { fclose(fp); return 0; } + + +/* ========================= Asynchronous Interface ========================= */ + +static char ln_buf[LINENOISE_MAX_LINE]; + +char *linenoise_async_rxchar(char c, const char *prompt) { + + static int initmode = 1; + static int initline = 1; + static struct linenoiseState l; + + if (initmode) { + initmode = 0; + } + + if (initline) { + linenoiseInitLine(&l, STDIN_FILENO, STDOUT_FILENO, ln_buf, sizeof(ln_buf), prompt); + refreshLine(&l); + initline = 0; + } + + int ret = linenoiseProcessChar(&l, c); + + if (ret == -2) { + return NULL; + } else if (ret == -1) { + printf("An error has occurred in linenoise\r\n"); + return NULL; + } else { + initline = 1; + linenoiseHistoryAdd(ln_buf); + return ln_buf; + } +} diff --git a/src/debugger/linenoise.h b/src/debugger/linenoise.h index ed20232c..7b4c13be 100644 --- a/src/debugger/linenoise.h +++ b/src/debugger/linenoise.h @@ -66,6 +66,8 @@ void linenoiseClearScreen(void); void linenoiseSetMultiLine(int ml); void linenoisePrintKeyCodes(void); +char *linenoise_async_rxchar(char c, const char *prompt); + #ifdef __cplusplus } #endif From 7e927c9920b5ff4d700f641cc3175dee8af9c6a2 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:53:18 +0000 Subject: [PATCH 047/149] remove unused variable --- src/tube-ula.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 50dab53c..8a15a57c 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -44,7 +44,6 @@ #include "tubevc.h" #include "startup.h" -extern volatile uint32_t tube_regs_block[8]; static volatile uint32_t *tube_regs; #define HBIT_7 (1 << 25) From 7a926fe342d51d0242b30dd1239857c9d147dfcb Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 12:54:43 +0000 Subject: [PATCH 048/149] remove unused variable --- src/tube.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube.S b/src/tube.S index c290d1ba..a4ece537 100644 --- a/src/tube.S +++ b/src/tube.S @@ -4,7 +4,7 @@ #define instrREG r7 .text -.global tube_mailbox_block + .global arm_irq_handler .global arm_fiq_handler From e53a104ef10de762c01f543176ed5736524ff2f0 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 18 Mar 2017 13:36:12 +0000 Subject: [PATCH 049/149] Debugger: Improved presentation of branches in ARM disassembler Change-Id: Ie8a61b46723fa6e803c5cb812484c901e49f1b3a --- src/darm/darm.c | 19 ++++--------------- src/darm/darm.h | 6 ++++++ src/mame/arm_debug.c | 13 ++++++++++--- src/tube-commands.c | 10 +++++++--- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/darm/darm.c b/src/darm/darm.c index b04b1673..3acaa0f0 100644 --- a/src/darm/darm.c +++ b/src/darm/darm.c @@ -63,8 +63,7 @@ static int _append_imm(char *arg, uint32_t imm) { const char *start = arg; if(imm > 0x1000) { - *arg++ = '0'; - *arg++ = 'x'; + *arg++ = '&'; arg += _utoa(imm, arg, 16); } else { @@ -440,19 +439,9 @@ int darm_str(const darm_t *d, darm_str_t *str) // branch stuff has been initialized yet if(d->instr == I_BLX && d->H == B_INVLD) break; - // check whether the immediate is negative - int32_t imm = d->imm; - if(imm < 0 && imm >= -0x1000) { - APPEND(args[arg], "#+-"); - imm = -imm; - } - else if(d->U == B_UNSET) { - APPEND(args[arg], "#+-"); - } - else { - APPEND(args[arg], "#+"); - } - args[arg] += _append_imm(args[arg], imm); + uint32_t target = (d->addr + 8 + d->imm) & d->addr_mask; + *args[arg]++ = '&'; + args[arg] += _utoa(target, args[arg], 16); continue; case 'M': diff --git a/src/darm/darm.h b/src/darm/darm.h index c31331fa..c7ffa71e 100644 --- a/src/darm/darm.h +++ b/src/darm/darm.h @@ -87,6 +87,12 @@ typedef struct _darm_t { // the original encoded instruction uint32_t w; + // the original address + uint32_t addr; + + // the original address + uint32_t addr_mask; + // the instruction label darm_instr_t instr; darm_enctype_t instr_type; diff --git a/src/mame/arm_debug.c b/src/mame/arm_debug.c index 0434f478..f2b7f489 100644 --- a/src/mame/arm_debug.c +++ b/src/mame/arm_debug.c @@ -108,9 +108,16 @@ static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { int len = snprintf(buf, bufsize, "%08"PRIx32" %08"PRIx32" ", addr, instr); buf += len; bufsize -= len; - if(darm_armv7_disasm(&dis, instr) == 0 && darm_str2(&dis, &dis_str, 0) == 0) { - strncpy(buf, dis_str.total, bufsize); - } else { + int ok = 0; + if (darm_armv7_disasm(&dis, instr) == 0) { + dis.addr = addr; + dis.addr_mask = ADDRESS_MASK; + if (darm_str2(&dis, &dis_str, 1) == 0) { + strncpy(buf, dis_str.total, bufsize); + ok = 1; + } + } + if (!ok) { strncpy(buf, "???", bufsize); } return addr + 4; diff --git a/src/tube-commands.c b/src/tube-commands.c index 46820621..b1c2bdbf 100644 --- a/src/tube-commands.c +++ b/src/tube-commands.c @@ -175,9 +175,13 @@ int doCmdDis(char *params) { do { for (i = 0; i < 16; i++) { opcode = *(unsigned int *)memAddr; - sprintf(line, "%08X %08X ***\r\n", memAddr, opcode); - if(darm_armv7_disasm(&d, opcode) == 0 && darm_str2(&d, &str, 0) == 0) { - sprintf(line + 18, "%s\r\n", str.total); + sprintf(line, "%08X %08X ***\r\n", memAddr, opcode); + if(darm_armv7_disasm(&d, opcode) == 0) { + d.addr = memAddr; + d.addr_mask = 0xFFFFFFC; + if (darm_str2(&d, &str, 0) == 0) { + sprintf(line + 18, "%s\r\n", str.total); + } } OS_Write0(line); memAddr += 4; From 9e2ecca22c05477c6f39d64bc2aea39e34082b93 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 14:46:30 +0000 Subject: [PATCH 050/149] remove unused label --- src/tube.S | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tube.S b/src/tube.S index a4ece537..e71b2519 100644 --- a/src/tube.S +++ b/src/tube.S @@ -16,7 +16,6 @@ CACHELINE_ALIGN = 5 .align CACHELINE_ALIGN -isr_code_start: // Default handlers for FIQ/IRQ do nothing From 3f99fbd1cc6931375b14e6a8ec915e96747808c2 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 14:54:20 +0000 Subject: [PATCH 051/149] Remove unused definitions --- src/tube.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/tube.h b/src/tube.h index 81f843af..e644cc43 100644 --- a/src/tube.h +++ b/src/tube.h @@ -11,14 +11,6 @@ extern volatile unsigned int copro_speed; extern int arm_speed; -extern volatile uint32_t *tube_mailbox; - -extern volatile uint32_t tube_mailbox_block; - -extern void arm_fiq_handler_flag0(); - extern void arm_fiq_handler_flag1(); -extern void lock_isr(); - #endif From ac0e5a47cb469cb7f9a214fef4fc0cf6b7f07364 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 14:58:01 +0000 Subject: [PATCH 052/149] Remove old definitions --- src/tube-ula.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/tube-ula.h b/src/tube-ula.h index 20f76974..31c2a9df 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -43,11 +43,7 @@ extern void tube_reset_performance_counters(); extern void tube_log_performance_counters(); -#ifdef USE_GPU extern void start_vc_ula(); -#endif - -#ifdef USE_HW_MAILBOX static volatile inline int is_mailbox_non_empty() { return !((*(volatile uint32_t *)MBOX0_STATUS) & MBOX0_EMPTY); @@ -57,20 +53,5 @@ static volatile inline unsigned int read_mailbox() { return (*(volatile uint32_t *)MBOX0_READ); } -#else - -extern volatile uint32_t *tube_mailbox; - -static volatile inline int is_mailbox_non_empty() { - return *tube_mailbox & ATTN_MASK; -} - -static volatile inline unsigned int read_mailbox() { - unsigned int tube_mailbox_copy = *tube_mailbox; - *tube_mailbox &= ~(ATTN_MASK | OVERRUN_MASK); - return tube_mailbox_copy; -} - -#endif #endif From d37eda4cd397c1798861468b1df459a5940c37d3 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 16:11:43 +0000 Subject: [PATCH 053/149] move tube_enable into tube_irq --- src/tube-ula.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 8a15a57c..e624e88a 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -90,12 +90,22 @@ uint8_t ph1rdpos,ph1wrpos,ph1len; #define PSTAT3 pstat[2] #define PSTAT4 pstat[3] -#ifdef DEBUG_TRANSFERS -uint32_t checksum_h = 0; -uint32_t count_h = 0; -uint32_t checksum_p = 0; -uint32_t count_p = 0; -#endif + +// +// bit 7 Selects if R7 is used to inform the copro of an interupt event used for fast 6502 +// bit 6 Selects if direct native arm irq are used +// bit 5 native arm irq lock +// bit 3 tube_enable +// bit 2 Reset event +// bit 1 NMI +// bit 0 IRQ +#define FAST6502_BIT 128 +#define NATIVEARM_BIT 64 +#define nativearmlock_bit 32 +#define TUBE_ENABLE_BIT 8 +#define RESET_BIT 4 +#define NMI_BIT 2 +#define IRQ_BIT 1 // The current Tube IRQ/NMI state is maintained in a global that the emulation code can see // @@ -105,8 +115,6 @@ uint32_t count_p = 0; int tube_irq; -static int tube_enabled; - #ifdef DEBUG_TUBE #define TUBE_READ_MARKER 0x80000000 @@ -180,7 +188,7 @@ void copro_command_excute(unsigned char copro_command,unsigned char val) static void tube_reset() { - tube_enabled = 1; + tube_irq |= TUBE_ENABLE_BIT; tube_irq &= ~(4+2+1); hp3pos = 0; ph1rdpos = ph1wrpos = ph1len = 0; @@ -263,7 +271,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) { case 0: /*Register 1 stat*/ - if (!tube_enabled) + if (!(tube_irq& TUBE_ENABLE_BIT)) return; if (val & 0x80) { @@ -276,7 +284,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); } - tube_irq = 0; + tube_irq &= ~(IRQ_BIT + NMI_BIT); if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= 1; if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= 1; if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=2; @@ -584,7 +592,7 @@ int tube_io_handler(uint32_t mail) } else { tube_host_read(addr); } - if ((tube_enabled && (HSTAT1 & HBIT_5))) { + if (((tube_irq& TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5))) { return tube_irq | 4; } else { return tube_irq & 3; @@ -753,7 +761,7 @@ int tube_is_rst_active() { unsigned int tube_mailbox_copy = read_mailbox(); tube_io_handler(tube_mailbox_copy); } - return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || (tube_enabled && (HSTAT1 & HBIT_5)); + return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || ((tube_irq & TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5)); } #if 0 static void tube_wait_for_rst_active() { @@ -825,7 +833,7 @@ void tube_log_performance_counters() { void disable_tube() { int i; - tube_enabled = 0; + tube_irq &= ~TUBE_ENABLE_BIT; for (i = 0; i < 8; i++) { tube_regs[i] = 0xfe; } From f37caa2cefe295df16ff54c5d34ad247048f7811 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 16:16:40 +0000 Subject: [PATCH 054/149] Add flag to enable fast IRQ/NMI signalling in faster 6502 core --- src/copro-65tubeasm.S | 4 +++- src/tube-ula.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 3b0e146a..69dc3843 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1375,7 +1375,7 @@ exec_65tube: #else mov memry, #0xFFFFFF00 #endif - + BL tube_enable_fast6502 ldr instt, =opcode_jump_table // set instt (r12) to the base address of the 6502 instruction handler ldr tregs, =(0x0000fee0 >> 5) // initialize the constant in tregs @@ -1432,6 +1432,7 @@ handle_rst: exec_65tube_exit: // We get here from the Event handler when RST is detected + mov r0, #0 // disable mailbox hardware to generate interrupts ldr r1, =MBOX0_CONFIG // when data is present str r0, [r1] @@ -1440,6 +1441,7 @@ exec_65tube_exit: // We get here from the Event handler wh str r0, [r1] msr CPSR, r2 // re-enable ARM interrupts + bl tube_disable_fast6502 pop {r4-r11,pc} // 6502 Event handler diff --git a/src/tube-ula.c b/src/tube-ula.c index e624e88a..e9eff050 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -167,6 +167,22 @@ static void tube_updateints_NMI() if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=2; } */ +void tube_enable_fast6502(void) +{ + int cpsr = _disable_interrupts(); + tube_irq |= FAST6502_BIT; + if ((cpsr & 0xc0) != 0xc0) { + _enable_interrupts(); + } +} +void tube_disable_fast6502(void) +{ + int cpsr = _disable_interrupts(); + tube_irq &= ~FAST6502_BIT; + if ((cpsr & 0xc0) != 0xc0) { + _enable_interrupts(); + } +} void copro_command_excute(unsigned char copro_command,unsigned char val) { switch (copro_command) From 95ae23420da001c263fa85c966696b1eb7b6bc2f Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 16:42:55 +0000 Subject: [PATCH 055/149] Move reset code / preparing for New FIQ code --- src/copro-65tubeasm.S | 3 +++ src/tube-ula.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 69dc3843..ed2fd23d 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1469,6 +1469,9 @@ Event_Handler: push {r2-r3,r12} // r0 contains the tube mailbox value bl tube_io_handler pop {r2-r3,r12} + + ldr r0, =tube_irq // Move higher for better pipelining + ldrb r0, [r0] tst r0, #4 // Bit 2 set indicate RST is active bne exec_65tube_exit // exit immediately if active edge seen diff --git a/src/tube-ula.c b/src/tube-ula.c index e9eff050..4cdb4032 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -300,6 +300,11 @@ static void tube_host_write(uint16_t addr, uint8_t val) } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); } + if ( HSTAT1 & HBIT_5) { + tube_irq |= RESET_BIT; + } else { + tube_irq &= ~RESET_BIT; + } tube_irq &= ~(IRQ_BIT + NMI_BIT); if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= 1; if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= 1; @@ -599,7 +604,10 @@ int tube_io_handler(uint32_t mail) #ifdef USE_GPU if ((mail >> 12) & 1) // Check for Reset - return tube_irq | 4; // Set reset Flag + { + tube_irq |= RESET_BIT; + return tube_irq; // Set reset Flag + } else { addr = (mail>>8) & 7; @@ -608,11 +616,9 @@ int tube_io_handler(uint32_t mail) } else { tube_host_read(addr); } - if (((tube_irq& TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5))) { - return tube_irq | 4; - } else { - return tube_irq & 3; - } + + return tube_irq ; + } #else addr = 0; From 9ec0857f760f42053781aea756eeb42316dcead2 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 18 Mar 2017 19:04:56 +0000 Subject: [PATCH 056/149] move variable to be with others --- src/tube-ula.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 4cdb4032..697b2499 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -70,6 +70,8 @@ uint8_t hp1,hp2,hp3[2],hp4; uint8_t pstat[4]; uint8_t ph3pos,hp3pos; uint8_t ph1rdpos,ph1wrpos,ph1len; +int tube_irq; + // Host end of the fifos are the ones read by the tube isr #define PH1_0 tube_regs[1] @@ -113,7 +115,6 @@ uint8_t ph1rdpos,ph1wrpos,ph1len; // Bit 1 is the tube asserting nmi // Bit 2 is the tube asserting reset -int tube_irq; #ifdef DEBUG_TUBE From 6fc9817a82b437c1955e658d7934dcac82da2e9f Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 07:17:58 +0000 Subject: [PATCH 057/149] TubeHandler Now in FIQ ( C version) Fast6502 only --- src/copro-65tube.c | 3 +-- src/copro-65tubeasm.S | 62 +++++-------------------------------------- src/tube-client.c | 11 ++++++++ src/tube-ula.c | 17 ++++++------ src/tube.S | 38 +++++++++++++++++++------- 5 files changed, 54 insertions(+), 77 deletions(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index 16442cd7..bcaa419c 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -56,7 +56,6 @@ static void copro_65tube_reset(unsigned char mpu_memory[]) { tube_wait_for_rst_release(); } -#define FIQ_VECTOR (HIGH_VECTORS_BASE + 0x3C) void copro_65tube_emulator() { // Remember the current copro so we can exit if it changes @@ -72,7 +71,6 @@ void copro_65tube_emulator() { for (i = 0; i < 256; i++) { Event_Handler_Dispatch_Table[i] = (uint32_t) (copro == COPRO_65TUBE_1 ? Event_Handler_Single_Core_Slow : Event_Handler); } - *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; mpu_memory = copro_65tube_poweron_reset(); @@ -87,6 +85,7 @@ void copro_65tube_emulator() { #endif tube_reset_performance_counters(); exec_65tube(mpu_memory, copro == COPRO_65TUBE_1 ? 1 : 0); + tube_log_performance_counters(); #ifdef HISTOGRAM copro_65tube_dump_histogram(); diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index ed2fd23d..087d09dc 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1404,18 +1404,6 @@ exec_65tube: str r0,targettime noslowsetup: - mov r0, #MBOX0_DATAIRQEN // if the slow flag is not set, then enable mailbox hardware - ldr r1, =MBOX0_CONFIG // to generate interrupts when data is present - str r0, [r1] - mov r0, #0x80 + 65 // route that to FIQ - ldr r1, =FIQCTRL - str r0, [r1] - - - mrs r0, CPSR // Enable ARM IRQs and FIQs - bic r0, r0, #ARM_INT_MASK - msr CPSR_c, r0 - handle_rst: orr flags, flags, #4 // Set the I bit bic flags, flags, #8 // Clear the D bit @@ -1430,16 +1418,7 @@ handle_rst: #endif FETCH_NEXT_3B_MERGED SUBPC // Start executing instructions -exec_65tube_exit: // We get here from the Event handler when RST is detected - - - mov r0, #0 // disable mailbox hardware to generate interrupts - ldr r1, =MBOX0_CONFIG // when data is present - str r0, [r1] - mov r0, #0 // disable FIQ - ldr r1, =FIQCTRL - str r0, [r1] - +exec_65tube_exit: // We get here from the Event handler when RST is detected msr CPSR, r2 // re-enable ARM interrupts bl tube_disable_fast6502 pop {r4-r11,pc} @@ -1449,29 +1428,12 @@ exec_65tube_exit: // We get here from the Event handler wh // if USE_MULTICORE is not defined, we have come here via a branch from the second instruction table Event_Handler: + ldr r0, =tube_irq mrs r2, CPSR // preserve the 6502 flags - orr r1, r2, #ARM_INT_MASK // disable ARM IRQs and FIQs - msr CPSR_c, r1 - - //ldr r1, =FIQCTRL - //mov r0, #0 - //str r0, [r1] - - ldr r1, =FIQCTRL // Re-enable ARM Mailbox FIQ interrupt - mov r0, #0xC1 // It's safe to do this before reading the mailbox - str r0, [r1] // As ARM FIQ interrupts currently disabled - ldr r1, =MBOX0_READ - ldr r0, [r1] - + bic instt, instt, #1024 // ack events + ldrb r0, [r0] sub regPC, regPC, #2 // set the instruction back as we haven't executed it - - push {r2-r3,r12} // r0 contains the tube mailbox value - bl tube_io_handler - pop {r2-r3,r12} - - ldr r0, =tube_irq // Move higher for better pipelining - ldrb r0, [r0] tst r0, #4 // Bit 2 set indicate RST is active bne exec_65tube_exit // exit immediately if active edge seen @@ -1535,26 +1497,14 @@ targettime: // we restore the modified table base pointer so we will re-enter this handler Event_Handler_Single_Core_Slow: + ldr r0, =tube_irq mrs r2, CPSR // preserve the 6502 flags // interrupts are left enabled bic instt, instt, #1024 // ack any events + ldrb r0,[r0] sub regPC, regPC, #2 // set the instruction back as we haven't executed it - ldr r1, =MBOX0_STATUS // poll the hardware mailbox status - ldr r0, [r1] - tst r0, #MBOX0_EMPTY // test if there are any messages - bne noirq2 - - ldr r1, =MBOX0_READ // read the top message off the mailbox - ldr r0, [r1] - - - - push {r2-r3,r12} // r0 contains the tube mailbox value - bl tube_io_handler - pop {r2-r3,r12} - tst r0, #4 // Bit 2 set indicate RST is active bne exec_65tube_exit // exit immediately if active edge seen diff --git a/src/tube-client.c b/src/tube-client.c index 9903dd49..5ce9f158 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -108,6 +108,17 @@ unsigned char * copro_mem_reset(int length) void init_emulator() { _disable_interrupts(); + + // Set up FIQ handler + + tube_irq = 0; // Make sure everything is clear + *((uint32_t *) FIQ_VECTOR) = (uint32_t) arm_fiq_handler_flag1; + + // Direct Mail box to FIQ handler + + (*(volatile uint32_t *)MBOX0_CONFIG) = MBOX0_DATAIRQEN; + (*(volatile uint32_t *)FIQCTRL) = 0x80 +65; + #ifndef MINIMAL_BUILD if (copro == COPRO_ARMNATIVE) { diff --git a/src/tube-ula.c b/src/tube-ula.c index 697b2499..780b5b46 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -586,7 +586,7 @@ int tube_io_handler(uint32_t mail) int rnw; int ntube; int nrst; - + #ifdef USE_HW_MAILBOX // Sequence numbers are currently 4 bits, and are stored in bits 12..15 int act_seq_num; @@ -617,7 +617,7 @@ int tube_io_handler(uint32_t mail) } else { tube_host_read(addr); } - + return tube_irq ; } @@ -780,10 +780,10 @@ void tube_init_hardware() int tube_is_rst_active() { // It's necessary to keep servicing the tube_mailbox // otherwise a software reset sequence won't get handled properly - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - tube_io_handler(tube_mailbox_copy); - } + //if (is_mailbox_non_empty()) { + // unsigned int tube_mailbox_copy = read_mailbox(); + // tube_io_handler(tube_mailbox_copy); + // } return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || ((tube_irq & TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5)); } #if 0 @@ -861,8 +861,6 @@ void disable_tube() { tube_regs[i] = 0xfe; } } - -#ifdef USE_GPU // todo : we need to sort out caches memory map etc here void start_vc_ula() { int func,r0,r1, r2,r3,r4,r5; @@ -912,5 +910,6 @@ void start_vc_ula() // LOG_DEBUG("%08x ?\r\n", r0); // } // } + } -#endif + diff --git a/src/tube.S b/src/tube.S index e71b2519..0026cba2 100644 --- a/src/tube.S +++ b/src/tube.S @@ -2,7 +2,6 @@ #include "tube-defs.h" #define instrREG r7 - .text .global arm_irq_handler @@ -10,6 +9,21 @@ .global arm_fiq_handler_flag1 +// +// bit 7 Selects if R7 is used to inform the copro of an interupt event used for fast 6502 +// bit 6 Selects if direct native arm irq are used +// bit 5 native arm irq lock +// bit 3 tube_enable +// bit 2 Reset event +// bit 1 NMI +// bit 0 IRQ +#define FAST6502_BIT 128 +#define NATIVEARM_BIT 64 +#define nativearmlock_bit 32 +#define TUBE_ENABLE_BIT 8 +#define RESET_BIT 4 +#define NMI_BIT 2 +#define IRQ_BIT 1 // ================================================= // ISR CODE // ================================================= @@ -26,14 +40,18 @@ arm_irq_handler: // ARM FIQ handler arm_fiq_handler_flag1: - // Disable the FIQ interrupt (the C code will re-enable) - // This is necessary because we don't want the FIQ handler to have to read - // the mailbox, so the FIQ condition will not be cleared until later - ldr r8, =FIQCTRL - mov r9, #0 - str r9, [r8] + ldr r12, =MBOX0_READ // Read the GPU mailbox + push {r0-r7,r14} + ldr r0, [r12] // Get Mailbox data + + BL tube_io_handler + ldr r10,=tube_irq + pop {r0-r7,r14} + ldr r10,[r10] + tst r10, #FAST6502_BIT // see if we should signal the 6502 Core + tstne r10,#RESET_BIT+NMI_BIT+IRQ_BIT + orrne instrREG, instrREG, #1024 - orr instrREG, instrREG, #1024 // signal event to 6502 instruction flow - - subs pc, lr, #4 + + subs pc, lr, #4 From b1d6dcce1de6831f6371868925d8fdf2fe6c23f4 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 07:58:02 +0000 Subject: [PATCH 058/149] make copros use new FIQ code --- src/copro-32016.c | 6 ++---- src/copro-65tubeasm.S | 2 ++ src/copro-80186.c | 21 +++++++++---------- src/copro-arm2.c | 15 +++++++------ src/copro-lib6502.c | 49 +++++++++++++++++++++---------------------- src/copro-mc6809.c | 15 +++++++------ src/copro-mc6809nc.c | 17 +++++++-------- src/copro-mc6809sc.c | 17 +++++++-------- src/copro-null.c | 10 +++------ src/copro-z80.c | 21 +++++++++---------- 10 files changed, 80 insertions(+), 93 deletions(-) diff --git a/src/copro-32016.c b/src/copro-32016.c index f4045e83..01be9552 100644 --- a/src/copro-32016.c +++ b/src/copro-32016.c @@ -48,10 +48,8 @@ void copro_32016_emulator() { // might need to reduce if we see LATEs tubecycles = 8; n32016_exec(); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int rst = intr & 4; + if (tube_irq & 7) { + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 087d09dc..1969cea7 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1504,6 +1504,8 @@ Event_Handler_Single_Core_Slow: bic instt, instt, #1024 // ack any events ldrb r0,[r0] sub regPC, regPC, #2 // set the instruction back as we haven't executed it + tst r0,#7 + beq noirq2 tst r0, #4 // Bit 2 set indicate RST is active bne exec_65tube_exit // exit immediately if active edge seen diff --git a/src/copro-80186.c b/src/copro-80186.c index 2d6109cc..c870bc39 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -47,11 +47,9 @@ void copro_80186_emulator() { exec86(1); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq & 7) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -65,12 +63,13 @@ void copro_80186_emulator() intcall86(2); } last_rst = rst; - } - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - if (ifl) { - intcall86(12); - } + + // IRQ is level sensitive, so check between every instruction + if (tube_irq & 1) { + if (ifl) { + intcall86(12); + } + } } } } diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 67ce0bba..b2111606 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -157,11 +157,9 @@ void copro_arm2_emulator() while (1) { arm2_execute_run(1); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq & 7) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -175,8 +173,9 @@ void copro_arm2_emulator() arm2_execute_set_input(ARM_FIRQ_LINE, 1); } last_rst = rst; - } - // IRQ is level sensitive, so check between every instruction - arm2_execute_set_input(ARM_IRQ_LINE, tube_irq & 1); + + // IRQ is level sensitive, so check between every instruction + arm2_execute_set_input(ARM_IRQ_LINE, tube_irq & 1); + } } } diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index ef607390..d159d9d0 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -54,33 +54,32 @@ static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { static int last_copro; static int copro_lib6502_poll(M6502 *mpu) { - static unsigned int last_rst = 0; - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; - // Reset the processor on a rst going inactive - if (rst && !last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - return 1; - } + static unsigned int last_rst = 0; + if (tube_irq & 7) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; + // Reset the processor on a rst going inactive + if (rst && !last_rst) { + // Exit if the copro has changed + if (copro != last_copro) { + return 1; + } copro_lib6502_reset(mpu); - } - // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { - M6502_nmi(mpu); - } - last_rst = rst; + } + // NMI is edge sensitive, so only check after mailbox activity + if (nmi) { + M6502_nmi(mpu); + } + last_rst = rst; + + // IRQ is level sensitive, so check between every instruction + if (tube_irq & 1) { + if (!(mpu->registers->p & 4)) { + M6502_irq(mpu); + } + } } - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - if (!(mpu->registers->p & 4)) { - M6502_irq(mpu); - } - } - return 0; + return 0; } void copro_lib6502_emulator() { diff --git a/src/copro-mc6809.c b/src/copro-mc6809.c index 99c0a24f..fb55fa12 100644 --- a/src/copro-mc6809.c +++ b/src/copro-mc6809.c @@ -106,11 +106,9 @@ void copro_mc6809_emulator() mc6809->run(mc6809); MC6809_IRQ_SET(mc6809, 0); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq & 7) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -125,8 +123,9 @@ void copro_mc6809_emulator() } last_rst = rst; + + // IRQ is level sensitive, so check between every instruction + MC6809_FIRQ_SET(mc6809, tube_irq & 1); } - // IRQ is level sensitive, so check between every instruction - MC6809_FIRQ_SET(mc6809, tube_irq & 1); - } + } } diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 55be2968..d0278914 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -91,11 +91,9 @@ void copro_mc6809nc_emulator() // Execute emulator for one instruction mc6809nc_execute(1); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq & 7) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -110,10 +108,11 @@ void copro_mc6809nc_emulator() } last_rst = rst; - } + // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - mc6809nc_request_firq(1); - } + if (tube_irq & 1) { + mc6809nc_request_firq(1); + } + } } } diff --git a/src/copro-mc6809sc.c b/src/copro-mc6809sc.c index 9123c546..667deb9b 100644 --- a/src/copro-mc6809sc.c +++ b/src/copro-mc6809sc.c @@ -129,14 +129,10 @@ void copro_mc6809sc_emulator() mc6809_step(&cpu); } - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - if (intr) { - cpu.sync = 0; - } - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq &7) { + cpu.sync = 0; + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -151,8 +147,9 @@ void copro_mc6809sc_emulator() } last_rst = rst; + + // IRQ is level sensitive, so check between every instruction + cpu.firq = tube_irq & 1; } - // IRQ is level sensitive, so check between every instruction - cpu.firq = tube_irq & 1; } } diff --git a/src/copro-null.c b/src/copro-null.c index 0acc8689..d8b6ac59 100644 --- a/src/copro-null.c +++ b/src/copro-null.c @@ -25,15 +25,11 @@ void copro_null_emulator() { // Wait for copro to be changed via *FX 151,230,N // then exit on the next reset while (1) { - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - // With tube disabled, only writes to reg 6 are implements - // which update the copro global variable - tube_io_handler(tube_mailbox_copy); - // Exit on a change of copro + + // Exit on a change of copro ( changed in the FIQ handler) if (copro != last_copro) { return; - } + } } } diff --git a/src/copro-z80.c b/src/copro-z80.c index 716c7405..bcf10eae 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -338,11 +338,9 @@ void copro_z80_emulator() // Execute emulator for one instruction simz80_execute(1); - if (is_mailbox_non_empty()) { - unsigned int tube_mailbox_copy = read_mailbox(); - unsigned int intr = tube_io_handler(tube_mailbox_copy); - unsigned int nmi = intr & 2; - unsigned int rst = intr & 4; + if (tube_irq & 7 ) { + unsigned int nmi = tube_irq & 2; + unsigned int rst = tube_irq & 4; // Reset the processor on active edge of rst if (rst && !last_rst) { // Exit if the copro has changed @@ -357,12 +355,13 @@ void copro_z80_emulator() simz80_NMI(); } last_rst = rst; - } - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - // check if the emulator IRQ is enabled - if (simz80_is_IRQ_enabled()) { - simz80_IRQ(); + + // IRQ is level sensitive, so check between every instruction + if (tube_irq & 1) { + // check if the emulator IRQ is enabled + if (simz80_is_IRQ_enabled()) { + simz80_IRQ(); + } } } } From 2ad41d6abeb6271a87625e3320e684cb49af38f9 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 08:09:31 +0000 Subject: [PATCH 059/149] remove old code --- src/copro-65tubeasm.S | 48 ++----------------------------------------- src/tube-isr.c | 18 +--------------- src/tube-ula.c | 6 ------ src/tube-ula.h | 9 -------- 4 files changed, 3 insertions(+), 78 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 1969cea7..416c8915 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -95,7 +95,7 @@ .equ Z_FLAG, 0x40000000 .equ C_FLAG, 0x20000000 -.equ ARM_INT_MASK,0xC0 + // Mask used when poping status into flags (RTI, PLP) // It selects the bits that are managed in flags, i.e. V, D, I @@ -103,52 +103,12 @@ // bits 31-8 are emulator control bits .equ R4_MASK, 0xFFFFFF4C -// Emulator control bits -#if defined(USE_MULTICORE) || !defined(USE_HW_MAILBOX) -.equ SLOW_FLAG, 0x00000100 -#endif + // ********************************************** // Start of macros // ********************************************** -#if defined(USE_MULTICORE) || !defined(USE_HW_MAILBOX) - -.macro FETCH_NEXT_STAGE_0_I -.endm - -.macro FETCH_NEXT_STAGE_2_I - b fetch_next_i -.endm - -// Macros for fetching the next instruction, for two and three byte instructions - -.macro FETCH_NEXT_STAGE_0 -.endm - -.macro FETCH_NEXT_STAGE_1 -.endm - -.macro FETCH_NEXT_STAGE_2 - b fetch_next -.endm - -.macro FETCH_NEXT_STAGE_12 - b fetch_next -.endm - -.macro FETCH_NEXT_STAGE_012 - b fetch_next -.endm - -// Macro for fetching the next instruction and also checking for any pending IRQs -// Used for instructions that can enable interrupts: CLI, PLP, RTI -.macro FETCH_NEXT_CHECK_IRQ - b fetch_next_check_irq -.endm - -#else - // one byte instructions .macro FETCH_NEXT_STAGE_0_I @@ -263,8 +223,6 @@ msr CPSR_flg, r2 // Restore the 6502 flags .endm -#endif - // Macro for pushing a byte to the stack, whilst correctly handing wrapping // This relies on the 6502 memory being 64KB aligned // Optimisations from dp11 on stardot @@ -1075,7 +1033,6 @@ opcode_jump_table: // End of Opcode Jump Table // ********************************************** -#if !defined(USE_MULTICORE) && defined(USE_HW_MAILBOX) // ********************************************** // Start of Event Handler Jump Table // ********************************************** @@ -1089,7 +1046,6 @@ Event_Handler_Dispatch_Table: // ********************************************** // End of Event Handler Jump Table // ********************************************** -#endif // ********************************************** // Instruction timings diff --git a/src/tube-isr.c b/src/tube-isr.c index 1734093c..3fdc7bf4 100644 --- a/src/tube-isr.c +++ b/src/tube-isr.c @@ -77,28 +77,12 @@ void copro_armnative_tube_interrupt_handler(uint32_t mail) { int ntube; int nrst; int unexpected = 0; -#ifdef USE_GPU + addr = (mail>>8) & 7; rnw = ( (mail >>11 ) & 1); nrst = !((mail >> 12) & 1) ; ntube = ((mail >> 12) & 1) ; -#else - addr = 0; - if (mail & A0_MASK) { - addr += 1; - } - if (mail & A1_MASK) { - addr += 2; - } - if (mail & A2_MASK) { - addr += 4; - } - rnw = (mail >> RNW_PIN) & 1; - ntube = (mail >> NTUBE_PIN) & 1; - nrst = (mail >> NRST_PIN) & 1; -#endif - // Handle a reset if (nrst == 0) { state = IDLE; diff --git a/src/tube-ula.c b/src/tube-ula.c index 780b5b46..240fc957 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -778,12 +778,6 @@ void tube_init_hardware() } int tube_is_rst_active() { - // It's necessary to keep servicing the tube_mailbox - // otherwise a software reset sequence won't get handled properly - //if (is_mailbox_non_empty()) { - // unsigned int tube_mailbox_copy = read_mailbox(); - // tube_io_handler(tube_mailbox_copy); - // } return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || ((tube_irq & TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5)); } #if 0 diff --git a/src/tube-ula.h b/src/tube-ula.h index 31c2a9df..17e2f024 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -45,13 +45,4 @@ extern void tube_log_performance_counters(); extern void start_vc_ula(); -static volatile inline int is_mailbox_non_empty() { - return !((*(volatile uint32_t *)MBOX0_STATUS) & MBOX0_EMPTY); -} - -static volatile inline unsigned int read_mailbox() { - return (*(volatile uint32_t *)MBOX0_READ); -} - - #endif From 1a843c4e28cbca8160d91b4c79a3dce11a01f18c Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 19 Mar 2017 15:22:53 +0000 Subject: [PATCH 060/149] Serial: fixed a hang when 64KB tx buffer full Change-Id: I1c51010f2b946aaab6b5b206374ca9caee906e20 --- src/rpi-aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index df78e009..a4676985 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -32,8 +32,8 @@ aux_t* RPI_GetAux(void) #define IRQ_VECTOR 0x38 static char tx_buffer[TX_BUFFER_SIZE]; -static int tx_head; -static int tx_tail; +static volatile int tx_head; +static volatile int tx_tail; static void __attribute__((interrupt("IRQ"))) RPI_AuxMiniUartIRQHandler() { From cfa4ca08495b76470c7f032fbebddd313599adc6 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 19 Mar 2017 15:29:03 +0000 Subject: [PATCH 061/149] Tube ULA: Make tube_irq a volatile Change-Id: I6892ce1f51f470aedb57e1513a035ecc6beb3bcf --- src/NS32016/32016.h | 2 +- src/tube-ula.c | 2 +- src/tube-ula.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 65276b2d..1db38f10 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -377,7 +377,7 @@ static inline void PiTRACE(const char *fmt, ...) {} #define PiWARN(...) { printf("pc=%08"PRIX32": ",n32016_get_pc()); printf(__VA_ARGS__); } extern int tubecycles; -extern int tube_irq; +extern volatile int tube_irq; extern uint32_t genaddr[2]; extern int gentype[2]; extern const uint8_t FormatSizes[FormatCount + 1]; diff --git a/src/tube-ula.c b/src/tube-ula.c index 240fc957..01aa523f 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -70,7 +70,7 @@ uint8_t hp1,hp2,hp3[2],hp4; uint8_t pstat[4]; uint8_t ph3pos,hp3pos; uint8_t ph1rdpos,ph1wrpos,ph1len; -int tube_irq; +volatile int tube_irq; // Host end of the fifos are the ones read by the tube isr diff --git a/src/tube-ula.h b/src/tube-ula.h index 17e2f024..97eb1b9d 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -13,7 +13,7 @@ // Uncomment to log all tube FIFO reads/writes (excluding status only) // #define DEBUG_TUBE -extern int tube_irq; +extern volatile int tube_irq; extern void disable_tube(); From a5282a123a5b5f84f11a320709d6c76a63168565 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 19 Mar 2017 15:28:17 +0000 Subject: [PATCH 062/149] Co Pro Z80: Fix issue that caused hang in DEBUG mode Change-Id: I39b0f7aaa6ab7f9c7489f4f766317366551c2d03 --- src/NS32016/32016.h | 6 ++++++ src/yaze/simz80.c | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 1db38f10..f338b880 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -377,7 +377,13 @@ static inline void PiTRACE(const char *fmt, ...) {} #define PiWARN(...) { printf("pc=%08"PRIX32": ",n32016_get_pc()); printf(__VA_ARGS__); } extern int tubecycles; + +#ifdef BEM +extern int tube_irq; +#else extern volatile int tube_irq; +#endif + extern uint32_t genaddr[2]; extern int gentype[2]; extern const uint8_t FormatSizes[FormatCount + 1]; diff --git a/src/yaze/simz80.c b/src/yaze/simz80.c index 4f33c5fa..43f7ac71 100644 --- a/src/yaze/simz80.c +++ b/src/yaze/simz80.c @@ -84,10 +84,6 @@ static const unsigned char partab[256] = { #define parity(x) partab[(x)&0xff] -#ifdef DEBUG -volatile int stopsim; -#endif - #define POP(x) do { \ FASTREG y = GetBYTE_pp(SP); \ x = y + (GetBYTE_pp(SP) << 8); \ @@ -160,11 +156,7 @@ simz80_execute(int n) FASTREG tmp2; #endif -#ifdef DEBUG - while (!stopsim) { -#else while (n--) { -#endif switch(GetBYTE_pp(PC)) { case 0x00: /* NOP */ break; From 450fafbfd771f9e5dd29947c0fbbcfeeb2066542 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 19 Mar 2017 15:57:33 +0000 Subject: [PATCH 063/149] Co Pro Z80: Fixes for new FIQ tube handler Change-Id: Id5d5eac8409f6bc8c0b6a603c7f15c1e78bb2681 --- src/copro-z80.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/copro-z80.c b/src/copro-z80.c index bcf10eae..a119e408 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -325,7 +325,8 @@ static void copro_z80_reset() { void copro_z80_emulator() { - static unsigned int last_rst = 0; + unsigned int last_rst = 0; + unsigned int last_nmi = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -338,30 +339,36 @@ void copro_z80_emulator() // Execute emulator for one instruction simz80_execute(1); - if (tube_irq & 7 ) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; - // Reset the processor on active edge of rst - if (rst && !last_rst) { + // Reset the processor on active edge of rst + if (tube_irq & 4) { + if (!last_rst) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_z80_reset(); + last_rst = 1; } - // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { + } else { + last_rst = 0; + } + + // NMI is edge sensitive, so only check after mailbox activity + if (tube_irq & 2) { + if (!last_nmi) { overlay_rom = 1; - simz80_NMI(); + simz80_NMI(); + last_nmi = 1; } - last_rst = rst; - - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - // check if the emulator IRQ is enabled - if (simz80_is_IRQ_enabled()) { - simz80_IRQ(); - } + } else { + last_nmi = 0; + } + + // IRQ is level sensitive, so check between every instruction + if (tube_irq & 1) { + // check if the emulator IRQ is enabled + if (simz80_is_IRQ_enabled()) { + simz80_IRQ(); } } } From b8c95065739db65e70f6ba26ff28be9c804c3379 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 21:16:07 +0000 Subject: [PATCH 064/149] Update tube-ula.c Optimise Clearing of NMI --- src/tube-ula.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 01aa523f..35b83254 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -439,10 +439,8 @@ uint8_t tube_parasite_read(uint32_t addr) PSTAT3 &= ~0x80; } //tube_updateints_NMI(); - // here we want to only really clear NMI if required, but setting irq might be simpler - tube_irq = tube_irq &(0xFF - 2); - if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0))) tube_irq|=2; - if ((HSTAT1 & HBIT_3) && (ph3pos == 0)) tube_irq|=2; + // here we want to only clear NMI if required + if ( ( !(ph3pos == 0) ) && ( (!(HSTAT1 & HBIT_4) && (!(hp3pos >0))) || (HSTAT1 & HBIT_4) ) ) tube_irq &= ~2; } break; case 6: /*Register 4 stat*/ From c9be007ab0691cd53e2ef02e535ef533f0f6cd3d Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 22:03:31 +0000 Subject: [PATCH 065/149] Tidy Code and remove NMI bug for Register 3 length 1 --- src/tube-ula.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 35b83254..99217a99 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -206,7 +206,7 @@ void copro_command_excute(unsigned char copro_command,unsigned char val) static void tube_reset() { tube_irq |= TUBE_ENABLE_BIT; - tube_irq &= ~(4+2+1); + tube_irq &= ~(RESET_BIT + NMI_BIT + IRQ_BIT); hp3pos = 0; ph1rdpos = ph1wrpos = ph1len = 0; ph3pos = 1; @@ -267,7 +267,7 @@ static void tube_host_read(uint16_t addr) ph3pos--; PSTAT3 |= 0xC0; if (!ph3pos) HSTAT3 &= ~HBIT_7; - if ((HSTAT1 & HBIT_3) && (ph3pos == 0)) tube_irq|=2; + if ((HSTAT1 & HBIT_3) && (ph3pos == 0)) tube_irq|=NMI_BIT; //tube_updateints_NMI(); } break; @@ -307,10 +307,10 @@ static void tube_host_write(uint16_t addr, uint8_t val) tube_irq &= ~RESET_BIT; } tube_irq &= ~(IRQ_BIT + NMI_BIT); - if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= 1; - if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= 1; - if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=2; - if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=2; + if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= IRQ_BIT; + if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= IRQ_BIT; + if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=NMI_BIT; + if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=NMI_BIT; break; case 1: /*Register 1*/ //if (!tube_enabled) @@ -318,7 +318,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) hp1 = val; PSTAT1 |= 0x80; HSTAT1 &= ~HBIT_6; - if (HSTAT1 & HBIT_1) tube_irq |= 1;//tube_updateints_IRQ(); + if (HSTAT1 & HBIT_1) tube_irq |= IRQ_BIT;//tube_updateints_IRQ(); break; case 2: copro_command = val; @@ -350,7 +350,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) PSTAT3 |= 0x80; HSTAT3 &= ~HBIT_6; } - if ((HSTAT1 & HBIT_3) && (hp3pos > 1)) tube_irq|=2; + if ((HSTAT1 & HBIT_3) && (hp3pos > 1)) tube_irq |= NMI_BIT; } else { @@ -358,7 +358,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) hp3pos = 1; PSTAT3 |= 0x80; HSTAT3 &= ~HBIT_6; - if (HSTAT1 & HBIT_3) tube_irq|=2; + if (HSTAT1 & HBIT_3) tube_irq |= NMI_BIT; } //tube_updateints_NMI(); break; @@ -382,7 +382,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) count_p = 0; } #endif - if (HSTAT1 & HBIT_2) tube_irq |= 1; //tube_updateints_IRQ(); + if (HSTAT1 & HBIT_2) tube_irq |= IRQ_BIT; //tube_updateints_IRQ(); break; default: LOG_WARN("Illegal host write to %d\r\n", addr); @@ -405,7 +405,7 @@ uint8_t tube_parasite_read(uint32_t addr) PSTAT1 &= ~0x80; HSTAT1 |= HBIT_6; //tube_updateints_IRQ(); // clear irq if required reg 4 isnt irqing - if (!(PSTAT4 & 128)) tube_irq = tube_irq & (0xFF - 1); + if (!(PSTAT4 & 128)) tube_irq &= ~IRQ_BIT } break; case 2: /*Register 2 stat*/ @@ -440,7 +440,7 @@ uint8_t tube_parasite_read(uint32_t addr) } //tube_updateints_NMI(); // here we want to only clear NMI if required - if ( ( !(ph3pos == 0) ) && ( (!(HSTAT1 & HBIT_4) && (!(hp3pos >0))) || (HSTAT1 & HBIT_4) ) ) tube_irq &= ~2; + if ( ( !(ph3pos == 0) ) && ( (!(HSTAT1 & HBIT_4) && (!(hp3pos >0))) || (HSTAT1 & HBIT_4) ) ) tube_irq &= ~NMI_BIT; } break; case 6: /*Register 4 stat*/ @@ -453,7 +453,7 @@ uint8_t tube_parasite_read(uint32_t addr) PSTAT4 &= ~0x80; HSTAT4 |= HBIT_6; //tube_updateints_IRQ(); // clear irq if reg 1 isnt irqing - if (!(PSTAT1 & 128)) tube_irq = tube_irq & (0xFF - 1); + if (!(PSTAT1 & 128)) tube_irq &= ~IRQ_BIT; } break; } @@ -544,7 +544,7 @@ void tube_parasite_write(uint32_t addr, uint8_t val) PSTAT3 &= ~0x40; } //NMI if other case isn't seting it - if (!(hp3pos > 1) ) tube_irq = tube_irq &(0xFF - 2); + if (!(hp3pos > 1) ) tube_irq &= ~NMI_BIT; } else { @@ -552,9 +552,8 @@ void tube_parasite_write(uint32_t addr, uint8_t val) ph3pos = 1; HSTAT3 |= HBIT_7; PSTAT3 &= ~0xC0; - tube_irq = tube_irq &(0xFF - 2); //NMI if other case isn't seting it - if (!(hp3pos > 0) ) tube_irq = tube_irq &(0xFF - 2); + if (!(hp3pos > 0) ) tube_irq &= ~NMI_BIT; } //tube_updateints_NMI(); // here we want to only clear NMI if required From a3a28b1f94d24bdc5c776bed3aba0d52b418c7b5 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 19 Mar 2017 22:16:47 +0000 Subject: [PATCH 066/149] Fix missing ; --- src/tube-ula.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 99217a99..47f05be6 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -405,7 +405,7 @@ uint8_t tube_parasite_read(uint32_t addr) PSTAT1 &= ~0x80; HSTAT1 |= HBIT_6; //tube_updateints_IRQ(); // clear irq if required reg 4 isnt irqing - if (!(PSTAT4 & 128)) tube_irq &= ~IRQ_BIT + if (!(PSTAT4 & 128)) tube_irq &= ~IRQ_BIT; } break; case 2: /*Register 2 stat*/ From 78ad40db90980796c321d60f0cdcd2e4711dec30 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 20 Mar 2017 19:29:05 +0000 Subject: [PATCH 067/149] Remove 'static' which isn't required --- src/copro-32016.c | 2 +- src/copro-80186.c | 2 +- src/copro-arm2.c | 2 +- src/copro-mc6809.c | 2 +- src/copro-mc6809nc.c | 2 +- src/copro-mc6809sc.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/copro-32016.c b/src/copro-32016.c index 01be9552..6fec4863 100644 --- a/src/copro-32016.c +++ b/src/copro-32016.c @@ -35,7 +35,7 @@ static void copro_32016_reset() { } void copro_32016_emulator() { - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; diff --git a/src/copro-80186.c b/src/copro-80186.c index c870bc39..1e27b468 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -35,7 +35,7 @@ void copro_80186_tube_write(uint16_t addr, uint8_t data) { void copro_80186_emulator() { - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; diff --git a/src/copro-arm2.c b/src/copro-arm2.c index b2111606..0697a177 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -146,7 +146,7 @@ static void copro_arm2_reset() void copro_arm2_emulator() { - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; diff --git a/src/copro-mc6809.c b/src/copro-mc6809.c index fb55fa12..8c6c4535 100644 --- a/src/copro-mc6809.c +++ b/src/copro-mc6809.c @@ -92,7 +92,7 @@ void copro_mc6809_emulator() mc6809->mem_cycle = DELEGATE_AS2(void, bool, uint16, copro_mc6809_mem_cycle, (void *)0); - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index d0278914..1d4e986f 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -78,7 +78,7 @@ static void copro_mc6809_reset() { void copro_mc6809nc_emulator() { - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; diff --git a/src/copro-mc6809sc.c b/src/copro-mc6809sc.c index 667deb9b..1ce43930 100644 --- a/src/copro-mc6809sc.c +++ b/src/copro-mc6809sc.c @@ -114,7 +114,7 @@ void copro_mc6809sc_emulator() cpu.write = copro_mc6809sc_write; cpu.fault = copro_mc6809sc_fault; - static unsigned int last_rst = 0; + unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; From b51c538fb44638fdd9ebb250c9998f7a0c3f8144 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 20 Mar 2017 20:14:08 +0000 Subject: [PATCH 068/149] Remove the chance of writing to the status register 0 causing extra NMIs. Also some code tidy --- src/tube-defs.h | 27 +++++++++------ src/tube-ula.c | 91 +++++++++++++++++++++++-------------------------- src/tube.S | 16 +-------- 3 files changed, 60 insertions(+), 74 deletions(-) diff --git a/src/tube-defs.h b/src/tube-defs.h index b7949a6c..a8d70ce5 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -69,22 +69,29 @@ // Indicate the platform has multiple cores #define HAS_MULTICORE -// Indicates we want to make active use of multiple cores -//#define USE_MULTICORE - -// Needs to match kernel_old setting in config.txt -//#define KERNEL_OLD - -// Include instruction histogram in multi core 65tube -//#define HISTOGRAM - #endif #define USE_GPU #define USE_HW_MAILBOX - +// +// tube_irq bit definitions +// +// bit 7 Selects if R7 is used to inform the copro of an interupt event used for fast 6502 +// bit 6 Selects if direct native arm irq are used +// bit 5 native arm irq lock +// bit 3 tube_enable +// bit 2 Reset event +// bit 1 NMI +// bit 0 IRQ +#define FAST6502_BIT 128 +#define NATIVEARM_BIT 64 +#define nativearmlock_bit 32 +#define TUBE_ENABLE_BIT 8 +#define RESET_BIT 4 +#define NMI_BIT 2 +#define IRQ_BIT 1 #include "rpi-base.h" diff --git a/src/tube-ula.c b/src/tube-ula.c index 47f05be6..7071ec2f 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -92,30 +92,6 @@ volatile int tube_irq; #define PSTAT3 pstat[2] #define PSTAT4 pstat[3] - -// -// bit 7 Selects if R7 is used to inform the copro of an interupt event used for fast 6502 -// bit 6 Selects if direct native arm irq are used -// bit 5 native arm irq lock -// bit 3 tube_enable -// bit 2 Reset event -// bit 1 NMI -// bit 0 IRQ -#define FAST6502_BIT 128 -#define NATIVEARM_BIT 64 -#define nativearmlock_bit 32 -#define TUBE_ENABLE_BIT 8 -#define RESET_BIT 4 -#define NMI_BIT 2 -#define IRQ_BIT 1 - -// The current Tube IRQ/NMI state is maintained in a global that the emulation code can see -// -// Bit 0 is the tube asserting irq -// Bit 1 is the tube asserting nmi -// Bit 2 is the tube asserting reset - - #ifdef DEBUG_TUBE #define TUBE_READ_MARKER 0x80000000 @@ -175,7 +151,8 @@ void tube_enable_fast6502(void) if ((cpsr & 0xc0) != 0xc0) { _enable_interrupts(); } -} +} + void tube_disable_fast6502(void) { int cpsr = _disable_interrupts(); @@ -184,6 +161,17 @@ void tube_disable_fast6502(void) _enable_interrupts(); } } + +void tube_ack_nmi(void) +{ + int cpsr = _disable_interrupts(); + tube_irq &= ~NMI_BIT; + if ((cpsr & 0xc0) != 0xc0) { + _enable_interrupts(); + } + +} + void copro_command_excute(unsigned char copro_command,unsigned char val) { switch (copro_command) @@ -197,7 +185,6 @@ void copro_command_excute(unsigned char copro_command,unsigned char val) return; default : - break; } @@ -288,7 +275,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) { case 0: /*Register 1 stat*/ - if (!(tube_irq& TUBE_ENABLE_BIT)) + if (!(tube_irq & TUBE_ENABLE_BIT)) return; if (val & 0x80) { @@ -297,20 +284,27 @@ static void tube_host_write(uint16_t addr, uint8_t val) tube_reset(); } else { HSTAT1 |= BYTE_TO_WORD(val & 0x3F); + + // only if we are now enabling NMIs do we possibly set NMI flag. + // NB NMIs are edge sensitive so this doesn't create extra false edges + if (val & 0x10) { + if (!(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq |= NMI_BIT; + if ( (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq |= NMI_BIT; + } } } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); + if (val & 0x10) tube_irq &= ~NMI_BIT; // if we are turning off NMI clear NMI flag + } + + if ( HSTAT1 & HBIT_5) { + tube_irq |= RESET_BIT; + } else { + tube_irq &= ~RESET_BIT; } - if ( HSTAT1 & HBIT_5) { - tube_irq |= RESET_BIT; - } else { - tube_irq &= ~RESET_BIT; - } - tube_irq &= ~(IRQ_BIT + NMI_BIT); + tube_irq &= ~(IRQ_BIT); if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= IRQ_BIT; if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= IRQ_BIT; - if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq|=NMI_BIT; - if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq|=NMI_BIT; break; case 1: /*Register 1*/ //if (!tube_enabled) @@ -318,7 +312,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) hp1 = val; PSTAT1 |= 0x80; HSTAT1 &= ~HBIT_6; - if (HSTAT1 & HBIT_1) tube_irq |= IRQ_BIT;//tube_updateints_IRQ(); + if (HSTAT1 & HBIT_1) tube_irq |= IRQ_BIT; //tube_updateints_IRQ(); break; case 2: copro_command = val; @@ -439,8 +433,8 @@ uint8_t tube_parasite_read(uint32_t addr) PSTAT3 &= ~0x80; } //tube_updateints_NMI(); - // here we want to only clear NMI if required - if ( ( !(ph3pos == 0) ) && ( (!(HSTAT1 & HBIT_4) && (!(hp3pos >0))) || (HSTAT1 & HBIT_4) ) ) tube_irq &= ~NMI_BIT; + // here we want to only clear NMI if required + if ( ( !(ph3pos == 0) ) && ( (!(HSTAT1 & HBIT_4) && (!(hp3pos >0))) || (HSTAT1 & HBIT_4) ) ) tube_irq &= ~NMI_BIT; } break; case 6: /*Register 4 stat*/ @@ -603,20 +597,19 @@ int tube_io_handler(uint32_t mail) if ((mail >> 12) & 1) // Check for Reset { - tube_irq |= RESET_BIT; - return tube_irq; // Set reset Flag + tube_irq |= RESET_BIT; + return tube_irq; // Set reset Flag } else { - addr = (mail>>8) & 7; - if ( ( (mail >>11 ) & 1) == 0) { // Check read write flag - tube_host_write(addr, mail & 0xFF); - } else { - tube_host_read(addr); - } - - return tube_irq ; - + addr = (mail>>8) & 7; + if ( ( (mail >>11 ) & 1) == 0) { // Check read write flag + tube_host_write(addr, mail & 0xFF); + } else { + tube_host_read(addr); + } + + return tube_irq ; } #else addr = 0; diff --git a/src/tube.S b/src/tube.S index 0026cba2..33bddd7a 100644 --- a/src/tube.S +++ b/src/tube.S @@ -9,21 +9,7 @@ .global arm_fiq_handler_flag1 -// -// bit 7 Selects if R7 is used to inform the copro of an interupt event used for fast 6502 -// bit 6 Selects if direct native arm irq are used -// bit 5 native arm irq lock -// bit 3 tube_enable -// bit 2 Reset event -// bit 1 NMI -// bit 0 IRQ -#define FAST6502_BIT 128 -#define NATIVEARM_BIT 64 -#define nativearmlock_bit 32 -#define TUBE_ENABLE_BIT 8 -#define RESET_BIT 4 -#define NMI_BIT 2 -#define IRQ_BIT 1 + // ================================================= // ISR CODE // ================================================= From 3360d32a4a55832329422c3e61c3d65cb90d901f Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 20 Mar 2017 20:29:00 +0000 Subject: [PATCH 069/149] use new function tube_ack_nmi() --- src/NS32016/32016.c | 3 ++- src/copro-z80.c | 49 +++++++++++++++++++++------------------------ src/tube-ula.h | 2 ++ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index 71b508de..0b1f1dd3 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -13,6 +13,7 @@ #include "defs.h" #include "Trap.h" #include "Decode.h" +#include "../tube-ula.h" #ifdef PROFILING #include "Profile.h" @@ -971,7 +972,7 @@ void n32016_exec() if (tube_irq & 2) { // NMI is edge sensitive, so it should be cleared here - tube_irq &= ~2; + tube_ack_nmi(); TakeInterrupt(intbase + (1 * 4)); } else if ((tube_irq & 1) && (psr & 0x800)) diff --git a/src/copro-z80.c b/src/copro-z80.c index a119e408..7877cddf 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -326,7 +326,6 @@ static void copro_z80_reset() { void copro_z80_emulator() { unsigned int last_rst = 0; - unsigned int last_nmi = 0; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -338,38 +337,36 @@ void copro_z80_emulator() { // Execute emulator for one instruction simz80_execute(1); - - // Reset the processor on active edge of rst - if (tube_irq & 4) { - if (!last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - break; + if (tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT)) { + + // Reset the processor on active edge of rst + if (tube_irq & RESET_BIT) { + if (!last_rst) { + // Exit if the copro has changed + if (copro != last_copro) { + break; + } + copro_z80_reset(); + last_rst = 1; } - copro_z80_reset(); - last_rst = 1; + } else { + last_rst = 0; } - } else { - last_rst = 0; - } - // NMI is edge sensitive, so only check after mailbox activity - if (tube_irq & 2) { - if (!last_nmi) { + // NMI is edge sensitive, + if (tube_irq & NMI_BIT) { overlay_rom = 1; simz80_NMI(); - last_nmi = 1; + tube_ack_nmi(); } - } else { - last_nmi = 0; - } - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { - // check if the emulator IRQ is enabled - if (simz80_is_IRQ_enabled()) { - simz80_IRQ(); - } + // IRQ is level sensitive, + if (tube_irq & IRQ_BIT) { + // check if the emulator IRQ is enabled + if (simz80_is_IRQ_enabled()) { + simz80_IRQ(); + } + } } } } diff --git a/src/tube-ula.h b/src/tube-ula.h index 97eb1b9d..e978011c 100644 --- a/src/tube-ula.h +++ b/src/tube-ula.h @@ -21,6 +21,8 @@ extern void disable_tube(); //extern void tube_host_write(uint16_t addr, uint8_t val); +void tube_ack_nmi(void); + extern uint8_t tube_parasite_read(uint32_t addr); extern void tube_parasite_write(uint32_t addr, uint8_t val); From 1afecf96a11d99c5b8dfdd4d8e98cf7f81062d50 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 20 Mar 2017 21:13:29 +0000 Subject: [PATCH 070/149] No need to pass slow down flag in . Tidying --- src/copro-65tube.c | 2 +- src/copro-65tube.h | 2 +- src/copro-65tubeasm.S | 51 +++++++++++++++++++------------------------ 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/copro-65tube.c b/src/copro-65tube.c index bcaa419c..1e272691 100644 --- a/src/copro-65tube.c +++ b/src/copro-65tube.c @@ -84,7 +84,7 @@ void copro_65tube_emulator() { copro_65tube_init_histogram(); #endif tube_reset_performance_counters(); - exec_65tube(mpu_memory, copro == COPRO_65TUBE_1 ? 1 : 0); + exec_65tube(mpu_memory); tube_log_performance_counters(); #ifdef HISTOGRAM diff --git a/src/copro-65tube.h b/src/copro-65tube.h index 111056ac..983ccf6c 100644 --- a/src/copro-65tube.h +++ b/src/copro-65tube.h @@ -4,7 +4,7 @@ extern void copro_65tube_emulator(); -extern void exec_65tube(unsigned char *memory, int slowdown); +extern void exec_65tube(unsigned char *memory); //extern unsigned char mpu_memory[]; diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 416c8915..432a7531 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1318,7 +1318,6 @@ timing_table: // ********************************************** // // R0 Points to memory -// R1 Slow down bit // Globals used // copro_speed @@ -1343,22 +1342,19 @@ exec_65tube: // This is very strange, because flags bit 7 is not used! // To reproduce, initialize flags to 0x80 - tst r1, #1 // test slow down bit - beq noslowsetup // setup ARM cycle counter #if defined(RPI2)|| defined(RPI3) - mrc p15 ,0, r0, c9, c12, 0 - BIC r0, r0, #8 - mcr p15, 0, r0, c9, c12, 0 - mrc p15, 0, r0, c9, c13, 0 + mrc p15 ,0, r0, c9, c12, 0 + BIC r0, r0, #8 + mcr p15, 0, r0, c9, c12, 0 + mrc p15, 0, r0, c9, c13, 0 #else - MRC p15, 0, r0, c15, c12, 0 // Read Performance Monitor Control Register - BIC r0 ,r0, #8 // clear div 64 bit - MCR p15, 0, r0, c15, c12, 0 // Write Performance Monitor Control Register - MRC p15, 0, r0, c15, c12, 1 // Read Cycle Counter Register + MRC p15, 0, r0, c15, c12, 0 // Read Performance Monitor Control Register + BIC r0 ,r0, #8 // clear div 64 bit + MCR p15, 0, r0, c15, c12, 0 // Write Performance Monitor Control Register + MRC p15, 0, r0, c15, c12, 1 // Read Cycle Counter Register #endif - str r0,targettime -noslowsetup: + str r0,targettime handle_rst: orr flags, flags, #4 // Set the I bit @@ -1375,8 +1371,7 @@ handle_rst: FETCH_NEXT_3B_MERGED SUBPC // Start executing instructions exec_65tube_exit: // We get here from the Event handler when RST is detected - msr CPSR, r2 // re-enable ARM interrupts - bl tube_disable_fast6502 + bl tube_disable_fast6502 pop {r4-r11,pc} // 6502 Event handler @@ -1384,11 +1379,11 @@ exec_65tube_exit: // We get here from the Event handler wh // if USE_MULTICORE is not defined, we have come here via a branch from the second instruction table Event_Handler: - ldr r0, =tube_irq + ldr r0, =tube_irq mrs r2, CPSR // preserve the 6502 flags bic instt, instt, #1024 // ack events - ldrb r0, [r0] + ldrb r0, [r0] sub regPC, regPC, #2 // set the instruction back as we haven't executed it tst r0, #4 // Bit 2 set indicate RST is active @@ -1453,15 +1448,15 @@ targettime: // we restore the modified table base pointer so we will re-enter this handler Event_Handler_Single_Core_Slow: - ldr r0, =tube_irq + ldr r0, =tube_irq mrs r2, CPSR // preserve the 6502 flags // interrupts are left enabled bic instt, instt, #1024 // ack any events - ldrb r0,[r0] + ldrb r0,[r0] sub regPC, regPC, #2 // set the instruction back as we haven't executed it - tst r0,#7 - beq noirq2 + tst r0,#7 + beq noirq2 tst r0, #4 // Bit 2 set indicate RST is active bne exec_65tube_exit // exit immediately if active edge seen @@ -1476,28 +1471,26 @@ Event_Handler_Single_Core_Slow: noirq2: ldrb r0, [regPC] // get next instruction - ldr r1,=timing_table + adr r1,timing_table ldr lr,lastPC ldrb r0,[r1,r0,LSL#1]! // get instruction time ldrb r1,[r1,#1] // get instruction length cmp lr,regPC - ADDNE r0,r0,#1 - - //ldr lr,[r1,#2] - ldr lr,=copro_speed + ADDNE r0,r0,#1 + add r1,r1,regPC + ldr lr,[lr] // load copro_speed str r1,lastPC - ldr lr,[lr] // load copro_speed // get last time LDR r1,targettime MUL r0,lr,r0 // add on new time - ADD lr,r1,r0,LSR #8 // shift by 8 + ADD lr,r1,r0,LSR #8 // shift by 8 // save time new time. - str lr,targettime + str lr,targettime // loop until current time(R0) > nexttime(R1) ( nb deal with wrap around) waste_time: From 2fa967a27fb74d052c26097a112a1bdfb4435d35 Mon Sep 17 00:00:00 2001 From: David Banks Date: Tue, 21 Mar 2017 19:11:56 +0000 Subject: [PATCH 071/149] 6809: Added debugger support (no memory hooks yet) Change-Id: Ie614887a52054c854445f2996cbb770e44300592 --- src/CMakeLists.txt | 6 + src/debugger/debugger.c | 3 +- src/mc6809nc/mc6809.c | 39 +- src/mc6809nc/mc6809_debug.c | 195 ++++++++ src/mc6809nc/mc6809_debug.h | 6 + src/mc6809nc/mc6809_dis.c | 941 ++++++++++++++++++++++++++++++++++++ src/mc6809nc/mc6809_dis.h | 2 + 7 files changed, 1178 insertions(+), 14 deletions(-) create mode 100644 src/mc6809nc/mc6809_debug.c create mode 100644 src/mc6809nc/mc6809_debug.h create mode 100644 src/mc6809nc/mc6809_dis.c create mode 100644 src/mc6809nc/mc6809_dis.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23275b7e..2cf233b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -233,6 +233,12 @@ file( GLOB debugger_files NS32016/32016_debug.h mame/arm_debug.c mame/arm_debug.h + mc6809nc/mc6809.c + mc6809nc/mc6809.h + mc6809nc/mc6809_debug.h + mc6809nc/mc6809_debug.c + mc6809nc/mc6809_dis.c + mc6809nc/mc6809_dis.h ) if( ${DEBUG} ) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 4562b6ac..e78d876a 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -9,6 +9,7 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" +#include "../mc6809nc/mc6809_debug.h" #include "../mame/arm_debug.h" #include "../NS32016/32016_debug.h" @@ -28,7 +29,7 @@ cpu_debug_t *cpu_debug_list[] = { NULL, // 4 Z80 NULL, // 7 Z80 NULL, // 8 80x86 - NULL, // 9 6809 + &mc6809nc_cpu_debug, // 9 6809 NULL, // 10 unused NULL, // 11 unused &arm2_cpu_debug, // 12 ARM2 diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index 927ad11f..d338def1 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -22,13 +22,18 @@ #include "mc6809.h" #include -unsigned X, Y, S, U, PC; -unsigned A, B, DP; -unsigned H, N, Z, OV, C; -unsigned EFI; +#ifdef INCLUDE_DEBUGGER +#include "mc6809_debug.h" +#include "../cpu_debug.h" +#endif + +static unsigned X, Y, S, U, PC; +static unsigned A, B, DP; +static unsigned H, N, Z, OV, C; +static unsigned EFI; #ifdef H6309 -unsigned E, F, V, MD; +static unsigned E, F, V, MD; #define MD_NATIVE 0x1 /* if 1, execute in 6309 mode */ #define MD_FIRQ_LIKE_IRQ 0x2 /* if 1, FIRQ acts like IRQ */ @@ -36,16 +41,16 @@ unsigned E, F, V, MD; #define MD_DBZ 0x80 /* divide by zero */ #endif /* H6309 */ -unsigned iPC; +static unsigned iPC; -unsigned ea = 0; -long cpu_clk = 0; -long cpu_period = 0; -unsigned int irqs_pending = 0; -unsigned int firqs_pending = 0; -unsigned int cc_changed = 0; +static unsigned ea = 0; +static long cpu_clk = 0; +static long cpu_period = 0; +static unsigned int irqs_pending = 0; +static unsigned int firqs_pending = 0; +static unsigned int cc_changed = 0; -unsigned *index_regs[4] = { &X, &Y, &U, &S }; +static unsigned *index_regs[4] = { &X, &Y, &U, &S }; static int sync_flag; @@ -1581,6 +1586,14 @@ int mc6809nc_execute (int cycles) { iPC = PC; + +#ifdef INCLUDE_DEBUGGER + if (mc6809nc_debug_enabled) + { + debug_preexec(&mc6809nc_cpu_debug, PC); + } +#endif + opcode = imm_byte (); switch (opcode) diff --git a/src/mc6809nc/mc6809_debug.c b/src/mc6809nc/mc6809_debug.c new file mode 100644 index 00000000..55dc0c28 --- /dev/null +++ b/src/mc6809nc/mc6809_debug.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include + +#include "../cpu_debug.h" + +#include "mc6809.h" +#include "mc6809_dis.h" +#include "mc6809_debug.h" + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +int mc6809nc_debug_enabled = 0; + +enum register_numbers { + i_PC, + i_CC, + i_A, + i_B, + i_D, + i_X, + i_Y, + i_U, + i_S, + i_DP +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "PC", + "CC", + "A", + "B", + "D", + "X", + "Y", + "U", + "S", + "DP", + NULL +}; + +// enable/disable debugging on this CPU, returns previous value. +static int dbg_debug_enable(int newvalue) { + int oldvalue = mc6809nc_debug_enabled; + mc6809nc_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_memread(uint32_t addr) { + // TODO: use the internal version so the debugger doesn't get notified + return read8(addr); +}; + +// CPU's usual memory write function. +static void dbg_memwrite(uint32_t addr, uint32_t value) { + // TODO: use the internal version so the debugger doesn't get notified + write8(addr, value); +}; + +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + return mc6809_disassemble(addr, buf, bufsize); +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + switch (which) { + case i_PC: + return get_pc(); + case i_CC: + return get_cc(); + case i_A: + return get_a(); + case i_B: + return get_b(); + case i_D: + return get_d(); + case i_X: + return get_x(); + case i_Y: + return get_y(); + case i_U: + return get_u(); + case i_S: + return get_s(); + case i_DP: + return get_dp(); + default: + return 0; + } +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + switch (which) { + case i_PC: + set_pc(value); + break; + case i_CC: + set_cc(value); + break; + case i_A: + set_a(value); + break; + case i_B: + set_b(value); + break; + case i_D: + set_d(value); + break; + case i_X: + set_x(value); + break; + case i_Y: + set_y(value); + break; + case i_U: + set_u(value); + break; + case i_S: + set_s(value); + break; + case i_DP: + set_dp(value); + break; + } +}; + +static const char* flagname = "E H H I N Z V C "; + +// Print register value in CPU standard form. +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + if (which == i_CC) { + int i; + int bit; + char c; + const char *flagnameptr = flagname; + int psr = dbg_reg_get(i_CC); + + if (bufsize < 40) { + strncpy(buf, "buffer too small!!!", bufsize); + } + + bit = 0x80; + for (i = 0; i < 8; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + return strlen(buf); + } else if (which == i_A || which == i_B || which == i_DP) { + return snprintf(buf, bufsize, "%02"PRIx32, dbg_reg_get(which)); + } 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 get_pc(); +} + +cpu_debug_t mc6809nc_cpu_debug = { + .cpu_name = "MC6809NC", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .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 +}; diff --git a/src/mc6809nc/mc6809_debug.h b/src/mc6809nc/mc6809_debug.h new file mode 100644 index 00000000..60da8c52 --- /dev/null +++ b/src/mc6809nc/mc6809_debug.h @@ -0,0 +1,6 @@ +#include "../cpu_debug.h" + +extern int mc6809nc_debug_enabled; + +extern cpu_debug_t mc6809nc_cpu_debug; + diff --git a/src/mc6809nc/mc6809_dis.c b/src/mc6809nc/mc6809_dis.c new file mode 100644 index 00000000..1c8dd604 --- /dev/null +++ b/src/mc6809nc/mc6809_dis.c @@ -0,0 +1,941 @@ +/* dis6809.c -- 6809 disassembler + Copyright (C) 1998 Jerome Thoen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include "mc6809.h" + +typedef unsigned char tt_u8; +typedef signed char tt_s8; +typedef unsigned short tt_u16; +typedef signed short tt_s16; + +static inline unsigned int get_memw(unsigned int addr) { + return (read8(addr) << 8) + read8(addr + 1); +} + +static inline unsigned char get_memb(unsigned int addr) { + return read8(addr); +} + +enum opcodes { + OP_UU , + OP_XX , + OP_ABX , + OP_ADCA, + OP_ADCB, + OP_ADDA, + OP_ADDB, + OP_ADDD, + OP_ANDA, + OP_ANDB, + OP_ANDC, + OP_ASL , + OP_ASLA, + OP_ASR , + OP_ASRA, + OP_ASRB, + OP_BCC , + OP_BEQ , + OP_BGE , + OP_BGT , + OP_BHI , + OP_BITA, + OP_BITB, + OP_BLE , + OP_BLO , + OP_BLS , + OP_BLT , + OP_BMI , + OP_BNE , + OP_BPL , + OP_BRA , + OP_BRN , + OP_BSR , + OP_BVC , + OP_BVS , + OP_CLR , + OP_CLRA, + OP_CLRB, + OP_CMPA, + OP_CMPB, + OP_CMPD, + OP_CMPS, + OP_CMPU, + OP_CMPX, + OP_CMPY, + OP_COM , + OP_COMA, + OP_COMB, + OP_CWAI, + OP_DAA , + OP_DEC , + OP_DECA, + OP_DECB, + OP_EORA, + OP_EORB, + OP_EXG , + OP_INC , + OP_INCA, + OP_INCB, + OP_JMP , + OP_JSR , + OP_LBCC, + OP_LBEQ, + OP_LBGE, + OP_LBGT, + OP_LBHI, + OP_LBLE, + OP_LBLO, + OP_LBLS, + OP_LBLT, + OP_LBMI, + OP_LBNE, + OP_LBPL, + OP_LBRA, + OP_LBRN, + OP_LBSR, + OP_LBVC, + OP_LBVS, + OP_LDA , + OP_LDB , + OP_LDD , + OP_LDS , + OP_LDU , + OP_LDX , + OP_LDY , + OP_LEAS, + OP_LEAU, + OP_LEAX, + OP_LEAY, + OP_LSLB, + OP_LSR , + OP_LSRA, + OP_LSRB, + OP_MUL , + OP_NEG , + OP_NEGA, + OP_NEGB, + OP_NOP , + OP_ORA , + OP_ORB , + OP_ORCC, + OP_PSHS, + OP_PSHU, + OP_PULS, + OP_PULU, + OP_ROL , + OP_ROLA, + OP_ROLB, + OP_ROR , + OP_RORA, + OP_RORB, + OP_RTI , + OP_RTS , + OP_SBCA, + OP_SBCB, + OP_SEX , + OP_STA , + OP_STB , + OP_STD , + OP_STS , + OP_STU , + OP_STX , + OP_STY , + OP_SUBA, + OP_SUBB, + OP_SUBD, + OP_SWI , + OP_SWI2, + OP_SWI3, + OP_SYNC, + OP_TFR , + OP_TST , + OP_TSTA, + OP_TSTB +}; + +static const char inst[] = "\ +-- \ +?? \ +ABX \ +ADCA\ +ADCB\ +ADDA\ +ADDB\ +ADDD\ +ANDA\ +ANDB\ +ANDC\ +ASL \ +ASLA\ +ASR \ +ASRA\ +ASRB\ +BCC \ +BEQ \ +BGE \ +BGT \ +BHI \ +BITA\ +BITB\ +BLE \ +BLO \ +BLS \ +BLT \ +BMI \ +BNE \ +BPL \ +BRA \ +BRN \ +BSR \ +BVC \ +BVS \ +CLR \ +CLRA\ +CLRB\ +CMPA\ +CMPB\ +CMPD\ +CMPS\ +CMPU\ +CMPX\ +CMPY\ +COM \ +COMA\ +COMB\ +CWAI\ +DAA \ +DEC \ +DECA\ +DECB\ +EORA\ +EORB\ +EXG \ +INC \ +INCA\ +INCB\ +JMP \ +JSR \ +LBCC\ +LBEQ\ +LBGE\ +LBGT\ +LBHI\ +LBLE\ +LBLO\ +LBLS\ +LBLT\ +LBMI\ +LBNE\ +LBPL\ +LBRA\ +LBRN\ +LBSR\ +LBVC\ +LBVS\ +LDA \ +LDB \ +LDD \ +LDS \ +LDU \ +LDX \ +LDY \ +LEAS\ +LEAU\ +LEAX\ +LEAY\ +LSLB\ +LSR \ +LSRA\ +LSRB\ +MUL \ +NEG \ +NEGA\ +NEGB\ +NOP \ +ORA \ +ORB \ +ORCC\ +PSHS\ +PSHU\ +PULS\ +PULU\ +ROL \ +ROLA\ +ROLB\ +ROR \ +RORA\ +RORB\ +RTI \ +RTS \ +SBCA\ +SBCB\ +SEX \ +STA \ +STB \ +STD \ +STS \ +STU \ +STX \ +STY \ +SUBA\ +SUBB\ +SUBD\ +SWI \ +SWI2\ +SWI3\ +SYNC\ +TFR \ +TST \ +TSTA\ +TSTB"; + +// The first byte is the opcode index +// The second byte is +// modes: +// 1 immediate +// 2 direct +// 3 indexed +// 4 extended +// 5 inherent +// 6 relative + +static const unsigned char map0[] = { + OP_NEG , 0x22, + OP_XX , 0x22, + OP_XX , 0x12, + OP_COM , 0x22, + OP_LSR , 0x22, + OP_XX , 0x12, + OP_ROR , 0x22, + OP_ASR , 0x22, + OP_ASL , 0x22, + OP_ROL , 0x22, + OP_DEC , 0x22, + OP_XX , 0x12, + OP_INC , 0x22, + OP_TST , 0x22, + OP_JMP , 0x22, + OP_CLR , 0x22, + OP_UU , 0x10, + OP_UU , 0x10, + OP_NOP , 0x15, + OP_SYNC, 0x15, + OP_XX , 0x10, + OP_XX , 0x10, + OP_LBRA, 0x36, + OP_LBSR, 0x36, + OP_XX , 0x10, + OP_DAA , 0x15, + OP_ORCC, 0x25, + OP_XX , 0x10, + OP_ANDC, 0x25, + OP_SEX , 0x15, + OP_EXG , 0x25, + OP_TFR , 0x25, + OP_BRA , 0x26, + OP_BRN , 0x26, + OP_BHI , 0x26, + OP_BLS , 0x26, + OP_BCC , 0x26, + OP_BLO , 0x26, + OP_BNE , 0x26, + OP_BEQ , 0x26, + OP_BVC , 0x26, + OP_BVS , 0x26, + OP_BPL , 0x26, + OP_BMI , 0x26, + OP_BGE , 0x26, + OP_BLT , 0x26, + OP_BGT , 0x26, + OP_BLE , 0x26, + OP_LEAX, 0x23, + OP_LEAY, 0x23, + OP_LEAS, 0x23, + OP_LEAU, 0x23, + OP_PSHS, 0x25, + OP_PULS, 0x25, + OP_PSHU, 0x25, + OP_PULU, 0x25, + OP_XX , 0x15, + OP_RTS , 0x15, + OP_ABX , 0x15, + OP_RTI , 0x15, + OP_CWAI, 0x25, + OP_MUL , 0x15, + OP_XX , 0x15, + OP_SWI , 0x15, + OP_NEGA, 0x15, + OP_XX , 0x15, + OP_XX , 0x15, + OP_COMA, 0x15, + OP_LSRA, 0x15, + OP_XX , 0x15, + OP_RORA, 0x15, + OP_ASRA, 0x15, + OP_ASLA, 0x15, + OP_ROLA, 0x15, + OP_DECA, 0x15, + OP_XX , 0x15, + OP_INCA, 0x15, + OP_TSTA, 0x15, + OP_XX , 0x15, + OP_CLRA, 0x15, + OP_NEGB, 0x15, + OP_XX , 0x15, + OP_XX , 0x15, + OP_COMB, 0x15, + OP_LSRB, 0x15, + OP_XX , 0x15, + OP_RORB, 0x15, + OP_ASRB, 0x15, + OP_LSLB, 0x15, + OP_ROLB, 0x15, + OP_DECB, 0x15, + OP_XX , 0x15, + OP_INCB, 0x15, + OP_TSTB, 0x15, + OP_XX , 0x15, + OP_CLRB, 0x15, + OP_NEG , 0x23, + OP_XX , 0x13, + OP_XX , 0x13, + OP_COM , 0x23, + OP_LSR , 0x23, + OP_XX , 0x13, + OP_ROR , 0x23, + OP_ASR , 0x23, + OP_ASL , 0x23, + OP_ROL , 0x23, + OP_DEC , 0x23, + OP_XX , 0x13, + OP_INC , 0x23, + OP_TST , 0x23, + OP_JMP , 0x23, + OP_CLR , 0x23, + OP_NEG , 0x34, + OP_XX , 0x14, + OP_XX , 0x14, + OP_COM , 0x34, + OP_LSR , 0x34, + OP_XX , 0x14, + OP_ROR , 0x34, + OP_ASR , 0x34, + OP_ASL , 0x34, + OP_ROL , 0x34, + OP_DEC , 0x34, + OP_XX , 0x14, + OP_INC , 0x34, + OP_TST , 0x34, + OP_JMP , 0x34, + OP_CLR , 0x34, + OP_SUBA, 0x21, + OP_CMPA, 0x21, + OP_SBCA, 0x21, + OP_SUBD, 0x31, + OP_ANDA, 0x21, + OP_BITA, 0x21, + OP_LDA , 0x21, + OP_XX , 0x11, + OP_EORA, 0x21, + OP_ADCA, 0x21, + OP_ORA , 0x21, + OP_ADDA, 0x21, + OP_CMPX, 0x31, + OP_BSR , 0x26, + OP_LDX , 0x31, + OP_XX , 0x10, + OP_SUBA, 0x22, + OP_CMPA, 0x22, + OP_SBCA, 0x22, + OP_SUBD, 0x22, + OP_ANDA, 0x22, + OP_BITA, 0x22, + OP_LDA , 0x22, + OP_STA , 0x22, + OP_EORA, 0x22, + OP_ADCA, 0x22, + OP_ORA , 0x22, + OP_ADDA, 0x22, + OP_CMPX, 0x22, + OP_JSR , 0x22, + OP_LDX , 0x22, + OP_STX , 0x22, + OP_SUBA, 0x23, + OP_CMPA, 0x23, + OP_SBCA, 0x23, + OP_SUBD, 0x23, + OP_ANDA, 0x23, + OP_BITA, 0x23, + OP_LDA , 0x23, + OP_STA , 0x23, + OP_EORA, 0x23, + OP_ADCA, 0x23, + OP_ORA , 0x23, + OP_ADDA, 0x23, + OP_CMPX, 0x23, + OP_JSR , 0x23, + OP_LDX , 0x23, + OP_STX , 0x23, + OP_SUBA, 0x34, + OP_CMPA, 0x34, + OP_SBCA, 0x34, + OP_SUBD, 0x34, + OP_ANDA, 0x34, + OP_BITA, 0x34, + OP_LDA , 0x34, + OP_STA , 0x34, + OP_EORA, 0x34, + OP_ADCA, 0x34, + OP_ORA , 0x34, + OP_ADDA, 0x34, + OP_CMPX, 0x34, + OP_JSR , 0x34, + OP_LDX , 0x34, + OP_STX , 0x34, + OP_SUBB, 0x21, + OP_CMPB, 0x21, + OP_SBCB, 0x21, + OP_ADDD, 0x31, + OP_ANDB, 0x21, + OP_BITB, 0x21, + OP_LDB , 0x21, + OP_XX , 0x11, + OP_EORB, 0x21, + OP_ADCB, 0x21, + OP_ORB , 0x21, + OP_ADDB, 0x21, + OP_LDD , 0x31, + OP_XX , 0x11, + OP_LDU , 0x31, + OP_XX , 0x10, + OP_SUBB, 0x22, + OP_CMPB, 0x22, + OP_SBCB, 0x22, + OP_ADDD, 0x22, + OP_ANDB, 0x22, + OP_BITB, 0x22, + OP_LDB , 0x22, + OP_STB , 0x22, + OP_EORB, 0x22, + OP_ADCB, 0x22, + OP_ORB , 0x22, + OP_ADDB, 0x22, + OP_LDD , 0x22, + OP_STD , 0x22, + OP_LDU , 0x22, + OP_STU , 0x22, + OP_SUBB, 0x23, + OP_CMPB, 0x23, + OP_SBCB, 0x23, + OP_ADDD, 0x23, + OP_ANDB, 0x23, + OP_BITB, 0x23, + OP_LDB , 0x23, + OP_STB , 0x23, + OP_EORB, 0x23, + OP_ADCB, 0x23, + OP_ORB , 0x23, + OP_ADDB, 0x23, + OP_LDD , 0x23, + OP_STD , 0x23, + OP_LDU , 0x23, + OP_STU , 0x23, + OP_SUBB, 0x34, + OP_CMPB, 0x34, + OP_SBCB, 0x34, + OP_ADDD, 0x34, + OP_ANDB, 0x34, + OP_BITB, 0x34, + OP_LDB , 0x34, + OP_STB , 0x34, + OP_EORB, 0x34, + OP_ADCB, 0x34, + OP_ORB , 0x34, + OP_ADDB, 0x34, + OP_LDD , 0x34, + OP_STD , 0x34, + OP_LDU , 0x34, + OP_STU , 0x34, +}; + +static const unsigned char map1[] = { + 33, OP_LBRN, 0x46, + 34, OP_LBHI, 0x46, + 35, OP_LBLS, 0x46, + 36, OP_LBCC, 0x46, + 37, OP_LBLO, 0x46, + 38, OP_LBNE, 0x46, + 39, OP_LBEQ, 0x46, + 40, OP_LBVC, 0x46, + 41, OP_LBVS, 0x46, + 42, OP_LBPL, 0x46, + 43, OP_LBMI, 0x46, + 44, OP_LBGE, 0x46, + 45, OP_LBLT, 0x46, + 46, OP_LBGT, 0x46, + 47, OP_LBLE, 0x46, + 63, OP_SWI2, 0x25, + 131, OP_CMPD, 0x41, + 140, OP_CMPY, 0x41, + 142, OP_LDY , 0x41, + 147, OP_CMPD, 0x32, + 156, OP_CMPY, 0x32, + 158, OP_LDY , 0x32, + 159, OP_STY , 0x32, + 163, OP_CMPD, 0x33, + 172, OP_CMPY, 0x33, + 174, OP_LDY , 0x33, + 175, OP_STY , 0x33, + 179, OP_CMPD, 0x44, + 188, OP_CMPY, 0x44, + 190, OP_LDY , 0x44, + 191, OP_STY , 0x44, + 206, OP_LDS , 0x41, + 222, OP_LDS , 0x32, + 223, OP_STS , 0x32, + 238, OP_LDS , 0x33, + 239, OP_STS , 0x33, + 254, OP_LDS , 0x44, + 255, OP_STS , 0x44, +}; + +static const unsigned char map2[] = { + 63, OP_SWI3, 0x25, + 131, OP_CMPU, 0x41, + 140, OP_CMPS, 0x41, + 147, OP_CMPU, 0x32, + 156, OP_CMPS, 0x32, + 163, OP_CMPU, 0x33, + 172, OP_CMPS, 0x33, + 179, OP_CMPU, 0x44, + 188, OP_CMPS, 0x44, + 255, OP_XX , 0x10 +}; + +static const char regi[] = { 'X', 'Y', 'U', 'S' }; + +static const char *exgi[] = { "D", "X", "Y", "U", "S", "PC", "??", "??", "A", + "B", "CC", "DP", "??", "??", "??", "??" }; + +static const char *pshsregi[] = { "PC", "U", "Y", "X", "DP", "B", "A", "CC" }; +static const char *pshuregi[] = { "PC", "S", "Y", "X", "DP", "B", "A", "CC" }; + +static char *str_buf; +static size_t str_bufsize; + +static void stringInit(char *buf, size_t bufsize) { + str_buf = buf; + str_bufsize = bufsize; +} + +static void stringAppend(const char *fmt, ...) { + int len; + va_list argptr; + va_start(argptr, fmt); + len = vsnprintf(str_buf, str_bufsize, fmt, argptr); + str_buf += len; + str_bufsize -= len; + va_end(argptr); +} + +/* disassemble one instruction at adress adr and return its size */ + +static char hexdigit(tt_u16 v) +{ + v &= 0xf; + if (v <= 9) + return '0' + v; + else + return 'A' - 10 + v; +} + +static char *hex8str(tt_u8 v) +{ + static char tmpbuf[3] = " "; + + tmpbuf[1] = hexdigit(v); + tmpbuf[0] = hexdigit(v >> 4); + + return tmpbuf; +} + +static char *hex16str(tt_u16 v) +{ + static char tmpbuf[5] = " "; + + tmpbuf[3] = hexdigit(v); + v >>= 4; + tmpbuf[2] = hexdigit(v); + v >>= 4; + tmpbuf[1] = hexdigit(v); + v >>= 4; + tmpbuf[0] = hexdigit(v); + + return tmpbuf; +} + +const char *statusString = "EFHINZVC"; + +static char *ccstr(tt_u8 val) +{ + static char tempbuf[9] = " "; + int i; + + for (i = 0; i < 8; i++) { + if (val & 0x80) + tempbuf[i] = statusString[i]; + else + tempbuf[i] = '.'; + val <<= 1; + } + + return tempbuf; +} + +static unsigned int disassemble(unsigned int addr) +{ + int d = get_memb(addr); + int s, i; + tt_u8 pb; + char reg; + const unsigned char *map = NULL; + + // Default for most undefined opcodes + unsigned char sm = 0x10; // size_mode byte + unsigned char oi = OP_XX; // opcode index + + if (d == 0x10) { + d = get_memb(addr + 1); + map = map1; + } + + if (d == 0x11) { + d = get_memb(addr + 1); + map = map2; + } + + if (map) { + // Search for the opcode in map1 or map2 + map -= 3; + do { + map += 3; + if (*map == d) { + oi = *(++map); + sm = *(++map); + break; + } + } while (*map < 255); + } else { + // Lookup directly in map0 + map = map0 + 2 * d; + oi = *(map++); + sm = *(map++); + } + + s = sm >> 4; + + stringAppend("%04X ", addr); + + for (i = 0; i < s; i++) { + stringAppend("%s", hex8str(get_memb(addr + i))); + stringAppend("%c", ' '); + } + for (i = s; i < 4; i++) { + stringAppend("%s", " "); + } + + const char *ip = inst + oi * 4; + for (i = 0; i < 4; i++) + stringAppend("%c", *(ip++)); + + stringAppend("%s", " "); + + + switch(sm & 15) { + case 1: /* immediate */ + stringAppend("%s", "#$"); + if (s == 2) + stringAppend("%s", hex8str(get_memb(addr + 1))); + else + stringAppend("%s", hex16str(get_memw(addr + s - 2))); + break; + case 2: /* direct */ + stringAppend("%s", "$"); + stringAppend("%s", hex8str(get_memb(addr + s - 1))); + break; + case 3: /* indexed */ + pb = get_memb(addr + s - 1); + reg = regi[(pb >> 5) & 0x03]; + + if (!(pb & 0x80)) { /* n4,R */ + if (pb & 0x10) + stringAppend("-$%s,%c", hex8str(((pb & 0x0f) ^ 0x0f) + 1), reg); + else + stringAppend("$%s,%c", hex8str(pb & 0x0f), reg); + } + else { + if (pb & 0x10) + stringAppend("%c", '['); + switch (pb & 0x0f) { + case 0: /* ,R+ */ + stringAppend(",%c+", reg); + break; + case 1: /* ,R++ */ + stringAppend(",%c++", reg); + break; + case 2: /* ,-R */ + stringAppend(",-%c", reg); + break; + case 3: /* ,--R */ + stringAppend(",--%c", reg); + break; + case 4: /* ,R */ + stringAppend(",%c", reg); + break; + case 5: /* B,R */ + stringAppend("B,%c", reg); + break; + case 6: /* A,R */ + stringAppend("A,%c", reg); + break; + case 8: /* n7,R */ + s += 1; + stringAppend("$%s,%c", hex8str(get_memb(addr + s - 1)), reg); + break; + case 9: /* n15,R */ + s += 2; + stringAppend("$%s,%c", hex16str(get_memw(addr + s - 2)), reg); + break; + case 11: /* D,R */ + stringAppend("D,%c", reg); + break; + case 12: /* n7,PCR */ + s += 1; + stringAppend("$%s,PCR", hex8str(get_memb(addr + s - 1))); + break; + case 13: /* n15,PCR */ + s += 2; + stringAppend("$%s,PCR", hex16str(get_memw(addr + s - 2))); + break; + case 15: /* [n] */ + s += 2; + stringAppend("$%s", hex16str(get_memw(addr + s - 2))); + break; + default: + stringAppend("%s", "??"); + break; } + if (pb & 0x10) + stringAppend("%c", ']'); + } + break; + case 4: /* extended */ + stringAppend("$%s", hex16str(get_memw(addr + s - 2))); + break; + case 5: /* inherent */ + pb = get_memb(addr + 1); + switch (d) { + case 0x1e: case 0x1f: /* exg tfr */ + stringAppend("%s,%s", exgi[(pb >> 4) & 0x0f], exgi[pb & 0x0f]); + break; + case 0x1a: case 0x1c: case 0x3c: /* orcc andcc cwai */ + stringAppend("#$%s=%s", hex8str(pb), ccstr(pb)); + break; + case 0x34: /* pshs */ + { + int p = 0; + + for (i = 0; i < 8; i++) { + if (pb & 0x80) { + if (p) + stringAppend("%c", ','); + stringAppend("%s", pshsregi[i]); + p = 1; + } + pb <<= 1; + } + } + break; + case 0x35: /* puls */ + { + int p = 0; + + for (i = 7; i >= 0; i--) { + if (pb & 0x01) { + if (p) + stringAppend("%c", ','); + stringAppend("%s", pshsregi[i]); + p = 1; + } + pb >>= 1; + } + } + break; + case 0x36: /* pshu */ + { + int p = 0; + + for (i = 0; i < 8; i++) { + if (pb & 0x80) { + if (p) + stringAppend("%c", ','); + stringAppend("%s", pshuregi[i]); + p = 1; + } + pb <<= 1; + } + } + break; + case 0x37: /* pulu */ + { + int p = 0; + + for (i = 7; i >= 0; i--) { + if (pb & 0x01) { + if (p) + stringAppend("%c", ','); + stringAppend("%s", pshuregi[i]); + p = 1; + } + pb >>= 1; + } + } + break; + } + break; + case 6: /* relative */ + { + tt_s16 v; + + if (s == 2) + v = (tt_s16)(tt_s8)get_memb(addr + 1); + else + v = (tt_s16)get_memw(addr + s - 2); + stringAppend("$%s", hex16str(addr + (tt_u16)s + v)); + break; + } + } + + return addr + s; +} + +uint32_t mc6809_disassemble(uint32_t addr, char *buf, size_t bufsize) +{ + stringInit(buf, bufsize); + return disassemble(addr); +} + diff --git a/src/mc6809nc/mc6809_dis.h b/src/mc6809nc/mc6809_dis.h new file mode 100644 index 00000000..dbd02973 --- /dev/null +++ b/src/mc6809nc/mc6809_dis.h @@ -0,0 +1,2 @@ +uint32_t mc6809_disassemble(uint32_t addr, char *buf, size_t bufsize); + From 200117429caa787a40662588bd82381c8d62e43b Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 21 Mar 2017 19:26:30 +0000 Subject: [PATCH 072/149] Fix bug in zpr dissassembly , fixed the need for #pragma's made keeping tracks of ticks optional --- src/lib6502.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/lib6502.c b/src/lib6502.c index 059d1581..0db21924 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -27,9 +27,7 @@ * - emulator+disassembler in same object file (library is kind of pointless) */ -#pragma GCC diagnostic ignored "-Wformat-extra-args" -#pragma GCC diagnostic ignored "-Wunused-value" - +#define notick #include #include @@ -69,9 +67,13 @@ enum { static int elapsed; +#ifdef notick +#define tick(n) +#define tickIf(p) +#else #define tick(n) elapsed+=n -#define tickIf(p) (p && elapsed++) - +#define tickIf(p) elapsed +=(p)?1:0 +#endif /* memory access (indirect if callback installed) -- ARGUMENTS ARE EVALUATED MORE THAN ONCE! */ #define putMemory(ADDR, BYTE) \ @@ -873,7 +875,7 @@ void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll) # define begin() fetch(); next() # define fetch() pollints(); tpc= itabp[memory[PC++]] # define next() goto *tpc -# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) oops(); next() +# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) //oops(); next() # define end() #else /* (!__GNUC__) || (__STRICT_ANSI__) */ @@ -931,7 +933,7 @@ int M6502_disassemble(M6502 *mpu, word ip, char buffer[64]) # define _absx sprintf(s, "%02X%02X,X", b[2], b[1]); return 3; # define _absy sprintf(s, "%02X%02X,Y", b[2], b[1]); return 3; # define _relative sprintf(s, "%04X", ip + 2 + (int8_t)b[1]); return 2; -# define _zpr sprintf(s, "%04X", b[1], ip + 2 + (int8_t)b[2]); return 3; +# define _zpr sprintf(s, "%02X,%04X", b[1], ip + 2 + (int8_t)b[2]); return 3; # define _indirect sprintf(s, "(%02X%02X)", b[2], b[1]); return 3; # define _indzp sprintf(s, "(%02X)", b[1]); return 2; # define _indx sprintf(s, "(%02X,X)", b[1]); return 2; @@ -950,7 +952,7 @@ void M6502_dump(M6502 *mpu, char buffer[124]) { M6502_Registers *r= mpu->registers; uint8_t p= r->p; -# define P(N,C) (p & (1 << (N)) ? (C) : '-') +# define P(N,C) ((p & (1 << (N))) ? (C) : '-') sprintf(buffer, "PC=%04X M[PC]=%02X SP=%04X A=%02X X=%02X Y=%02X P=%02X %c%c%c%c%c%c%c%c elapsed: %d", r->pc-1, mpu->memory[r->pc-1], 0x0100 + r->s, r->a, r->x, r->y, r->p, From 927eb2f93e63e03bb7fb3d9c76eaa7cb30e0949a Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 21 Mar 2017 21:29:56 +0000 Subject: [PATCH 073/149] fix cppcheck warning --- src/mame/arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mame/arm.c b/src/mame/arm.c index e9297ea1..f88a025b 100644 --- a/src/mame/arm.c +++ b/src/mame/arm.c @@ -743,7 +743,7 @@ void HandleALU(UINT32 insn) if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15) { if (ARM_DEBUG_CORE) - logerror("%08x: Pipelined R15 (Shift %d)\n", R15,(insn&INSN_I?8:insn&0x10u?12:12)); + logerror("%08x: Pipelined R15 (Shift %d)\n", R15,(insn&INSN_I?8:12)); /* Docs strongly suggest the mode bits should be included here, but it breaks Captain America, as it starts doing unaligned reads */ From 7cf89363490116e5cc51e8d1023378c198ef51a1 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 18:47:19 +0000 Subject: [PATCH 074/149] remove old 6809 cores --- src/copro-mc6809.c | 131 -- src/copro-mc6809.h | 9 - src/copro-mc6809sc.c | 155 -- src/copro-mc6809sc.h | 7 - src/mc6809/config.h | 0 src/mc6809/delegate.c | 37 - src/mc6809/delegate.h | 114 -- src/mc6809/hd6309.c | 2205 ----------------------- src/mc6809/hd6309.h | 58 - src/mc6809/mc6809.c | 1289 -------------- src/mc6809/mc6809.h | 111 -- src/mc6809/mc6809_common.c | 314 ---- src/mc6809/mc6809_common.h | 71 - src/mc6809/pl-endian.h | 38 - src/mc6809/xalloc.h | 28 - src/mc6809/xmalloc.c | 57 - src/mc6809sc/mc6809.c | 3442 ------------------------------------ src/mc6809sc/mc6809.h | 138 -- 18 files changed, 8204 deletions(-) delete mode 100644 src/copro-mc6809.c delete mode 100644 src/copro-mc6809.h delete mode 100644 src/copro-mc6809sc.c delete mode 100644 src/copro-mc6809sc.h delete mode 100644 src/mc6809/config.h delete mode 100644 src/mc6809/delegate.c delete mode 100644 src/mc6809/delegate.h delete mode 100644 src/mc6809/hd6309.c delete mode 100644 src/mc6809/hd6309.h delete mode 100644 src/mc6809/mc6809.c delete mode 100644 src/mc6809/mc6809.h delete mode 100644 src/mc6809/mc6809_common.c delete mode 100644 src/mc6809/mc6809_common.h delete mode 100644 src/mc6809/pl-endian.h delete mode 100644 src/mc6809/xalloc.h delete mode 100644 src/mc6809/xmalloc.c delete mode 100644 src/mc6809sc/mc6809.c delete mode 100644 src/mc6809sc/mc6809.h diff --git a/src/copro-mc6809.c b/src/copro-mc6809.c deleted file mode 100644 index 8c6c4535..00000000 --- a/src/copro-mc6809.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 6809 Co Pro Emulation based on XRoar 6809/6309 emulation - * - * (c) 2016 David Banks - */ -#include -#include -#include -#include "tube-defs.h" -#include "tube.h" -#include "tube-ula.h" -#include "startup.h" -#include "tuberom_6809.h" -#include "tube-client.h" - -#include "copro-mc6809.h" - -#ifdef USE_HD6309 -#include "mc6809/hd6309.h" -#else -#include "mc6809/mc6809.h" -#endif - -static struct MC6809 *mc6809; - -static int overlay_rom = 0; - -static unsigned char *copro_mc6809_ram; - -static unsigned char *copro_mc6809_rom = tuberom_6809_jgh_1_0; - -static int debug = 0; - -static void copro_mc6809_mem_cycle(void *sptr, _Bool rnw, uint16_t addr) { - if (rnw) { - // read cycle - if ((addr & 0xFFF0) == 0xFEE0) { - overlay_rom = 0; - mc6809->D = tube_parasite_read(addr & 7); - } else if (overlay_rom) { - mc6809->D = copro_mc6809_rom[addr & 0x7ff]; - } else { - mc6809->D = copro_mc6809_ram[addr & 0xffff]; - } - if (debug) { - printf("Rd %04x=%02x\r\n", addr, mc6809->D); - } - } else { - // write cycle - if ((addr & 0xFFF0) == 0xFEE0) { - overlay_rom = 0; - tube_parasite_write(addr & 7, mc6809->D); - } else { - copro_mc6809_ram[addr & 0xffff] = mc6809->D; - } - if (debug) { - printf("Wr %04x=%02x\r\n", addr, mc6809->D); - } - } -} - -static void copro_mc6809_poweron_reset() { - // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) - copro_mc6809_ram = copro_mem_reset(0x10000); -} - -static void copro_mc6809_reset() { - // Log ARM performance counters - tube_log_performance_counters(); - - // Re-instate the Tube ROM on reset - overlay_rom = 1; - - // Reset the processor - mc6809->reset(mc6809); - - // Wait for rst become inactive before continuing to execute - tube_wait_for_rst_release(); - - // Reset ARM performance counters - tube_reset_performance_counters(); -} - -void copro_mc6809_emulator() -{ - -#ifdef USE_HD6309 - mc6809 = hd6309_new(); -#else - mc6809 = mc6809_new(); -#endif - - mc6809->mem_cycle = DELEGATE_AS2(void, bool, uint16, copro_mc6809_mem_cycle, (void *)0); - - unsigned int last_rst = 0; - - // Remember the current copro so we can exit if it changes - int last_copro = copro; - - copro_mc6809_poweron_reset(); - copro_mc6809_reset(); - - while (1) - { - // Execute emulator for one instruction - mc6809->run(mc6809); - - MC6809_IRQ_SET(mc6809, 0); - if (tube_irq & 7) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; - // Reset the processor on active edge of rst - if (rst && !last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - break; - } - copro_mc6809_reset(); - } - // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { - MC6809_IRQ_SET(mc6809, 1); - } - - last_rst = rst; - - // IRQ is level sensitive, so check between every instruction - MC6809_FIRQ_SET(mc6809, tube_irq & 1); - } - } -} diff --git a/src/copro-mc6809.h b/src/copro-mc6809.h deleted file mode 100644 index 1f0ef9f0..00000000 --- a/src/copro-mc6809.h +++ /dev/null @@ -1,9 +0,0 @@ -// copro-mc6809.h -#ifndef COPRO_MC6809_H -#define COPRO_MC6809_H - -#define USE_HD6309 - -extern void copro_mc6809_emulator(); - -#endif diff --git a/src/copro-mc6809sc.c b/src/copro-mc6809sc.c deleted file mode 100644 index 1ce43930..00000000 --- a/src/copro-mc6809sc.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 6809 Co Pro Emulation based on Sean Conner's 6809 emulator - * - * (c) 2016 David Banks - */ -#include -#include -#include -#include "tube-defs.h" -#include "tube.h" -#include "tube-ula.h" -#include "startup.h" -#include "tuberom_6809.h" - -#include "copro-mc6809sc.h" - -#include "mc6809sc/mc6809.h" -#include "tube-client.h" - - -static int overlay_rom = 0; - -static unsigned char *copro_mc6809_ram; - -static unsigned char *copro_mc6809_rom = tuberom_6809_jgh_1_0; - -static int debug = 0; - -static mc6809__t cpu; - -static void copro_mc6809sc_write(mc6809__t *cpuptr, mc6809addr__t addr, mc6809byte__t data) { - if ((addr & 0xFFF0) == 0xFEE0) { - overlay_rom = 0; - tube_parasite_write(addr & 7, data); - } else { - copro_mc6809_ram[addr & 0xffff] = data; - } - if (debug) { - printf("Wr %04x=%02x\r\n", addr, data); - } -} - -static mc6809byte__t copro_mc6809sc_read(mc6809__t *cpuptr, mc6809addr__t addr, bool opcode_fetch) { - mc6809byte__t data; - if ((addr & 0xFFF0) == 0xFEE0) { - overlay_rom = 0; - data = tube_parasite_read(addr & 7); - } else if (overlay_rom) { - data = copro_mc6809_rom[addr & 0x7ff]; - } else { - data = copro_mc6809_ram[addr & 0xffff]; - } - if (debug) { - printf("Rd %04x=%02x\r\n", addr, data); - } - return data; -} - - -static void copro_mc6809sc_fault(mc6809__t *cpuptr, mc6809fault__t fault) { - - switch (fault) { - case MC6809_FAULT_INTERNAL_ERROR: - printf("MC6809_FAULT_INTERNAL_ERROR\r\n"); - break; - case MC6809_FAULT_INSTRUCTION: - printf(" MC6809_FAULT_INSTRUCTION\r\n"); - break; - case MC6809_FAULT_ADDRESS_MODE: - printf("MC6809_FAULT_ADDRESS_MODE\r\n"); - break; - case MC6809_FAULT_EXG: - printf("MC6809_FAULT_EXG\r\n"); - break; - case MC6809_FAULT_TFR: - printf("MC6809_FAULT_TFR\r\n"); - break; - case MC6809_FAULT_user: - printf("MC6809_FAULT_use\r\n"); - break; - default: - printf("undefined MC6809 fault, code=%d\r\n", fault); - } - printf("pc=%04x\r\n", cpuptr->instpc); - printf("opcode=%02x\r\n", cpuptr->inst); -} - -static void copro_mc6809_poweron_reset() { - // Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502) - copro_mc6809_ram = copro_mem_reset(0x10000); -} - -static void copro_mc6809_reset() { - // Log ARM performance counters - tube_log_performance_counters(); - - // Re-instate the Tube ROM on reset - overlay_rom = 1; - - // Reset the processor - mc6809_reset(&cpu); - - // Wait for rst become inactive before continuing to execute - tube_wait_for_rst_release(); - - // Reset ARM performance counters - tube_reset_performance_counters(); -} - -void copro_mc6809sc_emulator() -{ - - cpu.read = copro_mc6809sc_read; - cpu.write = copro_mc6809sc_write; - cpu.fault = copro_mc6809sc_fault; - - unsigned int last_rst = 0; - - // Remember the current copro so we can exit if it changes - int last_copro = copro; - - copro_mc6809_poweron_reset(); - copro_mc6809_reset(); - - while (1) - { - // Execute emulator for one instruction - if (cpu.sync == 0) { - mc6809_step(&cpu); - } - - if (tube_irq &7) { - cpu.sync = 0; - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; - // Reset the processor on active edge of rst - if (rst && !last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - break; - } - copro_mc6809_reset(); - } - // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { - cpu.irq = true; - } - - last_rst = rst; - - // IRQ is level sensitive, so check between every instruction - cpu.firq = tube_irq & 1; - } - } -} diff --git a/src/copro-mc6809sc.h b/src/copro-mc6809sc.h deleted file mode 100644 index ad792061..00000000 --- a/src/copro-mc6809sc.h +++ /dev/null @@ -1,7 +0,0 @@ -// copro-mc6809sc.h -#ifndef COPRO_MC6809SC_H -#define COPRO_MC6809SC_H - -extern void copro_mc6809sc_emulator(); - -#endif diff --git a/src/mc6809/config.h b/src/mc6809/config.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/mc6809/delegate.c b/src/mc6809/delegate.c deleted file mode 100644 index c988ee75..00000000 --- a/src/mc6809/delegate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - -Delegates in C -Copyright 2014-2015, Ciaran Anscomb - -This is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation; either version 2.1 of the License, or (at your -option) any later version. - -Implement the default no-op functions for defined delegate types. - -*/ - -#include "config.h" - -#include - -#include "delegate.h" - -DELEGATE_DEF_FUNC0(void, void, ) -DELEGATE_DEF_FUNC1(void, void, _Bool, bool, ) -DELEGATE_DEF_FUNC2(void, void, _Bool, bool, uint16_t, uint16, ) -DELEGATE_DEF_FUNC1(void, void, int, int, ) -DELEGATE_DEF_FUNC2(void, void, int, int, uint8_t *, uint8p, ) -DELEGATE_DEF_FUNC2(void, void, int, int, uint16_t *, uint16p, ) -DELEGATE_DEF_FUNC3(void, void, int, int, _Bool, bool, uint16_t, uint16, ) -DELEGATE_DEF_FUNC1(void, void, unsigned, unsigned, ) -DELEGATE_DEF_FUNC3(void, void, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, ) -DELEGATE_DEF_FUNC1(void, void, uint8_t, uint8, ) -DELEGATE_DEF_FUNC2(void, void, uint16_t, uint16, uint8_t, uint8, ) -DELEGATE_DEF_FUNC1(void, void, float, float, ) -DELEGATE_DEF_FUNC0(unsigned, unsigned, 0) -DELEGATE_DEF_FUNC0(uint8_t, uint8, 0) -DELEGATE_DEF_FUNC1(uint8_t, uint8, uint16_t, uint16, 0) -DELEGATE_DEF_FUNC0(uint8_t *, uint8p, NULL) -DELEGATE_DEF_FUNC2(void, void, uint8_t *, uint8p, unsigned, unsigned, ) diff --git a/src/mc6809/delegate.h b/src/mc6809/delegate.h deleted file mode 100644 index 2676543e..00000000 --- a/src/mc6809/delegate.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - -Delegates in C -Copyright 2014-2015, Ciaran Anscomb - -This is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation; either version 2.1 of the License, or (at your -option) any later version. - -*/ - -#ifndef DELEGATE_H__oeW3udTBnzIVk -#define DELEGATE_H__oeW3udTBnzIVk - -#include - -/* Underlying struct def for delegates. */ - -#define DELEGATE_S0(T) struct { T (*func)(void *); void *sptr; } -#define DELEGATE_S1(T,T0) struct { T (*func)(void *, T0); void *sptr; } -#define DELEGATE_S2(T,T0,T1) struct { T (*func)(void *, T0, T1); void *sptr; } -#define DELEGATE_S3(T,T0,T1,T2) struct { T (*func)(void *, T0, T1, T2); void *sptr; } - -/* Type name for delegates. */ - -#define DELEGATE_T0(N) delegate_##N -#define DELEGATE_T1(N,N0) delegate_##N##_##N0 -#define DELEGATE_T2(N,N0,N1) delegate_##N##_##N0##_##N1 -#define DELEGATE_T3(N,N0,N1,N2) delegate_##N##_##N0##_##N1##_##N2 - -/* Define a set of delegate types. */ - -typedef DELEGATE_S0(void) DELEGATE_T0(void); -typedef DELEGATE_S1(void, _Bool) DELEGATE_T1(void, bool); -typedef DELEGATE_S2(void, _Bool, uint16_t) DELEGATE_T2(void, bool, uint16); -typedef DELEGATE_S1(void, int) DELEGATE_T1(void, int); -typedef DELEGATE_S2(void, int, uint8_t *) DELEGATE_T2(void, int, uint8p); -typedef DELEGATE_S2(void, int, uint16_t *) DELEGATE_T2(void, int, uint16p); -typedef DELEGATE_S1(void, unsigned) DELEGATE_T1(void, unsigned); -typedef DELEGATE_S3(void, unsigned, unsigned, unsigned) DELEGATE_T3(void, unsigned, unsigned, unsigned); -typedef DELEGATE_S1(void, uint8_t) DELEGATE_T1(void, uint8); -typedef DELEGATE_S2(void, uint16_t, uint8_t) DELEGATE_T2(void, uint16, uint8); -typedef DELEGATE_S1(void, float) DELEGATE_T1(void, float); -typedef DELEGATE_S3(void, int, _Bool, uint16_t) DELEGATE_T3(void, int, bool, uint16); -typedef DELEGATE_S0(unsigned) DELEGATE_T0(unsigned); -typedef DELEGATE_S0(uint8_t) DELEGATE_T0(uint8); -typedef DELEGATE_S1(uint8_t, uint16_t) DELEGATE_T1(uint8, uint16); -typedef DELEGATE_S0(uint8_t *) DELEGATE_T0(uint8p); -typedef DELEGATE_S2(void, uint8_t *, unsigned) DELEGATE_T2(void, uint8p, unsigned); - -/* Convenience function for declaring anonymous structs. */ - -#define DELEGATE_INIT(f,s) {f,s} - -#define DELEGATE_AS0(N,f,s) (DELEGATE_T0(N))DELEGATE_INIT(f,s) -#define DELEGATE_AS1(N,N0,f,s) (DELEGATE_T1(N,N0))DELEGATE_INIT(f,s) -#define DELEGATE_AS2(N,N0,N1,f,s) (DELEGATE_T2(N,N0,N1))DELEGATE_INIT(f,s) -#define DELEGATE_AS3(N,N0,N1,N2,f,s) (DELEGATE_T3(N,N0,N1,N2))DELEGATE_INIT(f,s) - -/* Delegate default function names. */ - -#define DELEGATE_DEFAULT_F0(N) delegate_##N##_default -#define DELEGATE_DEFAULT_F1(N,N0) delegate_##N##_default_##N0 -#define DELEGATE_DEFAULT_F2(N,N0,N1) delegate_##N##_default_##N0##_##N1 -#define DELEGATE_DEFAULT_F3(N,N0,N1,N2) delegate_##N##_default_##N0##_##N1##_##N2 - -/* Default no-op functions for defined delegate types. */ - -#define DELEGATE_DEF_PROTO0(T,N) T DELEGATE_DEFAULT_F0(N)(void *) -#define DELEGATE_DEF_PROTO1(T,N,T0,N0) T DELEGATE_DEFAULT_F1(N,N0)(void *, T0) -#define DELEGATE_DEF_PROTO2(T,N,T0,N0,T1,N1) T DELEGATE_DEFAULT_F2(N,N0,N1)(void *, T0, T1) -#define DELEGATE_DEF_PROTO3(T,N,T0,N0,T1,N1,T2,N2) T DELEGATE_DEFAULT_F3(N,N0,N1,N2)(void *, T0, T1, T2) - -#define DELEGATE_DEF_FUNC0(T,N,R) T DELEGATE_DEFAULT_F0(N)(void *sptr) { (void)sptr; return R; } -#define DELEGATE_DEF_FUNC1(T,N,T0,N0,R) T DELEGATE_DEFAULT_F1(N,N0)(void *sptr, T0 v0) { (void)sptr; (void)v0; return R; } -#define DELEGATE_DEF_FUNC2(T,N,T0,N0,T1,N1,R) T DELEGATE_DEFAULT_F2(N,N0,N1)(void *sptr, T0 v0, T1 v1) { (void)sptr; (void)v0; (void)v1; return R; } -#define DELEGATE_DEF_FUNC3(T,N,T0,N0,T1,N1,T2,N2,R) T DELEGATE_DEFAULT_F3(N,N0,N1,N2)(void *sptr, T0 v0, T1 v1, T2 v2) { (void)sptr; (void)v0; (void)v1; (void)v2; return R; } - -DELEGATE_DEF_PROTO0(void, void); -DELEGATE_DEF_PROTO1(void, void, _Bool, bool); -DELEGATE_DEF_PROTO2(void, void, _Bool, bool, uint16_t, uint16); -DELEGATE_DEF_PROTO1(void, void, int, int); -DELEGATE_DEF_PROTO2(void, void, int, int, uint8_t *, uint8p); -DELEGATE_DEF_PROTO2(void, void, int, int, uint16_t *, uint16p); -DELEGATE_DEF_PROTO3(void, void, int, int, _Bool, bool, uint16_t, uint16); -DELEGATE_DEF_PROTO1(void, void, unsigned, unsigned); -DELEGATE_DEF_PROTO3(void, void, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned); -DELEGATE_DEF_PROTO1(void, void, uint8_t, uint8); -DELEGATE_DEF_PROTO2(void, void, uint16_t, uint16, uint8_t, uint8); -DELEGATE_DEF_PROTO1(void, void, float, float); -DELEGATE_DEF_PROTO0(unsigned, unsigned); -DELEGATE_DEF_PROTO0(uint8_t, uint8); -DELEGATE_DEF_PROTO1(uint8_t, uint8, uint16_t, uint16); -DELEGATE_DEF_PROTO0(uint8_t *, uint8p); -DELEGATE_DEF_PROTO2(void, void, uint8_t *, uint8p, unsigned, unsigned); - -#define DELEGATE_DEFAULT0(N) DELEGATE_AS0(N, DELEGATE_DEFAULT_F0(N), NULL) -#define DELEGATE_DEFAULT1(N,N0) DELEGATE_AS1(N, N0, DELEGATE_DEFAULT_F1(N, N0), NULL) -#define DELEGATE_DEFAULT2(N,N0,N1) DELEGATE_AS2(N, N0, N1, DELEGATE_DEFAULT_F2(N, N0, N1), NULL) -#define DELEGATE_DEFAULT3(N,N0,N1,N2) DELEGATE_AS3(N, N0, N1, N2, DELEGATE_DEFAULT_F3(N, N0, N1, N2), NULL) - -/* Calling interface. */ - -#define DELEGATE_CALL0(d) ((d).func((d).sptr)) -#define DELEGATE_CALL1(d,v0) ((d).func((d).sptr,(v0))) -#define DELEGATE_CALL2(d,v0,v1) ((d).func((d).sptr,(v0),(v1))) -#define DELEGATE_CALL3(d,v0,v1,v2) ((d).func((d).sptr,(v0),(v1),(v2))) -#define DELEGATE_SAFE_CALL0(d) do { if ((d).func) { DELEGATE_CALL0((d)); } } while (0) -#define DELEGATE_SAFE_CALL1(d,v0) do { if ((d).func) { DELEGATE_CALL1((d),(v0)); } } while (0) -#define DELEGATE_SAFE_CALL2(d,v0,v1) do { if ((d).func) { DELEGATE_CALL2((d),(v0),(v1)); } } while (0) -#define DELEGATE_SAFE_CALL3(d,v0,v1,v2) do { if ((d).func) { DELEGATE_CALL3((d),(v0),(v1),(v2)); } } while (0) - -#endif /* DELEGATE_H__oeW3udTBnzIVk */ diff --git a/src/mc6809/hd6309.c b/src/mc6809/hd6309.c deleted file mode 100644 index 02ccd57f..00000000 --- a/src/mc6809/hd6309.c +++ /dev/null @@ -1,2205 +0,0 @@ -/* Copyright 2003-2016 Ciaran Anscomb - * - * This file is part of XRoar. - * - * XRoar is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * XRoar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XRoar. If not, see . - */ - -/* References: - * MC6809E data sheet, - * Motorola - * HD6309E data sheet, - * Hitachi - * MC6809 Cycle-By-Cycle Performance, - * http://koti.mbnet.fi/~atjs/mc6809/Information/6809cyc.txt - * Motorola 6809 and Hitachi 6309 Programmers Reference, - * 2009 Darren Atkinson - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "xalloc.h" - -#include "delegate.h" -#include "hd6309.h" -#include "mc6809.h" - -/* - * External interface - */ - -static void hd6309_free(struct MC6809 *cpu); -static void hd6309_reset(struct MC6809 *cpu); -static void hd6309_run(struct MC6809 *cpu); -static void hd6309_jump(struct MC6809 *cpu, uint16_t pc); - -/* - * Common 6809 functions - */ - -#include "mc6809_common.h" - -/* - * Data reading & writing - */ - -/* Compute effective address */ - -static uint16_t ea_direct(struct MC6809 *cpu); -static uint16_t ea_extended(struct MC6809 *cpu); -static uint16_t ea_indexed(struct MC6809 *cpu); - -/* - * Interrupt handling - */ - -static void push_irq_registers(struct MC6809 *cpu); -static void push_firq_registers(struct MC6809 *cpu); -static void stack_irq_registers(struct MC6809 *cpu, _Bool entire); -static void take_interrupt(struct MC6809 *cpu, uint8_t mask, uint16_t vec); -static void instruction_posthook(struct MC6809 *cpu); - -/* - * ALU operations - */ - -/* 16-bit inherent operations */ - -static uint16_t op_neg16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_com16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_lsr16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_ror16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_asr16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_asl16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_rol16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_dec16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_inc16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_tst16(struct MC6809 *cpu, uint16_t in); -static uint16_t op_clr16(struct MC6809 *cpu, uint16_t in); - -/* 16-bit arithmetic operations */ - -static uint16_t op_sbc16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_and16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_eor16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_adc16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_or16(struct MC6809 *cpu, uint16_t a, uint16_t b); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Register handling macros - */ - -#define REG_CC (cpu->reg_cc) -#define REG_D (cpu->reg_d) -#define REG_DP (cpu->reg_dp) -#define REG_X (cpu->reg_x) -#define REG_Y (cpu->reg_y) -#define REG_U (cpu->reg_u) -#define REG_S (cpu->reg_s) -#define REG_PC (cpu->reg_pc) -#define REG_W (hcpu->reg_w) -#define REG_V (hcpu->reg_v) -#define REG_MD (hcpu->reg_md) - -/* Separate read & write for accumulators */ - -#define RREG_A (REG_D >> 8) -#define RREG_B (REG_D & 0xff) -#define WREG_A (MC6809_REG_A(cpu)) -#define WREG_B (MC6809_REG_B(cpu)) - -#define RREG_E (REG_W >> 8) -#define RREG_F (REG_W & 0xff) -#define WREG_E (HD6309_REG_E(hcpu)) -#define WREG_F (HD6309_REG_F(hcpu)) - -#define RREG_Q ((REG_D << 16) | REG_W) - -/* Condition code register macros */ - -#define CC_E (0x80) -#define CC_F (0x40) -#define CC_H (0x20) -#define CC_I (0x10) -#define CC_N (0x08) -#define CC_Z (0x04) -#define CC_V (0x02) -#define CC_C (0x01) - -#define CLR_HNZVC ( REG_CC &= ~(CC_H|CC_N|CC_Z|CC_V|CC_C) ) -#define CLR_NZ ( REG_CC &= ~(CC_N|CC_Z) ) -#define CLR_NZV ( REG_CC &= ~(CC_N|CC_Z|CC_V) ) -#define CLR_NZVC ( REG_CC &= ~(CC_N|CC_Z|CC_V|CC_C) ) -#define CLR_Z ( REG_CC &= ~(CC_Z) ) -#define CLR_NZC ( REG_CC &= ~(CC_N|CC_Z|CC_C) ) -#define CLR_NVC ( REG_CC &= ~(CC_N|CC_V|CC_C) ) -#define CLR_ZC ( REG_CC &= ~(CC_Z|CC_C) ) - -#define SET_Z(r) ( REG_CC |= ((r) ? 0 : CC_Z) ) -#define SET_N8(r) ( REG_CC |= (r&0x80)>>4 ) -#define SET_N16(r) ( REG_CC |= (r&0x8000)>>12 ) -#define SET_H(a,b,r) ( REG_CC |= ((a^b^r)&0x10)<<1 ) -#define SET_C8(r) ( REG_CC |= (r&0x100)>>8 ) -#define SET_C16(r) ( REG_CC |= (r&0x10000)>>16 ) -#define SET_V8(a,b,r) ( REG_CC |= ((a^b^r^(r>>1))&0x80)>>6 ) -#define SET_V16(a,b,r) ( REG_CC |= ((a^b^r^(r>>1))&0x8000)>>14 ) -#define SET_NZ8(r) ( SET_N8(r), SET_Z(r&0xff) ) -#define SET_NZ16(r) ( SET_N16(r), SET_Z(r&0xffff) ) -#define SET_NZC8(r) ( SET_N8(r), SET_Z(r&0xff), SET_C8(r) ) -#define SET_NZVC8(a,b,r) ( SET_N8(r), SET_Z(r&0xff), SET_V8(a,b,r), SET_C8(r) ) -#define SET_NZVC16(a,b,r) ( SET_N16(r), SET_Z(r&0xffff), SET_V16(a,b,r), SET_C16(r) ) - -/* Mode register macros */ - -#define MD_D0 (0x80) -#define MD_IL (0x40) -#define MD_FM (0x02) -#define MD_NM (0x01) - -#define NATIVE_MODE (REG_MD & MD_NM) -#define FIRQ_STACK_ALL (REG_MD & MD_FM) - -/* ------------------------------------------------------------------------- */ - -/* - * External interface - */ - -struct MC6809 *hd6309_new(void) { - struct HD6309 *hcpu = xmalloc(sizeof(*hcpu)); - *hcpu = (struct HD6309){.state=0}; - struct MC6809 *cpu = (struct MC6809 *)hcpu; - cpu->variant = MC6809_VARIANT_HD6309; - cpu->free = hd6309_free; - cpu->reset = hd6309_reset; - cpu->run = hd6309_run; - cpu->jump = hd6309_jump; - // External handlers - cpu->mem_cycle = DELEGATE_DEFAULT2(void, bool, uint16); - hd6309_reset(cpu); - return cpu; -} - -static void hd6309_free(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - free(hcpu); -} - -static void hd6309_reset(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - cpu->halt = 0; - cpu->nmi_armed = 0; - cpu->nmi = cpu->nmi_latch = cpu->nmi_active = 0; - cpu->firq = cpu->firq_latch = cpu->firq_active = 0; - cpu->irq = cpu->irq_latch = cpu->irq_active = 0; - hcpu->state = hd6309_state_reset; -} - -/* Run CPU while cpu->running is true. */ - -static void hd6309_run(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - int i; - - do { - - switch (hcpu->state) { - - case hd6309_state_reset: - REG_DP = 0; - REG_CC |= (CC_F | CC_I); - cpu->nmi_armed = 0; - cpu->nmi = cpu->nmi_active = 0; - cpu->firq_active = 0; - cpu->irq_active = 0; - hcpu->state = hd6309_state_reset_check_halt; - // fall through - - case hd6309_state_reset_check_halt: - if (cpu->halt) { - NVMA_CYCLE; - continue; - } - REG_PC = fetch_word(cpu, MC6809_INT_VEC_RESET); - NVMA_CYCLE; - hcpu->state = hd6309_state_label_a; - continue; - - // done_instruction case for backwards-compatibility - case hd6309_state_done_instruction: - case hd6309_state_label_a: - if (cpu->halt) { - NVMA_CYCLE; - continue; - } - hcpu->state = hd6309_state_label_b; - // fall through - - case hd6309_state_label_b: - if (cpu->nmi_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - hcpu->state = hd6309_state_dispatch_irq; - continue; - } - if (!(REG_CC & CC_F) && cpu->firq_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, FIRQ_STACK_ALL); - hcpu->state = hd6309_state_dispatch_irq; - continue; - } - if (!(REG_CC & CC_I) && cpu->irq_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - hcpu->state = hd6309_state_dispatch_irq; - continue; - } - hcpu->state = hd6309_state_next_instruction; - // Instruction fetch hook called here so that machine - // can be stopped beforehand. - DELEGATE_SAFE_CALL0(cpu->instruction_hook); - continue; - - case hd6309_state_dispatch_irq: - if (cpu->nmi_active) { - cpu->nmi_active = cpu->nmi = cpu->nmi_latch = 0; - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI); - hcpu->state = hd6309_state_label_a; - continue; - } - if (!(REG_CC & CC_F) && cpu->firq_active) { - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ); - hcpu->state = hd6309_state_label_a; - continue; - } - if (!(REG_CC & CC_I) && cpu->irq_active) { - take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ); - hcpu->state = hd6309_state_label_a; - continue; - } - hcpu->state = hd6309_state_cwai_check_halt; - continue; - - case hd6309_state_cwai_check_halt: - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - NVMA_CYCLE; - if (cpu->halt) { - continue; - } - hcpu->state = hd6309_state_dispatch_irq; - continue; - - case hd6309_state_sync: - if (cpu->nmi_active || cpu->firq_active || cpu->irq_active) { - NVMA_CYCLE; - instruction_posthook(cpu); - hcpu->state = hd6309_state_label_b; - continue; - } - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - NVMA_CYCLE; - if (cpu->halt) - hcpu->state = hd6309_state_sync_check_halt; - continue; - - case hd6309_state_sync_check_halt: - NVMA_CYCLE; - if (!cpu->halt) { - hcpu->state = hd6309_state_sync; - } - continue; - - case hd6309_state_tfm: - // order is read, NVMA, write - hcpu->tfm_data = fetch_byte(cpu, *hcpu->tfm_src); - NVMA_CYCLE; - hcpu->state = hd6309_state_tfm_write; - continue; - - case hd6309_state_tfm_write: - if (cpu->nmi_active) { - cpu->nmi = 0; - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI); - hcpu->state = hd6309_state_label_a; - continue; - } - if (!(REG_CC & CC_F) && cpu->firq_active) { - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ); - hcpu->state = hd6309_state_label_a; - continue; - } - if (!(REG_CC & CC_I) && cpu->irq_active) { - take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ); - hcpu->state = hd6309_state_label_a; - continue; - } - store_byte(cpu, *hcpu->tfm_dest, hcpu->tfm_data); - *hcpu->tfm_src += hcpu->tfm_src_mod; - *hcpu->tfm_dest += hcpu->tfm_dest_mod; - REG_W--; - if (REG_W == 0) { - REG_PC += 3; - hcpu->state = hd6309_state_label_a; - break; - } - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - hcpu->state = hd6309_state_tfm; - continue; - - case hd6309_state_next_instruction: - { - unsigned op; - // Fetch op-code and process - hcpu->state = hd6309_state_label_a; - op = byte_immediate(cpu); - switch (op) { - - // 0x00 - 0x0f direct mode ops - // 0x40 - 0x4f inherent A register ops - // 0x50 - 0x5f inherent B register ops - // 0x60 - 0x6f indexed mode ops - // 0x70 - 0x7f extended mode ops - case 0x00: case 0x03: - case 0x04: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: - case 0x0c: case 0x0d: case 0x0f: - case 0x40: case 0x43: - case 0x44: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: - case 0x4c: case 0x4d: case 0x4f: - case 0x50: case 0x53: - case 0x54: case 0x56: case 0x57: - case 0x58: case 0x59: case 0x5a: - case 0x5c: case 0x5d: case 0x5f: - case 0x60: case 0x63: - case 0x64: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: - case 0x6c: case 0x6d: case 0x6f: - case 0x70: case 0x73: - case 0x74: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: - case 0x7c: case 0x7d: case 0x7f: { - uint16_t ea; - unsigned tmp1; - switch ((op >> 4) & 0xf) { - case 0x0: ea = ea_direct(cpu); tmp1 = fetch_byte(cpu, ea); break; - case 0x4: ea = 0; tmp1 = RREG_A; break; - case 0x5: ea = 0; tmp1 = RREG_B; break; - case 0x6: ea = ea_indexed(cpu); tmp1 = fetch_byte(cpu, ea); break; - case 0x7: ea = ea_extended(cpu); tmp1 = fetch_byte(cpu, ea); break; - default: ea = tmp1 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_neg(cpu, tmp1); break; // NEG, NEGA, NEGB - case 0x3: tmp1 = op_com(cpu, tmp1); break; // COM, COMA, COMB - case 0x4: tmp1 = op_lsr(cpu, tmp1); break; // LSR, LSRA, LSRB - case 0x6: tmp1 = op_ror(cpu, tmp1); break; // ROR, RORA, RORB - case 0x7: tmp1 = op_asr(cpu, tmp1); break; // ASR, ASRA, ASRB - case 0x8: tmp1 = op_asl(cpu, tmp1); break; // ASL, ASLA, ASLB - case 0x9: tmp1 = op_rol(cpu, tmp1); break; // ROL, ROLA, ROLB - case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DEC, DECA, DECB - case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INC, INCA, INCB - case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TST, TSTA, TSTB - case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLR, CLRA, CLRB - default: break; - } - switch (op & 0xf) { - case 0xd: // TST - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - default: // the rest need storing - switch ((op >> 4) & 0xf) { - default: - case 0x0: case 0x6: case 0x7: - NVMA_CYCLE; - store_byte(cpu, ea, tmp1); - break; - case 0x4: - WREG_A = tmp1; - if (!NATIVE_MODE) - peek_byte(cpu, REG_PC); - break; - case 0x5: - WREG_B = tmp1; - if (!NATIVE_MODE) - peek_byte(cpu, REG_PC); - break; - } - } - } break; - - /* XXX: in documentation, the usual savings while - * computing effective address don't seem to apply to - * these instructions, so in theory an extra cycles - * needs to be inserted to account for that. Needs - * real hardware rest. */ - - // 0x01, 0x61, 0x71 OIM - // 0x02, 0x62, 0x72 AIM - // 0x05, 0x65, 0x75 EIM - // 0x0b, 0x6b, 0x7b TIM - case 0x01: case 0x61: case 0x71: - case 0x02: case 0x62: case 0x72: - case 0x05: case 0x65: case 0x75: - case 0x0b: case 0x6b: case 0x7b: { - unsigned a, tmp1, tmp2; - tmp2 = byte_immediate(cpu); - switch ((op >> 4) & 0xf) { - default: - case 0x0: a = ea_direct(cpu); tmp1 = fetch_byte(cpu, a); break; - case 0x6: a = ea_indexed(cpu); tmp1 = fetch_byte(cpu, a); break; - case 0x7: a = ea_extended(cpu); tmp1 = fetch_byte(cpu, a); break; - } - switch (op & 0xf) { - default: - case 0x1: tmp1 = op_or(cpu, tmp1, tmp2); break; - case 0x2: tmp1 = op_and(cpu, tmp1, tmp2); break; - case 0x5: tmp1 = op_eor(cpu, tmp1, tmp2); break; - case 0xb: tmp1 = op_and(cpu, tmp1, tmp2); break; - } - switch (op & 0xf) { - case 0xb: // TIM - NVMA_CYCLE; - break; - default: // the others - store_byte(cpu, a, tmp1); - break; - } - } break; - - // 0x0e JMP direct - // 0x6e JMP indexed - // 0x7e JMP extended - case 0x0e: case 0x6e: case 0x7e: { - unsigned ea; - switch ((op >> 4) & 0xf) { - case 0x0: ea = ea_direct(cpu); break; - case 0x6: ea = ea_indexed(cpu); break; - case 0x7: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - REG_PC = ea; - } break; - - // 0x10 Page 2 - case 0x10: - hcpu->state = hd6309_state_instruction_page_2; - continue; - // 0x11 Page 3 - case 0x11: - hcpu->state = hd6309_state_instruction_page_3; - continue; - // 0x12 NOP inherent - case 0x12: peek_byte(cpu, REG_PC); break; - // 0x13 SYNC inherent - case 0x13: - if (!NATIVE_MODE) - peek_byte(cpu, REG_PC); - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - instruction_posthook(cpu); - hcpu->state = hd6309_state_sync; - continue; - // 0x14 SEXW inherent - case 0x14: - REG_D = (REG_W & 0x8000) ? 0xffff : 0; - CLR_NZ; - SET_N16(REG_D); - if (REG_D == 0 && REG_W == 0) - REG_CC |= CC_Z; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - break; - // 0x16 LBRA relative - case 0x16: { - unsigned ea; - ea = long_relative(cpu); - REG_PC += ea; - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - } break; - // 0x17 LBSR relative - case 0x17: { - unsigned ea; - ea = long_relative(cpu); - ea += REG_PC; - NVMA_CYCLE; - NVMA_CYCLE; - if (!NATIVE_MODE) { - NVMA_CYCLE; - NVMA_CYCLE; - } - push_s_word(cpu, REG_PC); - REG_PC = ea; - } break; - // 0x19 DAA inherent - case 0x19: { - unsigned tmp = 0; - if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06; - if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60; - if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60; - tmp += RREG_A; - WREG_A = tmp; - // CC.C NOT cleared, only set if appropriate - CLR_NZV; - SET_NZC8(tmp); - peek_byte(cpu, REG_PC); - } break; - // 0x1a ORCC immediate - case 0x1a: { - unsigned data; - data = byte_immediate(cpu); - REG_CC |= data; - peek_byte(cpu, REG_PC); - } break; - // 0x1c ANDCC immediate - case 0x1c: { - unsigned data; - data = byte_immediate(cpu); - REG_CC &= data; - peek_byte(cpu, REG_PC); - } break; - // 0x1d SEX inherent - case 0x1d: - WREG_A = (RREG_B & 0x80) ? 0xff : 0; - CLR_NZ; - SET_NZ16(REG_D); - if (!NATIVE_MODE) - peek_byte(cpu, REG_PC); - break; - // 0x1e EXG immediate - case 0x1e: { - unsigned postbyte; - uint16_t tmp1, tmp2; - postbyte = byte_immediate(cpu); - switch (postbyte >> 4) { - case 0x0: tmp1 = REG_D; break; - case 0x1: tmp1 = REG_X; break; - case 0x2: tmp1 = REG_Y; break; - case 0x3: tmp1 = REG_U; break; - case 0x4: tmp1 = REG_S; break; - case 0x5: tmp1 = REG_PC; break; - case 0x6: tmp1 = REG_W; break; - case 0x7: tmp1 = REG_V; break; - case 0x8: tmp1 = (RREG_A << 8) | RREG_A; break; - case 0x9: tmp1 = (RREG_B << 8) | RREG_B; break; - case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; - case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; - case 0xe: tmp1 = (RREG_E << 8) | RREG_E; break; - case 0xf: tmp1 = (RREG_F << 8) | RREG_F; break; - default: tmp1 = 0; break; - } - switch (postbyte & 0xf) { - case 0x0: tmp2 = REG_D; REG_D = tmp1; break; - case 0x1: tmp2 = REG_X; REG_X = tmp1; break; - case 0x2: tmp2 = REG_Y; REG_Y = tmp1; break; - case 0x3: tmp2 = REG_U; REG_U = tmp1; break; - case 0x4: tmp2 = REG_S; REG_S = tmp1; break; - case 0x5: tmp2 = REG_PC; REG_PC = tmp1; break; - case 0x6: tmp2 = REG_W; REG_W = tmp1; break; - case 0x7: tmp2 = REG_V; REG_V = tmp1; break; - case 0x8: tmp2 = (RREG_A << 8) | RREG_A; WREG_A = tmp1 >> 8; break; - case 0x9: tmp2 = (RREG_B << 8) | RREG_B; WREG_B = tmp1; break; - case 0xa: tmp2 = (REG_CC << 8) | REG_CC; REG_CC = tmp1; break; - case 0xb: tmp2 = (REG_DP << 8) | REG_DP; REG_DP = tmp1 >> 8; break; - case 0xe: tmp2 = (RREG_E << 8) | RREG_E; WREG_E = tmp1 >> 8; break; - case 0xf: tmp2 = (RREG_F << 8) | RREG_F; WREG_F = tmp1; break; - default: tmp2 = 0; break; - } - switch (postbyte >> 4) { - case 0x0: REG_D = tmp2; break; - case 0x1: REG_X = tmp2; break; - case 0x2: REG_Y = tmp2; break; - case 0x3: REG_U = tmp2; break; - case 0x4: REG_S = tmp2; break; - case 0x5: REG_PC = tmp2; break; - case 0x6: REG_W = tmp2; break; - case 0x7: REG_V = tmp2; break; - case 0x8: WREG_A = tmp2 >> 8; break; - case 0x9: WREG_B = tmp2; break; - case 0xa: REG_CC = tmp2; break; - case 0xb: REG_DP = tmp2 >> 8; break; - case 0xe: WREG_E = tmp2 >> 8; break; - case 0xf: WREG_F = tmp2; break; - default: break; - } - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - if (!NATIVE_MODE) { - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - } - } break; - // 0x1f TFR immediate - case 0x1f: { - unsigned postbyte; - uint16_t tmp1; - postbyte = byte_immediate(cpu); - switch (postbyte >> 4) { - case 0x0: tmp1 = REG_D; break; - case 0x1: tmp1 = REG_X; break; - case 0x2: tmp1 = REG_Y; break; - case 0x3: tmp1 = REG_U; break; - case 0x4: tmp1 = REG_S; break; - case 0x5: tmp1 = REG_PC; break; - case 0x6: tmp1 = REG_W; break; - case 0x7: tmp1 = REG_V; break; - case 0x8: tmp1 = (RREG_A << 8) | RREG_A; break; - case 0x9: tmp1 = (RREG_B << 8) | RREG_B; break; - case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; - case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; - case 0xe: tmp1 = (RREG_E << 8) | RREG_E; break; - case 0xf: tmp1 = (RREG_F << 8) | RREG_F; break; - default: tmp1 = 0; break; - } - switch (postbyte & 0xf) { - case 0x0: REG_D = tmp1; break; - case 0x1: REG_X = tmp1; break; - case 0x2: REG_Y = tmp1; break; - case 0x3: REG_U = tmp1; break; - case 0x4: REG_S = tmp1; break; - case 0x5: REG_PC = tmp1; break; - case 0x6: REG_W = tmp1; break; - case 0x7: REG_V = tmp1; break; - case 0x8: WREG_A = tmp1 >> 8; break; - case 0x9: WREG_B = tmp1; break; - case 0xa: REG_CC = tmp1; break; - case 0xb: REG_DP = tmp1 >> 8; break; - case 0xe: WREG_E = tmp1 >> 8; break; - case 0xf: WREG_F = tmp1; break; - default: break; - } - NVMA_CYCLE; - NVMA_CYCLE; - if (!NATIVE_MODE) { - NVMA_CYCLE; - NVMA_CYCLE; - } - } break; - - // 0x20 - 0x2f short branches - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: { - unsigned tmp; - tmp = byte_immediate(cpu); - tmp = sex8(tmp); - NVMA_CYCLE; - if (branch_condition(cpu, op)) - REG_PC += tmp; - } break; - - // 0x30 LEAX indexed - case 0x30: - REG_X = ea_indexed(cpu); - CLR_Z; - SET_Z(REG_X); - NVMA_CYCLE; - break; - // 0x31 LEAY indexed - case 0x31: - REG_Y = ea_indexed(cpu); - CLR_Z; - SET_Z(REG_Y); - NVMA_CYCLE; - break; - // 0x32 LEAS indexed - case 0x32: - REG_S = ea_indexed(cpu); - NVMA_CYCLE; - cpu->nmi_armed = 1; // XXX: Really? - break; - // 0x33 LEAU indexed - case 0x33: - REG_U = ea_indexed(cpu); - NVMA_CYCLE; - break; - // 0x34 PSHS immediate - case 0x34: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - peek_byte(cpu, REG_S); - if (postbyte & 0x80) { push_s_word(cpu, REG_PC); } - if (postbyte & 0x40) { push_s_word(cpu, REG_U); } - if (postbyte & 0x20) { push_s_word(cpu, REG_Y); } - if (postbyte & 0x10) { push_s_word(cpu, REG_X); } - if (postbyte & 0x08) { push_s_byte(cpu, REG_DP); } - if (postbyte & 0x04) { push_s_byte(cpu, RREG_B); } - if (postbyte & 0x02) { push_s_byte(cpu, RREG_A); } - if (postbyte & 0x01) { push_s_byte(cpu, REG_CC); } - } - break; - // 0x35 PULS immediate - case 0x35: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - if (postbyte & 0x01) { REG_CC = pull_s_byte(cpu); } - if (postbyte & 0x02) { WREG_A = pull_s_byte(cpu); } - if (postbyte & 0x04) { WREG_B = pull_s_byte(cpu); } - if (postbyte & 0x08) { REG_DP = pull_s_byte(cpu); } - if (postbyte & 0x10) { REG_X = pull_s_word(cpu); } - if (postbyte & 0x20) { REG_Y = pull_s_word(cpu); } - if (postbyte & 0x40) { REG_U = pull_s_word(cpu); } - if (postbyte & 0x80) { REG_PC = pull_s_word(cpu); } - peek_byte(cpu, REG_S); - } - break; - // 0x36 PSHU immediate - case 0x36: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - peek_byte(cpu, REG_U); - if (postbyte & 0x80) { push_u_word(cpu, REG_PC); } - if (postbyte & 0x40) { push_u_word(cpu, REG_S); } - if (postbyte & 0x20) { push_u_word(cpu, REG_Y); } - if (postbyte & 0x10) { push_u_word(cpu, REG_X); } - if (postbyte & 0x08) { push_u_byte(cpu, REG_DP); } - if (postbyte & 0x04) { push_u_byte(cpu, RREG_B); } - if (postbyte & 0x02) { push_u_byte(cpu, RREG_A); } - if (postbyte & 0x01) { push_u_byte(cpu, REG_CC); } - } - break; - // 0x37 PULU immediate - case 0x37: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - if (postbyte & 0x01) { REG_CC = pull_u_byte(cpu); } - if (postbyte & 0x02) { WREG_A = pull_u_byte(cpu); } - if (postbyte & 0x04) { WREG_B = pull_u_byte(cpu); } - if (postbyte & 0x08) { REG_DP = pull_u_byte(cpu); } - if (postbyte & 0x10) { REG_X = pull_u_word(cpu); } - if (postbyte & 0x20) { REG_Y = pull_u_word(cpu); } - if (postbyte & 0x40) { REG_S = pull_u_word(cpu); } - if (postbyte & 0x80) { REG_PC = pull_u_word(cpu); } - peek_byte(cpu, REG_U); - } - break; - // 0x39 RTS inherent - case 0x39: - peek_byte(cpu, REG_PC); - REG_PC = pull_s_word(cpu); - NVMA_CYCLE; - break; - // 0x3a ABX inherent - case 0x3a: - REG_X += RREG_B; - peek_byte(cpu, REG_PC); - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - // 0x3b RTI inherent - case 0x3b: - peek_byte(cpu, REG_PC); - REG_CC = pull_s_byte(cpu); - if (REG_CC & CC_E) { - WREG_A = pull_s_byte(cpu); - WREG_B = pull_s_byte(cpu); - if (NATIVE_MODE) { - WREG_E = pull_s_byte(cpu); - WREG_F = pull_s_byte(cpu); - } - REG_DP = pull_s_byte(cpu); - REG_X = pull_s_word(cpu); - REG_Y = pull_s_word(cpu); - REG_U = pull_s_word(cpu); - REG_PC = pull_s_word(cpu); - } else { - REG_PC = pull_s_word(cpu); - } - cpu->nmi_armed = 1; - peek_byte(cpu, REG_S); - break; - // 0x3c CWAI immediate - case 0x3c: { - unsigned data; - data = byte_immediate(cpu); - REG_CC &= data; - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - stack_irq_registers(cpu, 1); - NVMA_CYCLE; - hcpu->state = hd6309_state_dispatch_irq; - } break; - // 0x3d MUL inherent - case 0x3d: { - unsigned tmp = RREG_A * RREG_B; - REG_D = tmp; - CLR_ZC; - SET_Z(tmp); - if (tmp & 0x80) - REG_CC |= CC_C; - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - } break; - // 0x3f SWI inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_SWI); - hcpu->state = hd6309_state_label_a; - continue; - - // 0x80 - 0xbf A register arithmetic ops - // 0xc0 - 0xff B register arithmetic ops - case 0x80: case 0x81: case 0x82: - case 0x84: case 0x85: case 0x86: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x90: case 0x91: case 0x92: - case 0x94: case 0x95: case 0x96: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0xa0: case 0xa1: case 0xa2: - case 0xa4: case 0xa5: case 0xa6: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xb0: case 0xb1: case 0xb2: - case 0xb4: case 0xb5: case 0xb6: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xc0: case 0xc1: case 0xc2: - case 0xc4: case 0xc5: case 0xc6: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xd0: case 0xd1: case 0xd2: - case 0xd4: case 0xd5: case 0xd6: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xe0: case 0xe1: case 0xe2: - case 0xe4: case 0xe5: case 0xe6: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xf0: case 0xf1: case 0xf2: - case 0xf4: case 0xf5: case 0xf6: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x40) ? RREG_A : RREG_B; - switch ((op >> 4) & 3) { - case 0: tmp2 = byte_immediate(cpu); break; - case 1: tmp2 = byte_direct(cpu); break; - case 2: tmp2 = byte_indexed(cpu); break; - case 3: tmp2 = byte_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBA, SUBB - case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPA, CMPB - case 0x2: tmp1 = op_sbc(cpu, tmp1, tmp2); break; // SBCA, SBCB - case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; // ANDA, ANDB - case 0x5: (void)op_and(cpu, tmp1, tmp2); break; // BITA, BITB - case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDA, LDB - case 0x8: tmp1 = op_eor(cpu, tmp1, tmp2); break; // EORA, EORB - case 0x9: tmp1 = op_adc(cpu, tmp1, tmp2); break; // ADCA, ADCB - case 0xa: tmp1 = op_or(cpu, tmp1, tmp2); break; // ORA, ORB - case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDA, ADDB - default: break; - } - if (!(op & 0x40)) { - WREG_A = tmp1; - } else { - WREG_B = tmp1; - } - } break; - - // 0x83, 0x93, 0xa3, 0xb3 SUBD - // 0x8c, 0x9c, 0xac, 0xbc CMPX - // 0xc3, 0xd3, 0xe3, 0xf3 ADDD - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x8c: case 0x9c: case 0xac: case 0xbc: - case 0xc3: case 0xd3: case 0xe3: case 0xf3: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x08) ? REG_D : REG_X; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0x4f) { - case 0x03: tmp1 = op_sub16(cpu, tmp1, tmp2); break; // SUBD - case 0x0c: (void)op_sub16(cpu, tmp1, tmp2); break; // CMPX - case 0x43: tmp1 = op_add16(cpu, tmp1, tmp2); break; // ADDD - default: break; - } - if (!NATIVE_MODE) - NVMA_CYCLE; - if (!(op & 0x08)) { - REG_D = tmp1; - } - } break; - - // 0x8d BSR - // 0x9d, 0xad, 0xbd JSR - case 0x8d: case 0x9d: case 0xad: case 0xbd: { - uint16_t ea; - switch ((op >> 4) & 3) { - case 0: ea = short_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 1: ea = ea_direct(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - case 2: ea = ea_indexed(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - case 3: ea = ea_extended(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - default: ea = 0; break; - } - push_s_word(cpu, REG_PC); - REG_PC = ea; - } break; - - // 0x8e, 0x9e, 0xae, 0xbe LDX - // 0xcc, 0xdc, 0xec, 0xfc LDD - // 0xce, 0xde, 0xee, 0xfe LDU - case 0x8e: case 0x9e: case 0xae: case 0xbe: - case 0xcc: case 0xdc: case 0xec: case 0xfc: - case 0xce: case 0xde: case 0xee: case 0xfe: { - unsigned tmp1, tmp2; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - tmp1 = op_ld16(cpu, 0, tmp2); - switch (op & 0x42) { - case 0x02: - REG_X = tmp1; - break; - case 0x40: - REG_D = tmp1; - break; - case 0x42: - REG_U = tmp1; - break; - default: break; - } - } break; - - // 0x97, 0xa7, 0xb7 STA - // 0xd7, 0xe7, 0xf7 STB - case 0x97: case 0xa7: case 0xb7: - case 0xd7: case 0xe7: case 0xf7: { - uint16_t ea; - uint8_t tmp1; - tmp1 = !(op & 0x40) ? RREG_A : RREG_B; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - store_byte(cpu, ea, tmp1); - CLR_NZV; - SET_NZ8(tmp1); - } break; - - // 0x9f, 0xaf, 0xbf STX - // 0xdd, 0xed, 0xfd STD - // 0xdf, 0xef, 0xff STU - case 0x9f: case 0xaf: case 0xbf: - case 0xdd: case 0xed: case 0xfd: - case 0xdf: case 0xef: case 0xff: { - uint16_t ea, tmp1; - switch (op & 0x42) { - case 0x02: tmp1 = REG_X; break; - case 0x40: tmp1 = REG_D; break; - case 0x42: tmp1 = REG_U; break; - default: tmp1 = 0; break; - } - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - CLR_NZV; - SET_NZ16(tmp1); - store_byte(cpu, ea, tmp1 >> 8); - store_byte(cpu, ea+1, tmp1); - } break; - - // 0xcd LDQ immediate - case 0xcd: { - REG_D = word_immediate(cpu); - REG_W = word_immediate(cpu); - CLR_NZV; - SET_N16(REG_D); - if (REG_D == 0 && REG_W == 0) - REG_CC |= CC_Z; - } break; - - // Illegal instruction - default: - // XXX Two dead cycles? Verify further! - peek_byte(cpu, cpu->reg_pc); - peek_byte(cpu, cpu->reg_pc); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - break; - } - - case hd6309_state_instruction_page_2: - { - unsigned op; - hcpu->state = hd6309_state_label_a; - op = byte_immediate(cpu); - switch (op) { - - // 0x10, 0x11 Page 2 - case 0x10: - case 0x11: - hcpu->state = hd6309_state_instruction_page_2; - continue; - - // 0x1021 - 0x102f long branches - case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: { - unsigned tmp = word_immediate(cpu); - if (branch_condition(cpu, op)) { - REG_PC += tmp; - if (!NATIVE_MODE) - NVMA_CYCLE; - } - NVMA_CYCLE; - } break; - - /* XXX: The order in which bits in CC are set when it - * is the destination register is NOT correct. Fixing - * this probably means rewriting all of op_*(). Also, - * the effect on PC as a destination register needs - * investigating. */ - - // 0x1030 ADDR - // 0x1031 ADCR - // 0x1032 SUBR - // 0x1033 SBCR - // 0x1034 ANDR - // 0x1035 ORR - // 0x1036 EORR - // 0x1037 CMPR - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: { - unsigned postbyte; - postbyte = byte_immediate(cpu); - unsigned tmp1, tmp2; - if (!(postbyte & 0x08)) { - // 16-bit operation - switch (postbyte & 0xf) { - case 0x0: tmp1 = REG_D; break; - case 0x1: tmp1 = REG_X; break; - case 0x2: tmp1 = REG_Y; break; - case 0x3: tmp1 = REG_U; break; - case 0x4: tmp1 = REG_S; break; - case 0x5: tmp1 = REG_PC; break; - case 0x6: tmp1 = REG_W; break; - case 0x7: tmp1 = REG_V; break; - default: tmp1 = 0; break; - } - switch ((postbyte >> 4) & 0xf) { - case 0x8: case 0x9: - case 0x0: tmp2 = REG_D; break; - case 0x1: tmp2 = REG_X; break; - case 0x2: tmp2 = REG_Y; break; - case 0x3: tmp2 = REG_U; break; - case 0x4: tmp2 = REG_S; break; - case 0x5: tmp2 = REG_PC; break; - case 0xe: case 0xf: - case 0x6: tmp2 = REG_W; break; - case 0x7: tmp2 = REG_V; break; - case 0xa: tmp2 = REG_CC; break; - case 0xb: tmp2 = REG_DP << 8; break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_add16(cpu, tmp1, tmp2); break; - case 0x1: tmp1 = op_adc16(cpu, tmp1, tmp2); break; - case 0x2: tmp1 = op_sub16(cpu, tmp1, tmp2); break; - case 0x3: tmp1 = op_sbc16(cpu, tmp1, tmp2); break; - case 0x4: tmp1 = op_and16(cpu, tmp1, tmp2); break; - case 0x5: tmp1 = op_or16(cpu, tmp1, tmp2); break; - case 0x6: tmp1 = op_eor16(cpu, tmp1, tmp2); break; - case 0x7: (void)op_sub16(cpu, tmp1, tmp2); break; - default: break; - } - switch (postbyte & 0xf) { - case 0x0: REG_D = tmp1; break; - case 0x1: REG_X = tmp1; break; - case 0x2: REG_Y = tmp1; break; - case 0x3: REG_U = tmp1; break; - case 0x4: REG_S = tmp1; break; - case 0x5: REG_PC = tmp1; break; - case 0x6: REG_W = tmp1; break; - case 0x7: REG_V = tmp1; break; - default: break; - } - } else { - // 8-bit operation - switch (postbyte & 0xf) { - case 0x8: tmp1 = RREG_A; break; - case 0x9: tmp1 = RREG_B; break; - case 0xa: tmp1 = REG_CC; break; - case 0xb: tmp1 = REG_DP; break; - case 0xe: tmp1 = RREG_E; break; - case 0xf: tmp1 = RREG_F; break; - default: tmp1 = 0; break; - } - switch ((postbyte >> 4) & 0xf) { - case 0x0: tmp2 = REG_D & 0xff; break; - case 0x1: tmp2 = REG_X & 0xff; break; - case 0x2: tmp2 = REG_Y & 0xff; break; - case 0x3: tmp2 = REG_U & 0xff; break; - case 0x4: tmp2 = REG_S & 0xff; break; - case 0x5: tmp2 = REG_PC & 0xff; break; - case 0x6: tmp2 = REG_W & 0xff; break; - case 0x7: tmp2 = REG_V & 0xff; break; - case 0x8: tmp2 = RREG_A; break; - case 0x9: tmp2 = RREG_B; break; - case 0xa: tmp2 = REG_CC; break; - case 0xb: tmp2 = REG_DP; break; - case 0xe: tmp2 = RREG_E; break; - case 0xf: tmp2 = RREG_F; break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_add(cpu, tmp1, tmp2); break; - case 0x1: tmp1 = op_adc(cpu, tmp1, tmp2); break; - case 0x2: tmp1 = op_sub(cpu, tmp1, tmp2); break; - case 0x3: tmp1 = op_sbc(cpu, tmp1, tmp2); break; - case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; - case 0x5: tmp1 = op_or(cpu, tmp1, tmp2); break; - case 0x6: tmp1 = op_eor(cpu, tmp1, tmp2); break; - case 0x7: (void)op_sub(cpu, tmp1, tmp2); break; - default: break; - } - switch (postbyte & 0xf) { - case 0x8: WREG_A = tmp1; break; - case 0x9: WREG_B = tmp1; break; - case 0xa: REG_CC = tmp1; break; - case 0xb: REG_DP = tmp1; break; - case 0xe: WREG_E = tmp1; break; - case 0xf: WREG_F = tmp1; break; - default: break; - } - } - NVMA_CYCLE; - } break; - - // 0x1038 PSHSW inherent - case 0x38: - NVMA_CYCLE; - NVMA_CYCLE; - push_s_byte(cpu, RREG_F); - push_s_byte(cpu, RREG_E); - break; - // 0x1039 PULSW inherent - case 0x39: - NVMA_CYCLE; - NVMA_CYCLE; - WREG_E = pull_s_byte(cpu); - WREG_F = pull_s_byte(cpu); - break; - // 0x103a PSHUW inherent - case 0x3a: - NVMA_CYCLE; - NVMA_CYCLE; - push_u_byte(cpu, RREG_F); - push_u_byte(cpu, RREG_E); - break; - // 0x103b PULUW inherent - case 0x3b: - NVMA_CYCLE; - NVMA_CYCLE; - WREG_E = pull_u_byte(cpu); - WREG_F = pull_u_byte(cpu); - break; - // 0x103f SWI2 inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, 0, MC6809_INT_VEC_SWI2); - hcpu->state = hd6309_state_label_a; - continue; - - // XXX to test: is there really no NEGW, ASRW or ASLW? - - // 0x1040 - 0x104f D register inherent ops - // 0x1050 - 0x105f W register inherent ops - case 0x40: case 0x43: - case 0x44: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: - case 0x4c: case 0x4d: case 0x4f: - case 0x53: - case 0x54: case 0x56: - case 0x59: case 0x5a: - case 0x5c: case 0x5d: case 0x5f: { - unsigned tmp1; - tmp1 = !(op & 0x10) ? REG_D : REG_W; - switch (op & 0xf) { - case 0x0: tmp1 = op_neg16(cpu, tmp1); break; // NEGD - case 0x3: tmp1 = op_com16(cpu, tmp1); break; // COMD, COMW - case 0x4: tmp1 = op_lsr16(cpu, tmp1); break; // LSRD, LSRW - case 0x6: tmp1 = op_ror16(cpu, tmp1); break; // RORD, RORW - case 0x7: tmp1 = op_asr16(cpu, tmp1); break; // ASRD - case 0x8: tmp1 = op_asl16(cpu, tmp1); break; // ASLD - case 0x9: tmp1 = op_rol16(cpu, tmp1); break; // ROLD, ROLW - case 0xa: tmp1 = op_dec16(cpu, tmp1); break; // DECD, DECW - case 0xc: tmp1 = op_inc16(cpu, tmp1); break; // INCD, INCW - case 0xd: tmp1 = op_tst16(cpu, tmp1); break; // TSTD, TSTW - case 0xf: tmp1 = op_clr16(cpu, tmp1); break; // CLRD, CLRW - default: break; - } - switch (op & 0xf) { - case 0xd: // TST - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - default: // the rest - if (!(op & 0x10)) { - REG_D = tmp1; - } else { - REG_W = tmp1; - } - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - } - } break; - - // 0x1080, 0x1090, 0x10a0, 0x10b0 SUBW - // 0x1081, 0x1091, 0x10a1, 0x10b1 CMPW - // 0x108b, 0x109b, 0x10ab, 0x10bb ADDW - case 0x80: case 0x90: case 0xa0: case 0xb0: - case 0x81: case 0x91: case 0xa1: case 0xb1: - case 0x8b: case 0x9b: case 0xab: case 0xbb: { - unsigned tmp1, tmp2; - tmp1 = REG_W; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_sub16(cpu, tmp1, tmp2); break; - case 0x1: (void)op_sub16(cpu, tmp1, tmp2); break; - case 0xb: tmp1 = op_add16(cpu, tmp1, tmp2); break; - default: break; - } - if (!NATIVE_MODE) - NVMA_CYCLE; - REG_W = tmp1; - } break; - - // 0x1086, 0x1096, 0x10a6, 0x10b6 LDW - // 0x108e, 0x109e, 0x10ae, 0x10be LDY - case 0x86: case 0x96: case 0xa6: case 0xb6: - case 0x8e: case 0x9e: case 0xae: case 0xbe: { - unsigned tmp1, tmp2; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - tmp1 = op_ld16(cpu, 0, tmp2); - if (!(op & 0x08)) { - REG_W = tmp1; - } else { - REG_Y = tmp1; - } - } break; - - // 0x1082, 0x1092, 0x10a2, 0x10b2 SBCD - // 0x1083, 0x1093, 0x10a3, 0x10b3 CMPD - // 0x1084, 0x1094, 0x10a4, 0x10b4 ANDD - // 0x1085, 0x1095, 0x10a5, 0x10b5 BITD - // 0x1088, 0x1098, 0x10a8, 0x10b8 EORD - // 0x1089, 0x1099, 0x10a9, 0x10b9 ADCD - // 0x108a, 0x109a, 0x10aa, 0x10ba ORD - case 0x82: case 0x92: case 0xa2: case 0xb2: - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x84: case 0x94: case 0xa4: case 0xb4: - case 0x85: case 0x95: case 0xa5: case 0xb5: - case 0x88: case 0x98: case 0xa8: case 0xb8: - case 0x89: case 0x99: case 0xa9: case 0xb9: - case 0x8a: case 0x9a: case 0xaa: case 0xba: { - unsigned tmp1, tmp2; - tmp1 = REG_D; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x2: tmp1 = op_sbc16(cpu, tmp1, tmp2); break; - case 0x3: (void)op_sub16(cpu, tmp1, tmp2); break; - case 0x4: tmp1 = op_and16(cpu, tmp1, tmp2); break; - case 0x5: (void)op_and16(cpu, tmp1, tmp2); break; - case 0x8: tmp1 = op_eor16(cpu, tmp1, tmp2); break; - case 0x9: tmp1 = op_adc16(cpu, tmp1, tmp2); break; - case 0xa: tmp1 = op_or16(cpu, tmp1, tmp2); break; - default: break; - } - if (!NATIVE_MODE) - NVMA_CYCLE; - REG_D = tmp1; - } break; - - // 0x108c, 0x109c, 0x10ac, 0x10bc CMPY - case 0x8c: case 0x9c: case 0xac: case 0xbc: { - unsigned tmp1, tmp2; - tmp1 = REG_Y; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - (void)op_sub16(cpu, tmp1, tmp2); // CMPY - if (!NATIVE_MODE) - NVMA_CYCLE; - } break; - - // 0x1097, 0x10a7, 0x10b7 STW - // 0x109f, 0x10af, 0x10bf STY - // 0x10df, 0x10ef, 0x10ff STS - case 0x97: case 0xa7: case 0xb7: - case 0x9f: case 0xaf: case 0xbf: - case 0xdf: case 0xef: case 0xff: { - unsigned ea, tmp1; - switch (op & 0x48) { - case 0x00: tmp1 = REG_W; break; - case 0x08: tmp1 = REG_Y; break; - case 0x48: tmp1 = REG_S; break; - default: tmp1 = 0; break; - } - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - CLR_NZV; - SET_NZ16(tmp1); - store_byte(cpu, ea, tmp1 >> 8); - store_byte(cpu, ea+1, tmp1); - } break; - - // 0x10ce, 0x10de, 0x10ee, 0x10fe LDS - case 0xce: case 0xde: case 0xee: case 0xfe: { - unsigned tmp1; - switch ((op >> 4) & 3) { - case 0: tmp1 = word_immediate(cpu); break; - case 1: tmp1 = word_direct(cpu); break; - case 2: tmp1 = word_indexed(cpu); break; - case 3: tmp1 = word_extended(cpu); break; - default: tmp1 = 0; break; - } - REG_S = op_ld16(cpu, 0, tmp1); - cpu->nmi_armed = 1; - } break; - - // 0x10dc, 0x10ec, 0x10fc LDQ direct, indexed, extended - case 0xdc: case 0xec: case 0xfc: { - unsigned ea; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - REG_D = fetch_word(cpu, ea); - REG_W = fetch_word(cpu, ea+2); - CLR_NZV; - SET_N16(REG_D); - if (REG_D == 0 && REG_W == 0) - REG_CC |= CC_Z; - } break; - - // 0x10dd, 0x10ed, 0x10fd STQ - case 0xdd: case 0xed: case 0xfd: { - unsigned ea; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - store_byte(cpu, ea, REG_D >> 8); - store_byte(cpu, ea + 1, REG_D); - store_byte(cpu, ea + 2, REG_W >> 8); - store_byte(cpu, ea + 3, REG_W); - CLR_NZV; - SET_N16(REG_D); - if (REG_D == 0 && REG_W == 0) - REG_CC |= CC_Z; - } break; - - // Illegal instruction - default: - peek_byte(cpu, cpu->reg_pc); - peek_byte(cpu, cpu->reg_pc); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - break; - } - - case hd6309_state_instruction_page_3: - { - unsigned op; - hcpu->state = hd6309_state_label_a; - op = byte_immediate(cpu); - switch (op) { - - // 0x10, 0x11 Page 3 - case 0x10: - case 0x11: - hcpu->state = hd6309_state_instruction_page_3; - continue; - - // 0x1130 - 0x1137 direct logical bit ops - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: { - unsigned postbyte; - unsigned mem_byte; - unsigned ea; - postbyte = byte_immediate(cpu); - ea = ea_direct(cpu); - mem_byte = fetch_byte(cpu, ea); - int dest_bit = postbyte & 7; - int src_bit = (postbyte >> 3) & 7; - int src_lsl = dest_bit - src_bit; - unsigned reg_code = (postbyte >> 6) & 3; - unsigned dst_mask = (1 << dest_bit); - unsigned reg_val; - switch (reg_code) { - case 0: reg_val = REG_CC; break; - case 1: reg_val = RREG_A; break; - case 2: reg_val = RREG_B; break; - // Invalid register here does *not* trigger an - // illegal instruction trap. - // TODO: verify if this value is predictable: - default: reg_val = 0; break; - } - unsigned out; - switch (op & 7) { - case 0: // BAND - out = ((mem_byte << src_lsl) & reg_val) & dst_mask; - break; - case 1: // BIAND - out = ((~mem_byte << src_lsl) & reg_val) & dst_mask; - break; - case 2: // BOR - out = ((mem_byte << src_lsl) | reg_val) & dst_mask; - break; - case 3: // BIOR - out = ((~mem_byte << src_lsl) | reg_val) & dst_mask; - break; - case 4: // BEOR - out = ((mem_byte << src_lsl) ^ reg_val) & dst_mask; - break; - case 5: // BIEOR - out = ((~mem_byte << src_lsl) ^ reg_val) & dst_mask; - break; - case 6: // LDBT - out = (mem_byte << src_lsl) & dst_mask; - break; - case 7: // STBT - out = (reg_val << src_lsl) & dst_mask; - break; - default: out = 0; break; - } - if ((op & 7) == 7) { - // STBT - out |= (mem_byte & ~dst_mask); - store_byte(cpu, ea, out); - } else { - switch (reg_code) { - default: - case 0: - REG_CC = (REG_CC & ~dst_mask) | (out & dst_mask); - break; - case 1: - WREG_A = (RREG_A & ~dst_mask) | (out & dst_mask); - break; - case 2: - WREG_B = (RREG_B & ~dst_mask) | (out & dst_mask); - break; - } - } - } break; - - // 0x1138 TFM r0+,r1+ - // 0x1139 TFM r0-,r1- - // 0x113a TFM r0+,r1 - // 0x113b TFM r0,r1+ - case 0x38: case 0x39: case 0x3a: case 0x3b: { - unsigned postbyte; - switch (op & 3) { - case 0: hcpu->tfm_src_mod = hcpu->tfm_dest_mod = 1; break; - case 1: hcpu->tfm_src_mod = hcpu->tfm_dest_mod = -1; break; - case 2: hcpu->tfm_src_mod = 1; hcpu->tfm_dest_mod = 0; break; - case 3: hcpu->tfm_src_mod = 0; hcpu->tfm_dest_mod = 1; break; - default: break; - } - postbyte = byte_immediate(cpu); - // Verified 3 NVMA cycles: - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - switch (postbyte >> 4) { - case 0: hcpu->tfm_src = ®_D; break; - case 1: hcpu->tfm_src = ®_X; break; - case 2: hcpu->tfm_src = ®_Y; break; - case 3: hcpu->tfm_src = ®_U; break; - case 4: hcpu->tfm_src = ®_S; break; - default: - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - switch (postbyte & 0xf) { - case 0: hcpu->tfm_dest = ®_D; break; - case 1: hcpu->tfm_dest = ®_X; break; - case 2: hcpu->tfm_dest = ®_Y; break; - case 3: hcpu->tfm_dest = ®_U; break; - case 4: hcpu->tfm_dest = ®_S; break; - default: - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - REG_PC -= 3; - hcpu->state = hd6309_state_tfm; - continue; - } - - // 0x113c BITMD immediate - case 0x3c: { - unsigned data; - data = byte_immediate(cpu); - data &= (MD_D0 | MD_IL); - if (REG_MD & data) - REG_CC &= ~CC_Z; - else - REG_CC |= CC_Z; - REG_MD &= ~data; - NVMA_CYCLE; - } break; - - // 0x113d LDMD immediate - case 0x3d: { - unsigned data; - data = byte_immediate(cpu); - data &= (MD_FM | MD_NM); - REG_MD = (REG_MD & ~(MD_FM | MD_NM)) | data; - NVMA_CYCLE; - NVMA_CYCLE; - } break; - - // 0x113f SWI3 inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, 0, MC6809_INT_VEC_SWI3); - hcpu->state = hd6309_state_label_a; - continue; - - // 0x1140 - 0x114f E register inherent ops - // 0x1150 - 0x115f F register inherent ops - case 0x43: - case 0x4a: - case 0x4c: case 0x4d: case 0x4f: - case 0x53: - case 0x5a: - case 0x5c: case 0x5d: case 0x5f: { - unsigned tmp1; - tmp1 = !(op & 0x10) ? RREG_E : RREG_F; - switch (op & 0xf) { - case 0x3: tmp1 = op_com(cpu, tmp1); break; // COME, COMF - case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DECE, DECF - case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INCE, INCF - case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TSTE, TSTF - case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLRE, CLRF - default: break; - } - switch (op & 0xf) { - case 0xd: // TST - NVMA_CYCLE; - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - default: // the rest need storing - if (!(op & 0x10)) { - WREG_E = tmp1; - } else { - WREG_F = tmp1; - } - if (!NATIVE_MODE) - NVMA_CYCLE; - break; - } - } break; - - // 0x1180 - 0x11bf E register arithmetic ops - // 0x11c0 - 0x11ff F register arithmetic ops - case 0x80: case 0x81: case 0x86: case 0x8b: - case 0x90: case 0x91: case 0x96: case 0x9b: - case 0xa0: case 0xa1: case 0xa6: case 0xab: - case 0xb0: case 0xb1: case 0xb6: case 0xbb: - case 0xc0: case 0xc1: case 0xc6: case 0xcb: - case 0xd0: case 0xd1: case 0xd6: case 0xdb: - case 0xe0: case 0xe1: case 0xe6: case 0xeb: - case 0xf0: case 0xf1: case 0xf6: case 0xfb: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x40) ? RREG_E : RREG_F; - switch ((op >> 4) & 3) { - case 0: tmp2 = byte_immediate(cpu); break; - case 1: tmp2 = byte_direct(cpu); break; - case 2: tmp2 = byte_indexed(cpu); break; - case 3: tmp2 = byte_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBE, SUBF - case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPE, CMPF - case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDE, LDF - case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDE, ADDF - default: break; - } - if (!(op & 0x40)) { - WREG_E = tmp1; - } else { - WREG_F = tmp1; - } - } break; - - // 0x1183, 0x1193, 0x11a3, 0x11b3 CMPU - // 0x118c, 0x119c, 0x11ac, 0x11bc CMPS - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x8c: case 0x9c: case 0xac: case 0xbc: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x08) ? REG_U : REG_S; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - (void)op_sub16(cpu, tmp1, tmp2); // CMPU, CMPS - if (!NATIVE_MODE) - NVMA_CYCLE; - } break; - - // 0x118d, 0x119d, 0x11ad, 0x11bd DIVD - case 0x8d: case 0x9d: case 0xad: case 0xbd: { - uint16_t tmp1; - uint8_t tmp2; - tmp1 = REG_D; - switch ((op >> 4) & 3) { - case 0: tmp2 = byte_immediate(cpu); break; - case 1: tmp2 = byte_direct(cpu); break; - case 2: tmp2 = byte_indexed(cpu); break; - case 3: tmp2 = byte_extended(cpu); break; - default: tmp2 = 0; break; - } - if (tmp2 == 0) { - REG_MD |= MD_D0; - stack_irq_registers(cpu, 1); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - int16_t stmp1 = *((int16_t *)&tmp1); - int8_t stmp2 = *((int8_t *)&tmp2); - int quotient = stmp1 / stmp2; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - CLR_NZVC; - if (quotient >= -256 && quotient < 256) { - WREG_B = quotient; - WREG_A = stmp1 - (quotient * stmp2); - REG_CC |= (RREG_B & 1); - for (i = 12; i; i--) - NVMA_CYCLE; - if ((quotient >= 0) == ((RREG_B & 0x80) == 0)) { - SET_NZ8(RREG_B); - NVMA_CYCLE; - } else { - REG_CC |= (CC_N | CC_V); - } - } else { - REG_CC |= CC_V; - } - } break; - - // 0x118e, 0x119e, 0x11ae, 0x11be DIVQ - case 0x8e: case 0x9e: case 0xae: case 0xbe: { - uint32_t tmp1; - uint16_t tmp2; - tmp1 = RREG_Q; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - if (tmp2 == 0) { - REG_MD |= MD_D0; - stack_irq_registers(cpu, 1); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - int32_t stmp1 = *((int32_t *)&tmp1); - int16_t stmp2 = *((int16_t *)&tmp2); - int quotient = stmp1 / stmp2; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - CLR_NZVC; - if (quotient >= -65536 && quotient < 65536) { - REG_W = quotient; - REG_D = stmp1 - (quotient * stmp2); - REG_CC |= (REG_W & 1); - for (i = 21; i; i--) - NVMA_CYCLE; - if ((quotient >= 0) == ((RREG_E & 0x80) == 0)) { - SET_NZ16(REG_W); - } else { - REG_CC |= (CC_N | CC_V); - } - } else { - REG_CC |= CC_V; - } - } break; - - // 0x118f, 0x119f, 0x11af, 0x11bf MULD - case 0x8f: case 0x9f: case 0xaf: case 0xbf: { - uint16_t tmp1, tmp2; - tmp1 = REG_D; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - int16_t stmp1 = *((int16_t *)&tmp1); - int16_t stmp2 = *((int16_t *)&tmp2); - int32_t result = stmp1 * stmp2; - uint32_t uresult = *((uint32_t *)&result); - for (i = 24; i; i--) - NVMA_CYCLE; - REG_D = uresult >> 16; - REG_W = uresult & 0xffff; - CLR_NZ; - SET_N16(REG_D); - if (REG_D == 0 && REG_W == 0) - REG_CC |= CC_N; - } break; - - // 0x1197, 0x11a7, 0x11b7 STE - // 0x11d7, 0x11e7, 0x11f7 STF - case 0x97: case 0xa7: case 0xb7: - case 0xd7: case 0xe7: case 0xf7: { - unsigned ea, tmp1; - tmp1 = !(op & 0x40) ? RREG_E : RREG_F; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - store_byte(cpu, ea, tmp1); - CLR_NZV; - SET_NZ8(tmp1); - } break; - - // Illegal instruction - default: - peek_byte(cpu, cpu->reg_pc); - peek_byte(cpu, cpu->reg_pc); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, HD6309_INT_VEC_ILLEGAL); - hcpu->state = hd6309_state_label_a; - continue; - } - break; - } - - } - - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - instruction_posthook(cpu); - continue; - - } while (cpu->running); - -} - -static void hd6309_jump(struct MC6809 *cpu, uint16_t pc) { - REG_PC = pc; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Common 6809 functions - */ - -#include "mc6809_common.c" - -/* - * Data reading & writing - */ - -/* Compute effective address */ - -static uint16_t ea_direct(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - unsigned ea = REG_DP << 8 | fetch_byte(cpu, REG_PC++); - if (!NATIVE_MODE) - NVMA_CYCLE; - return ea; -} - -static uint16_t ea_extended(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - unsigned ea = fetch_word(cpu, REG_PC); - REG_PC += 2; - if (!NATIVE_MODE) - NVMA_CYCLE; - return ea; -} - -static uint16_t ea_indexed(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - unsigned ea; - uint16_t reg; - unsigned postbyte = byte_immediate(cpu); - switch ((postbyte >> 5) & 3) { - case 0: reg = REG_X; break; - case 1: reg = REG_Y; break; - case 2: reg = REG_U; break; - case 3: reg = REG_S; break; - default: reg = 0; break; - } - if ((postbyte & 0x80) == 0) { - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - return reg + sex5(postbyte); - } - if (postbyte == 0x8f || postbyte == 0x90) { - ea = REG_W; - NVMA_CYCLE; - } else if (postbyte == 0xaf || postbyte == 0xb0) { - ea = word_immediate(cpu); - ea = ea + REG_W; - NVMA_CYCLE; - } else if (postbyte == 0xcf || postbyte == 0xd0) { - ea = REG_W; - REG_W += 2; - NVMA_CYCLE; - NVMA_CYCLE; - } else if (postbyte == 0xef || postbyte == 0xf0) { - REG_W -= 2; - ea = REG_W; - NVMA_CYCLE; - NVMA_CYCLE; - } else switch (postbyte & 0x0f) { - case 0x00: ea = reg; reg += 1; peek_byte(cpu, REG_PC); NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 0x01: ea = reg; reg += 2; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 0x02: reg -= 1; ea = reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 0x03: reg -= 2; ea = reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 0x04: ea = reg; peek_byte(cpu, REG_PC); break; - case 0x05: ea = reg + sex8(RREG_B); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x06: ea = reg + sex8(RREG_A); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x07: ea = reg + sex8(RREG_E); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x08: ea = byte_immediate(cpu); ea = sex8(ea) + reg; NVMA_CYCLE; break; - case 0x09: ea = word_immediate(cpu); ea = ea + reg; NVMA_CYCLE; NVMA_CYCLE; if (!NATIVE_MODE) NVMA_CYCLE; break; - case 0x0a: ea = reg + sex8(RREG_F); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x0b: ea = reg + REG_D; peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC + 1); NVMA_CYCLE; if (!NATIVE_MODE) { NVMA_CYCLE; NVMA_CYCLE; } break; - case 0x0c: ea = byte_immediate(cpu); ea = sex8(ea) + REG_PC; NVMA_CYCLE; break; - case 0x0d: ea = word_immediate(cpu); ea = ea + REG_PC; peek_byte(cpu, REG_PC); NVMA_CYCLE; if (!NATIVE_MODE) { NVMA_CYCLE; NVMA_CYCLE; } break; - case 0x0e: ea = reg + REG_W; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x0f: ea = word_immediate(cpu); if (!NATIVE_MODE) NVMA_CYCLE; break; - default: ea = 0; break; - } - if (postbyte & 0x10) { - ea = fetch_word(cpu, ea); - NVMA_CYCLE; - } - switch ((postbyte >> 5) & 3) { - case 0: REG_X = reg; break; - case 1: REG_Y = reg; break; - case 2: REG_U = reg; break; - case 3: REG_S = reg; break; - } - return ea; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Interrupt handling - */ - -static void push_irq_registers(struct MC6809 *cpu) { - struct HD6309 *hcpu = (struct HD6309 *)cpu; - NVMA_CYCLE; - push_s_word(cpu, REG_PC); - push_s_word(cpu, REG_U); - push_s_word(cpu, REG_Y); - push_s_word(cpu, REG_X); - push_s_byte(cpu, REG_DP); - if (NATIVE_MODE) { - push_s_byte(cpu, RREG_F); - push_s_byte(cpu, RREG_E); - } - push_s_byte(cpu, RREG_B); - push_s_byte(cpu, RREG_A); - push_s_byte(cpu, REG_CC); -} - -static void push_firq_registers(struct MC6809 *cpu) { - NVMA_CYCLE; - push_s_word(cpu, REG_PC); - push_s_byte(cpu, REG_CC); -} - -static void stack_irq_registers(struct MC6809 *cpu, _Bool entire) { - if (entire) { - REG_CC |= CC_E; - push_irq_registers(cpu); - } else { - REG_CC &= ~CC_E; - push_firq_registers(cpu); - } -} - -static void take_interrupt(struct MC6809 *cpu, uint8_t mask, uint16_t vec) { - REG_CC |= mask; - NVMA_CYCLE; - DELEGATE_SAFE_CALL1(cpu->interrupt_hook, vec); - REG_PC = fetch_word(cpu, vec); - NVMA_CYCLE; -} - -static void instruction_posthook(struct MC6809 *cpu) { - DELEGATE_SAFE_CALL0(cpu->instruction_posthook); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * ALU operations - */ - -/* 16-bit inherent operations */ - -static uint16_t op_neg16(struct MC6809 *cpu, uint16_t in) { - unsigned out = ~in + 1; - CLR_NZVC; - SET_NZVC16(0, in, out); - return out; -} - -static uint16_t op_com16(struct MC6809 *cpu, uint16_t in) { - unsigned out = ~in; - CLR_NZV; - SET_NZ16(out); - REG_CC |= CC_C; - return out; -} - -static uint16_t op_lsr16(struct MC6809 *cpu, uint16_t in) { - unsigned out = in >> 1; - CLR_NZC; - REG_CC |= (in & 1); - SET_Z(out); - return out; -} - -static uint16_t op_ror16(struct MC6809 *cpu, uint16_t in) { - unsigned out = (in >> 1) | ((REG_CC & 1) << 15); - CLR_NZC; - REG_CC |= (in & 1); - SET_NZ16(out); - return out; -} - -static uint16_t op_asr16(struct MC6809 *cpu, uint16_t in) { - unsigned out = (in >> 1) | (in & 0x8000); - CLR_NZC; - REG_CC |= (in & 1); - SET_NZ16(out); - return out; -} - -static uint16_t op_asl16(struct MC6809 *cpu, uint16_t in) { - unsigned out = in << 1; - CLR_NZVC; - SET_NZVC16(in, in, out); - return out; -} - -static uint16_t op_rol16(struct MC6809 *cpu, uint16_t in) { - unsigned out = (in << 1) | (REG_CC & 1); - CLR_NZVC; - SET_NZVC16(in, in, out); - return out; -} - -static uint16_t op_dec16(struct MC6809 *cpu, uint16_t in) { - unsigned out = in - 1; - CLR_NZV; - SET_NZ16(out); - if (out == 0x7fff) REG_CC |= CC_V; - return out; -} - -static uint16_t op_inc16(struct MC6809 *cpu, uint16_t in) { - unsigned out = in + 1; - CLR_NZV; - SET_NZ16(out); - if (out == 0x8000) REG_CC |= CC_V; - return out; -} - -static uint16_t op_tst16(struct MC6809 *cpu, uint16_t in) { - CLR_NZV; - SET_NZ16(in); - return in; -} - -static uint16_t op_clr16(struct MC6809 *cpu, uint16_t in) { - (void)in; - CLR_NVC; - REG_CC |= CC_Z; - return 0; -} - -/* 16-bit arithmetic operations */ - -static uint16_t op_sbc16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a - b - (REG_CC & CC_C); - CLR_NZVC; - SET_NZVC16(a, b, out); - return out; -} - -static uint16_t op_and16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a & b; - CLR_NZV; - SET_NZ16(out); - return out; -} - -static uint16_t op_eor16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a ^ b; - CLR_NZV; - SET_NZ16(out); - return out; -} - -static uint16_t op_adc16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a + b + (REG_CC & CC_C); - CLR_NZVC; - SET_NZVC16(a, b, out); - return out; -} - -static uint16_t op_or16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a | b; - CLR_NZV; - SET_NZ16(out); - return out; -} diff --git a/src/mc6809/hd6309.h b/src/mc6809/hd6309.h deleted file mode 100644 index d6feb1bb..00000000 --- a/src/mc6809/hd6309.h +++ /dev/null @@ -1,58 +0,0 @@ -/* XRoar - a Dragon/Tandy Coco emulator - * Copyright (C) 2003-2016 Ciaran Anscomb - * - * See COPYING.GPL for redistribution conditions. */ - -#ifndef XROAR_HD6309_H_ -#define XROAR_HD6309_H_ - -#include - -#include "mc6809.h" - -#define MC6809_VARIANT_HD6309 (0x00006309) - -#define HD6309_INT_VEC_ILLEGAL (0xfff0) - -/* MPU state. Represents current position in the high-level flow chart from - * the data sheet (figure 14). */ -enum hd6309_state { - hd6309_state_label_a, - hd6309_state_sync, - hd6309_state_dispatch_irq, - hd6309_state_label_b, - hd6309_state_reset, - hd6309_state_reset_check_halt, - hd6309_state_next_instruction, - hd6309_state_instruction_page_2, - hd6309_state_instruction_page_3, - hd6309_state_cwai_check_halt, - hd6309_state_sync_check_halt, - hd6309_state_done_instruction, - hd6309_state_tfm, - hd6309_state_tfm_write -}; - -struct HD6309 { - struct MC6809 mc6809; - // Separate state variable for the sake of debugging - enum hd6309_state state; - // Extra registers - uint16_t reg_w; - uint8_t reg_md; - uint16_t reg_v; - // TFM state - uint16_t *tfm_src; - uint16_t *tfm_dest; - uint8_t tfm_data; - uint16_t tfm_src_mod; - uint16_t tfm_dest_mod; -}; - -#define HD6309_REG_E(hcpu) (*((uint8_t *)&hcpu->reg_w + MC6809_REG_HI)) -#define HD6309_REG_F(hcpu) (*((uint8_t *)&hcpu->reg_w + MC6809_REG_LO)) - -/* new still returns a struct MC6809 */ -struct MC6809 *hd6309_new(void); - -#endif /* XROAR_HD6309_H_ */ diff --git a/src/mc6809/mc6809.c b/src/mc6809/mc6809.c deleted file mode 100644 index b7fcd588..00000000 --- a/src/mc6809/mc6809.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* Copyright 2003-2016 Ciaran Anscomb - * - * This file is part of XRoar. - * - * XRoar is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * XRoar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XRoar. If not, see . - */ - -/* References: - * MC6809E data sheet, - * Motorola - * MC6809 Cycle-By-Cycle Performance, - * http://koti.mbnet.fi/~atjs/mc6809/Information/6809cyc.txt - * Dragon Update, Illegal Op-codes, - * Feb 1994 Ciaran Anscomb - * Motorola 6809 and Hitachi 6309 Programmers Reference, - * 2009 Darren Atkinson - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "xalloc.h" - -#include "delegate.h" -#include "mc6809.h" - -inline void MC6809_HALT_SET(struct MC6809 *cpu, _Bool val) { - cpu->halt = val; -} - -inline void MC6809_NMI_SET(struct MC6809 *cpu, _Bool val) { - cpu->nmi = val; -} - -inline void MC6809_FIRQ_SET(struct MC6809 *cpu, _Bool val) { - cpu->firq = val; -} - -inline void MC6809_IRQ_SET(struct MC6809 *cpu, _Bool val) { - cpu->irq = val; -} - -/* - * External interface - */ - -static void mc6809_free(struct MC6809 *cpu); -static void mc6809_reset(struct MC6809 *cpu); -static void mc6809_run(struct MC6809 *cpu); -static void mc6809_jump(struct MC6809 *cpu, uint16_t pc); - -/* - * Common 6809 functions - */ - -#include "mc6809_common.h" - -/* - * Data reading & writing - */ - -/* Compute effective address */ - -static uint16_t ea_direct(struct MC6809 *cpu); -static uint16_t ea_extended(struct MC6809 *cpu); -static uint16_t ea_indexed(struct MC6809 *cpu); - -/* - * Interrupt handling - */ - -static void push_irq_registers(struct MC6809 *cpu); -static void push_firq_registers(struct MC6809 *cpu); -static void stack_irq_registers(struct MC6809 *cpu, _Bool entire); -static void take_interrupt(struct MC6809 *cpu, uint8_t mask, uint16_t vec); -static void instruction_posthook(struct MC6809 *cpu); - -/* - * ALU operations - */ - -/* Illegal 6809 8-bit inherent operations */ - -static uint8_t op_negcom(struct MC6809 *cpu, uint8_t in); - -/* Illegal 6809 8-bit arithmetic operations */ - -static uint8_t op_discard(struct MC6809 *cpu, uint8_t a, uint8_t b); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Register handling macros - */ - -#define REG_CC (cpu->reg_cc) -#define REG_D (cpu->reg_d) -#define REG_DP (cpu->reg_dp) -#define REG_X (cpu->reg_x) -#define REG_Y (cpu->reg_y) -#define REG_U (cpu->reg_u) -#define REG_S (cpu->reg_s) -#define REG_PC (cpu->reg_pc) - -/* Separate read & write for accumulators */ - -#define RREG_A (REG_D >> 8) -#define RREG_B (REG_D & 0xff) -#define WREG_A (MC6809_REG_A(cpu)) -#define WREG_B (MC6809_REG_B(cpu)) - -/* Condition code register macros */ - -#define CC_E (0x80) -#define CC_F (0x40) -#define CC_H (0x20) -#define CC_I (0x10) -#define CC_N (0x08) -#define CC_Z (0x04) -#define CC_V (0x02) -#define CC_C (0x01) - -#define CLR_HNZVC ( REG_CC &= ~(CC_H|CC_N|CC_Z|CC_V|CC_C) ) -#define CLR_NZ ( REG_CC &= ~(CC_N|CC_Z) ) -#define CLR_NZV ( REG_CC &= ~(CC_N|CC_Z|CC_V) ) -#define CLR_NZVC ( REG_CC &= ~(CC_N|CC_Z|CC_V|CC_C) ) -#define CLR_Z ( REG_CC &= ~(CC_Z) ) -#define CLR_NZC ( REG_CC &= ~(CC_N|CC_Z|CC_C) ) -#define CLR_NVC ( REG_CC &= ~(CC_N|CC_V|CC_C) ) -#define CLR_ZC ( REG_CC &= ~(CC_Z|CC_C) ) - -#define SET_Z(r) ( REG_CC |= ((r) ? 0 : CC_Z) ) -#define SET_N8(r) ( REG_CC |= (r&0x80)>>4 ) -#define SET_N16(r) ( REG_CC |= (r&0x8000)>>12 ) -#define SET_H(a,b,r) ( REG_CC |= ((a^b^r)&0x10)<<1 ) -#define SET_C8(r) ( REG_CC |= (r&0x100)>>8 ) -#define SET_C16(r) ( REG_CC |= (r&0x10000)>>16 ) -#define SET_V8(a,b,r) ( REG_CC |= ((a^b^r^(r>>1))&0x80)>>6 ) -#define SET_V16(a,b,r) ( REG_CC |= ((a^b^r^(r>>1))&0x8000)>>14 ) -#define SET_NZ8(r) ( SET_N8(r), SET_Z(r&0xff) ) -#define SET_NZ16(r) ( SET_N16(r), SET_Z(r&0xffff) ) -#define SET_NZC8(r) ( SET_N8(r), SET_Z(r&0xff), SET_C8(r) ) -#define SET_NZVC8(a,b,r) ( SET_N8(r), SET_Z(r&0xff), SET_V8(a,b,r), SET_C8(r) ) -#define SET_NZVC16(a,b,r) ( SET_N16(r), SET_Z(r&0xffff), SET_V16(a,b,r), SET_C16(r) ) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * External interface - */ - -struct MC6809 *mc6809_new(void) { - struct MC6809 *cpu = xmalloc(sizeof(*cpu)); - *cpu = (struct MC6809){0}; - cpu->variant = MC6809_VARIANT_MC6809; - cpu->free = mc6809_free; - cpu->reset = mc6809_reset; - cpu->run = mc6809_run; - cpu->jump = mc6809_jump; - // External handlers - cpu->mem_cycle = DELEGATE_DEFAULT2(void, bool, uint16); - mc6809_reset(cpu); - return cpu; -} - -static void mc6809_free(struct MC6809 *cpu) { - free(cpu); -} - -static void mc6809_reset(struct MC6809 *cpu) { - cpu->halt = cpu->nmi = 0; - cpu->nmi_armed = 0; - cpu->nmi = cpu->nmi_latch = cpu->nmi_active = 0; - cpu->firq = cpu->firq_latch = cpu->firq_active = 0; - cpu->irq = cpu->irq_latch = cpu->irq_active = 0; - cpu->state = mc6809_state_reset; -} - -/* Run CPU while cpu->running is true. */ - -static void mc6809_run(struct MC6809 *cpu) { - - do { - - switch (cpu->state) { - - case mc6809_state_reset: - REG_DP = 0; - REG_CC |= (CC_F | CC_I); - cpu->nmi_armed = 0; - cpu->nmi = 0; - cpu->nmi_active = 0; - cpu->firq_active = 0; - cpu->irq_active = 0; - cpu->state = mc6809_state_reset_check_halt; - // fall through - - case mc6809_state_reset_check_halt: - if (cpu->halt) { - NVMA_CYCLE; - continue; - } - REG_PC = fetch_word(cpu, MC6809_INT_VEC_RESET); - NVMA_CYCLE; - cpu->state = mc6809_state_label_a; - continue; - - // done_instruction case for backwards-compatibility - case mc6809_state_done_instruction: - case mc6809_state_label_a: - if (cpu->halt) { - NVMA_CYCLE; - continue; - } - cpu->state = mc6809_state_label_b; - // fall through - - case mc6809_state_label_b: - if (cpu->nmi_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - cpu->state = mc6809_state_dispatch_irq; - continue; - } - if (!(REG_CC & CC_F) && cpu->firq_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 0); - cpu->state = mc6809_state_dispatch_irq; - continue; - } - if (!(REG_CC & CC_I) && cpu->irq_active) { - peek_byte(cpu, REG_PC); - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - cpu->state = mc6809_state_dispatch_irq; - continue; - } - cpu->state = mc6809_state_next_instruction; - // Instruction fetch hook called here so that machine - // can be stopped beforehand. - DELEGATE_SAFE_CALL0(cpu->instruction_hook); - continue; - - case mc6809_state_dispatch_irq: - if (cpu->nmi_active) { - cpu->nmi_active = cpu->nmi = cpu->nmi_latch = 0; - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI); - cpu->state = mc6809_state_label_a; - continue; - } - if (!(REG_CC & CC_F) && cpu->firq_active) { - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ); - cpu->state = mc6809_state_label_a; - continue; - } - if (!(REG_CC & CC_I) && cpu->irq_active) { - take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ); - cpu->state = mc6809_state_label_a; - continue; - } - cpu->state = mc6809_state_cwai_check_halt; - continue; - - case mc6809_state_cwai_check_halt: - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - NVMA_CYCLE; - if (cpu->halt) { - continue; - } - cpu->state = mc6809_state_dispatch_irq; - continue; - - case mc6809_state_sync: - if (cpu->nmi_active || cpu->firq_active || cpu->irq_active) { - NVMA_CYCLE; - instruction_posthook(cpu); - cpu->state = mc6809_state_label_b; - continue; - } - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - NVMA_CYCLE; - if (cpu->halt) - cpu->state = mc6809_state_sync_check_halt; - continue; - - case mc6809_state_sync_check_halt: - NVMA_CYCLE; - if (!cpu->halt) { - cpu->state = mc6809_state_sync; - } - continue; - - case mc6809_state_next_instruction: - { - unsigned op; - cpu->state = mc6809_state_label_a; - // Fetch op-code and process - op = byte_immediate(cpu); - switch (op) { - - // 0x00 - 0x0f direct mode ops - // 0x40 - 0x4f inherent A register ops - // 0x50 - 0x5f inherent B register ops - // 0x60 - 0x6f indexed mode ops - // 0x70 - 0x7f extended mode ops - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0f: - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - case 0x4c: case 0x4d: case 0x4f: - case 0x50: case 0x51: case 0x52: case 0x53: - case 0x54: case 0x55: case 0x56: case 0x57: - case 0x58: case 0x59: case 0x5a: case 0x5b: - case 0x5c: case 0x5d: case 0x5f: - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7f: { - uint16_t ea; - unsigned tmp1; - switch ((op >> 4) & 0xf) { - case 0x0: ea = ea_direct(cpu); tmp1 = fetch_byte(cpu, ea); break; - case 0x4: ea = 0; tmp1 = RREG_A; break; - case 0x5: ea = 0; tmp1 = RREG_B; break; - case 0x6: ea = ea_indexed(cpu); tmp1 = fetch_byte(cpu, ea); break; - case 0x7: ea = ea_extended(cpu); tmp1 = fetch_byte(cpu, ea); break; - default: ea = tmp1 = 0; break; - } - switch (op & 0xf) { - case 0x1: // NEG illegal - case 0x0: tmp1 = op_neg(cpu, tmp1); break; // NEG, NEGA, NEGB - case 0x2: tmp1 = op_negcom(cpu, tmp1); break; // NEGCOM illegal - case 0x3: tmp1 = op_com(cpu, tmp1); break; // COM, COMA, COMB - case 0x5: // LSR illegal - case 0x4: tmp1 = op_lsr(cpu, tmp1); break; // LSR, LSRA, LSRB - case 0x6: tmp1 = op_ror(cpu, tmp1); break; // ROR, RORA, RORB - case 0x7: tmp1 = op_asr(cpu, tmp1); break; // ASR, ASRA, ASRB - case 0x8: tmp1 = op_asl(cpu, tmp1); break; // ASL, ASLA, ASLB - case 0x9: tmp1 = op_rol(cpu, tmp1); break; // ROL, ROLA, ROLB - case 0xb: // DEC illegal - case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DEC, DECA, DECB - case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INC, INCA, INCB - case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TST, TSTA, TSTB - case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLR, CLRA, CLRB - default: break; - } - switch (op & 0xf) { - case 0xd: // TST - NVMA_CYCLE; - NVMA_CYCLE; - break; - default: // the rest need storing - switch ((op >> 4) & 0xf) { - default: - case 0x0: case 0x6: case 0x7: - NVMA_CYCLE; - store_byte(cpu, ea, tmp1); - break; - case 0x4: - WREG_A = tmp1; - peek_byte(cpu, REG_PC); - break; - case 0x5: - WREG_B = tmp1; - peek_byte(cpu, REG_PC); - break; - } - } - } break; - - // 0x0e JMP direct - // 0x6e JMP indexed - // 0x7e JMP extended - case 0x0e: case 0x6e: case 0x7e: { - unsigned ea; - switch ((op >> 4) & 0xf) { - case 0x0: ea = ea_direct(cpu); break; - case 0x6: ea = ea_indexed(cpu); break; - case 0x7: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - REG_PC = ea; - } break; - - // 0x10 Page 2 - case 0x10: - cpu->state = mc6809_state_instruction_page_2; - continue; - // 0x11 Page 3 - case 0x11: - cpu->state = mc6809_state_instruction_page_3; - continue; - // 0x12 NOP inherent - case 0x12: peek_byte(cpu, REG_PC); break; - // 0x13 SYNC inherent - case 0x13: - peek_byte(cpu, REG_PC); - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - instruction_posthook(cpu); - cpu->state = mc6809_state_sync; - continue; - // 0x14, 0x15 HCF? (illegal) - case 0x14: - case 0x15: - cpu->state = mc6809_state_hcf; - break; - // 0x16 LBRA relative - case 0x16: { - uint16_t ea; - ea = long_relative(cpu); - REG_PC += ea; - NVMA_CYCLE; - NVMA_CYCLE; - } break; - // 0x17 LBSR relative - case 0x17: { - uint16_t ea; - ea = long_relative(cpu); - ea += REG_PC; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - push_s_word(cpu, REG_PC); - REG_PC = ea; - } break; - // 0x18 Shift CC with mask inherent (illegal) - case 0x18: - REG_CC = (REG_CC << 1) & (CC_H | CC_Z); - NVMA_CYCLE; - peek_byte(cpu, REG_PC); - break; - // 0x19 DAA inherent - case 0x19: { - unsigned tmp = 0; - if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06; - if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60; - if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60; - tmp += RREG_A; - WREG_A = tmp; - // CC.C NOT cleared, only set if appropriate - CLR_NZV; - SET_NZC8(tmp); - peek_byte(cpu, REG_PC); - } break; - // 0x1a ORCC immediate - case 0x1a: { - unsigned data; - data = byte_immediate(cpu); - REG_CC |= data; - peek_byte(cpu, REG_PC); - } break; - // 0x1b NOP inherent (illegal) - case 0x1b: peek_byte(cpu, REG_PC); break; - // 0x1c ANDCC immediate - case 0x1c: { - unsigned data; - data = byte_immediate(cpu); - REG_CC &= data; - peek_byte(cpu, REG_PC); - } break; - // 0x1d SEX inherent - case 0x1d: - WREG_A = (RREG_B & 0x80) ? 0xff : 0; - CLR_NZ; - SET_NZ16(REG_D); - peek_byte(cpu, REG_PC); - break; - // 0x1e EXG immediate - case 0x1e: { - unsigned postbyte; - uint16_t tmp1, tmp2; - postbyte = byte_immediate(cpu); - switch (postbyte >> 4) { - case 0x0: tmp1 = REG_D; break; - case 0x1: tmp1 = REG_X; break; - case 0x2: tmp1 = REG_Y; break; - case 0x3: tmp1 = REG_U; break; - case 0x4: tmp1 = REG_S; break; - case 0x5: tmp1 = REG_PC; break; - case 0x8: tmp1 = RREG_A | 0xff00; break; - case 0x9: tmp1 = RREG_B | 0xff00; break; - // TODO: verify this behaviour - case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; - case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; - default: tmp1 = 0xffff; break; - } - switch (postbyte & 0xf) { - case 0x0: tmp2 = REG_D; REG_D = tmp1; break; - case 0x1: tmp2 = REG_X; REG_X = tmp1; break; - case 0x2: tmp2 = REG_Y; REG_Y = tmp1; break; - case 0x3: tmp2 = REG_U; REG_U = tmp1; break; - case 0x4: tmp2 = REG_S; REG_S = tmp1; break; - case 0x5: tmp2 = REG_PC; REG_PC = tmp1; break; - case 0x8: tmp2 = RREG_A | 0xff00; WREG_A = tmp1; break; - case 0x9: tmp2 = RREG_B | 0xff00; WREG_B = tmp1; break; - // TODO: verify this behaviour - case 0xa: tmp2 = (REG_CC << 8) | REG_CC; REG_CC = tmp1; break; - case 0xb: tmp2 = (REG_DP << 8) | REG_DP; REG_DP = tmp1; break; - default: tmp2 = 0xffff; break; - } - switch (postbyte >> 4) { - case 0x0: REG_D = tmp2; break; - case 0x1: REG_X = tmp2; break; - case 0x2: REG_Y = tmp2; break; - case 0x3: REG_U = tmp2; break; - case 0x4: REG_S = tmp2; break; - case 0x5: REG_PC = tmp2; break; - case 0x8: WREG_A = tmp2; break; - case 0x9: WREG_B = tmp2; break; - case 0xa: REG_CC = tmp2; break; - case 0xb: REG_DP = tmp2; break; - default: break; - } - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - } break; - // 0x1f TFR immediate - case 0x1f: { - unsigned postbyte; - uint16_t tmp1; - postbyte = byte_immediate(cpu); - switch (postbyte >> 4) { - case 0x0: tmp1 = REG_D; break; - case 0x1: tmp1 = REG_X; break; - case 0x2: tmp1 = REG_Y; break; - case 0x3: tmp1 = REG_U; break; - case 0x4: tmp1 = REG_S; break; - case 0x5: tmp1 = REG_PC; break; - case 0x8: tmp1 = RREG_A | 0xff00; break; - case 0x9: tmp1 = RREG_B | 0xff00; break; - // TODO: verify this behaviour - case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; - case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; - default: tmp1 = 0xffff; break; - } - switch (postbyte & 0xf) { - case 0x0: REG_D = tmp1; break; - case 0x1: REG_X = tmp1; break; - case 0x2: REG_Y = tmp1; break; - case 0x3: REG_U = tmp1; break; - case 0x4: REG_S = tmp1; break; - case 0x5: REG_PC = tmp1; break; - case 0x8: WREG_A = tmp1; break; - case 0x9: WREG_B = tmp1; break; - case 0xa: REG_CC = tmp1; break; - case 0xb: REG_DP = tmp1; break; - default: break; - } - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - } break; - - // 0x20 - 0x2f short branches - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: { - unsigned tmp = sex8(byte_immediate(cpu)); - NVMA_CYCLE; - if (branch_condition(cpu, op)) - REG_PC += tmp; - } break; - - // 0x30 LEAX indexed - case 0x30: - REG_X = ea_indexed(cpu); - CLR_Z; - SET_Z(REG_X); - NVMA_CYCLE; - break; - // 0x31 LEAY indexed - case 0x31: - REG_Y = ea_indexed(cpu); - CLR_Z; - SET_Z(REG_Y); - NVMA_CYCLE; - break; - // 0x32 LEAS indexed - case 0x32: - REG_S = ea_indexed(cpu); - NVMA_CYCLE; - cpu->nmi_armed = 1; // XXX: Really? - break; - // 0x33 LEAU indexed - case 0x33: - REG_U = ea_indexed(cpu); - NVMA_CYCLE; - break; - - // 0x34 PSHS immediate - case 0x34: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - NVMA_CYCLE; - peek_byte(cpu, REG_S); - if (postbyte & 0x80) { push_s_word(cpu, REG_PC); } - if (postbyte & 0x40) { push_s_word(cpu, REG_U); } - if (postbyte & 0x20) { push_s_word(cpu, REG_Y); } - if (postbyte & 0x10) { push_s_word(cpu, REG_X); } - if (postbyte & 0x08) { push_s_byte(cpu, REG_DP); } - if (postbyte & 0x04) { push_s_byte(cpu, RREG_B); } - if (postbyte & 0x02) { push_s_byte(cpu, RREG_A); } - if (postbyte & 0x01) { push_s_byte(cpu, REG_CC); } - } - break; - // 0x35 PULS immediate - case 0x35: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - NVMA_CYCLE; - if (postbyte & 0x01) { REG_CC = pull_s_byte(cpu); } - if (postbyte & 0x02) { WREG_A = pull_s_byte(cpu); } - if (postbyte & 0x04) { WREG_B = pull_s_byte(cpu); } - if (postbyte & 0x08) { REG_DP = pull_s_byte(cpu); } - if (postbyte & 0x10) { REG_X = pull_s_word(cpu); } - if (postbyte & 0x20) { REG_Y = pull_s_word(cpu); } - if (postbyte & 0x40) { REG_U = pull_s_word(cpu); } - if (postbyte & 0x80) { REG_PC = pull_s_word(cpu); } - peek_byte(cpu, REG_S); - } - break; - // 0x36 PSHU immediate - case 0x36: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - NVMA_CYCLE; - peek_byte(cpu, REG_U); - if (postbyte & 0x80) { push_u_word(cpu, REG_PC); } - if (postbyte & 0x40) { push_u_word(cpu, REG_S); } - if (postbyte & 0x20) { push_u_word(cpu, REG_Y); } - if (postbyte & 0x10) { push_u_word(cpu, REG_X); } - if (postbyte & 0x08) { push_u_byte(cpu, REG_DP); } - if (postbyte & 0x04) { push_u_byte(cpu, RREG_B); } - if (postbyte & 0x02) { push_u_byte(cpu, RREG_A); } - if (postbyte & 0x01) { push_u_byte(cpu, REG_CC); } - } - break; - // 0x37 PULU immediate - case 0x37: - { - unsigned postbyte = byte_immediate(cpu); - NVMA_CYCLE; - NVMA_CYCLE; - if (postbyte & 0x01) { REG_CC = pull_u_byte(cpu); } - if (postbyte & 0x02) { WREG_A = pull_u_byte(cpu); } - if (postbyte & 0x04) { WREG_B = pull_u_byte(cpu); } - if (postbyte & 0x08) { REG_DP = pull_u_byte(cpu); } - if (postbyte & 0x10) { REG_X = pull_u_word(cpu); } - if (postbyte & 0x20) { REG_Y = pull_u_word(cpu); } - if (postbyte & 0x40) { REG_S = pull_u_word(cpu); } - if (postbyte & 0x80) { REG_PC = pull_u_word(cpu); } - peek_byte(cpu, REG_U); - } - break; - // 0x38 ANDCC immediate (illegal) - case 0x38: { - unsigned data; - data = byte_immediate(cpu); - REG_CC &= data; - peek_byte(cpu, REG_PC); - /* Differs from legal 0x1c version by - * taking one more cycle: */ - NVMA_CYCLE; - } break; - // 0x39 RTS inherent - case 0x39: - peek_byte(cpu, REG_PC); - REG_PC = pull_s_word(cpu); - NVMA_CYCLE; - break; - // 0x3a ABX inherent - case 0x3a: - REG_X += RREG_B; - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - break; - // 0x3b RTI inherent - case 0x3b: - peek_byte(cpu, REG_PC); - REG_CC = pull_s_byte(cpu); - if (REG_CC & CC_E) { - WREG_A = pull_s_byte(cpu); - WREG_B = pull_s_byte(cpu); - REG_DP = pull_s_byte(cpu); - REG_X = pull_s_word(cpu); - REG_Y = pull_s_word(cpu); - REG_U = pull_s_word(cpu); - REG_PC = pull_s_word(cpu); - } else { - REG_PC = pull_s_word(cpu); - } - cpu->nmi_armed = 1; - peek_byte(cpu, REG_S); - break; - // 0x3c CWAI immediate - case 0x3c: { - unsigned data; - data = byte_immediate(cpu); - REG_CC &= data; - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - stack_irq_registers(cpu, 1); - NVMA_CYCLE; - cpu->state = mc6809_state_dispatch_irq; - } break; - // 0x3d MUL inherent - case 0x3d: { - unsigned tmp = RREG_A * RREG_B; - REG_D = tmp; - CLR_ZC; - SET_Z(tmp); - if (tmp & 0x80) - REG_CC |= CC_C; - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - NVMA_CYCLE; - } break; - // 0x3e RESET (illegal) - case 0x3e: - peek_byte(cpu, REG_PC); - push_irq_registers(cpu); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_RESET); - cpu->state = mc6809_state_label_a; - continue; - // 0x3f SWI inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_SWI); - cpu->state = mc6809_state_label_a; - continue; - - // 0x80 - 0xbf A register arithmetic ops - // 0xc0 - 0xff B register arithmetic ops - case 0x80: case 0x81: case 0x82: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x90: case 0x91: case 0x92: - case 0x94: case 0x95: case 0x96: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0xa0: case 0xa1: case 0xa2: - case 0xa4: case 0xa5: case 0xa6: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xb0: case 0xb1: case 0xb2: - case 0xb4: case 0xb5: case 0xb6: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xc0: case 0xc1: case 0xc2: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xd0: case 0xd1: case 0xd2: - case 0xd4: case 0xd5: case 0xd6: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xe0: case 0xe1: case 0xe2: - case 0xe4: case 0xe5: case 0xe6: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xf0: case 0xf1: case 0xf2: - case 0xf4: case 0xf5: case 0xf6: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x40) ? RREG_A : RREG_B; - switch ((op >> 4) & 3) { - case 0: tmp2 = byte_immediate(cpu); break; - case 1: tmp2 = byte_direct(cpu); break; - case 2: tmp2 = byte_indexed(cpu); break; - case 3: tmp2 = byte_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0xf) { - case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBA, SUBB - case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPA, CMPB - case 0x2: tmp1 = op_sbc(cpu, tmp1, tmp2); break; // SBCA, SBCB - case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; // ANDA, ANDB - case 0x5: (void)op_and(cpu, tmp1, tmp2); break; // BITA, BITB - case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDA, LDB - case 0x7: tmp1 = op_discard(cpu, tmp1, tmp2); break; // illegal - case 0x8: tmp1 = op_eor(cpu, tmp1, tmp2); break; // EORA, EORB - case 0x9: tmp1 = op_adc(cpu, tmp1, tmp2); break; // ADCA, ADCB - case 0xa: tmp1 = op_or(cpu, tmp1, tmp2); break; // ORA, ORB - case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDA, ADDB - default: break; - } - if (!(op & 0x40)) { - WREG_A = tmp1; - } else { - WREG_B = tmp1; - } - } break; - - // 0x83, 0x93, 0xa3, 0xb3 SUBD - // 0x8c, 0x9c, 0xac, 0xbc CMPX - // 0xc3, 0xd3, 0xe3, 0xf3 ADDD - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x8c: case 0x9c: case 0xac: case 0xbc: - case 0xc3: case 0xd3: case 0xe3: case 0xf3: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x08) ? REG_D : REG_X; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - switch (op & 0x4f) { - case 0x03: tmp1 = op_sub16(cpu, tmp1, tmp2); break; // SUBD - case 0x0c: (void)op_sub16(cpu, tmp1, tmp2); break; // CMPX - case 0x43: tmp1 = op_add16(cpu, tmp1, tmp2); break; // ADDD - default: break; - } - NVMA_CYCLE; - if (!(op & 0x08)) { - REG_D = tmp1; - } - } break; - - // 0x8d BSR - // 0x9d, 0xad, 0xbd JSR - case 0x8d: case 0x9d: case 0xad: case 0xbd: { - unsigned ea; - switch ((op >> 4) & 3) { - case 0: ea = short_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 1: ea = ea_direct(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - case 2: ea = ea_indexed(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - case 3: ea = ea_extended(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; - default: ea = 0; break; - } - push_s_word(cpu, REG_PC); - REG_PC = ea; - } break; - - // 0x8e, 0x9e, 0xae, 0xbe LDX - // 0xcc, 0xdc, 0xec, 0xfc LDD - // 0xce, 0xde, 0xee, 0xfe LDU - case 0x8e: case 0x9e: case 0xae: case 0xbe: - case 0xcc: case 0xdc: case 0xec: case 0xfc: - case 0xce: case 0xde: case 0xee: case 0xfe: { - unsigned tmp1, tmp2; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - tmp1 = op_ld16(cpu, 0, tmp2); - switch (op & 0x42) { - case 0x02: - REG_X = tmp1; - break; - case 0x40: - REG_D = tmp1; - break; - case 0x42: - REG_U = tmp1; - break; - default: break; - } - } break; - - // 0x97, 0xa7, 0xb7 STA - // 0xd7, 0xe7, 0xf7 STB - case 0x97: case 0xa7: case 0xb7: - case 0xd7: case 0xe7: case 0xf7: { - uint16_t ea; - uint8_t tmp1; - tmp1 = !(op & 0x40) ? RREG_A : RREG_B; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - store_byte(cpu, ea, tmp1); - CLR_NZV; - SET_NZ8(tmp1); - } break; - - // 0x9f, 0xaf, 0xbf STX - // 0xdd, 0xed, 0xfd STD - // 0xdf, 0xef, 0xff STU - case 0x9f: case 0xaf: case 0xbf: - case 0xdd: case 0xed: case 0xfd: - case 0xdf: case 0xef: case 0xff: { - uint16_t ea, tmp1; - switch (op & 0x42) { - case 0x02: tmp1 = REG_X; break; - case 0x40: tmp1 = REG_D; break; - case 0x42: tmp1 = REG_U; break; - default: tmp1 = 0; break; - } - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - CLR_NZV; - SET_NZ16(tmp1); - store_byte(cpu, ea, tmp1 >> 8); - store_byte(cpu, ea+1, tmp1); - } break; - - // 0x8f STX immediate (illegal) - // 0xcf STU immediate (illegal) - // Illegal instruction only part working - case 0x8f: case 0xcf: { - unsigned tmp1; - tmp1 = !(op & 0x40) ? REG_X : REG_U; - (void)fetch_byte(cpu, REG_PC); - REG_PC++; - store_byte(cpu, REG_PC, tmp1); - REG_PC++; - CLR_NZV; - REG_CC |= CC_N; - } break; - - // 0xcd HCF? (illegal) - case 0xcd: - cpu->state = mc6809_state_hcf; - break; - - // Illegal instruction - default: - NVMA_CYCLE; - break; - } - break; - } - - case mc6809_state_instruction_page_2: - { - unsigned op; - cpu->state = mc6809_state_label_a; - op = byte_immediate(cpu); - switch (op) { - - // 0x10, 0x11 Page 2 - case 0x10: - case 0x11: - cpu->state = mc6809_state_instruction_page_2; - continue; - - // 0x1020 - 0x102f long branches - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: { - unsigned tmp = word_immediate(cpu); - if (branch_condition(cpu, op)) { - REG_PC += tmp; - NVMA_CYCLE; - } - NVMA_CYCLE; - } break; - - // 0x103f SWI2 inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, 0, MC6809_INT_VEC_SWI2); - cpu->state = mc6809_state_label_a; - continue; - - // 0x1083, 0x1093, 0x10a3, 0x10b3 CMPD - // 0x108c, 0x109c, 0x10ac, 0x10bc CMPY - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x8c: case 0x9c: case 0xac: case 0xbc: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x08) ? REG_D : REG_Y; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - (void)op_sub16(cpu, tmp1, tmp2); - NVMA_CYCLE; - } break; - - // 0x108e, 0x109e, 0x10ae, 0x10be LDY - // 0x10ce, 0x10de, 0x10ee, 0x10fe LDS - case 0x8e: case 0x9e: case 0xae: case 0xbe: - case 0xce: case 0xde: case 0xee: case 0xfe: { - unsigned tmp1, tmp2; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - tmp1 = op_ld16(cpu, 0, tmp2); - if (!(op & 0x40)) { - REG_Y = tmp1; - } else { - REG_S = tmp1; - cpu->nmi_armed = 1; - } - } break; - - // 0x109f, 0x10af, 0x10bf STY - // 0x10df, 0x10ef, 0x10ff STS - case 0x9f: case 0xaf: case 0xbf: - case 0xdf: case 0xef: case 0xff: { - unsigned ea, tmp1; - tmp1 = !(op & 0x40) ? REG_Y : REG_S; - switch ((op >> 4) & 3) { - case 1: ea = ea_direct(cpu); break; - case 2: ea = ea_indexed(cpu); break; - case 3: ea = ea_extended(cpu); break; - default: ea = 0; break; - } - CLR_NZV; - SET_NZ16(tmp1); - store_byte(cpu, ea, tmp1 >> 8); - store_byte(cpu, ea+1, tmp1); - } break; - - // Illegal instruction - default: - NVMA_CYCLE; - break; - } - break; - } - - case mc6809_state_instruction_page_3: - { - unsigned op; - cpu->state = mc6809_state_label_a; - op = byte_immediate(cpu); - switch (op) { - - // 0x10, 0x11 Page 3 - case 0x10: - case 0x11: - cpu->state = mc6809_state_instruction_page_3; - continue; - - // 0x113F SWI3 inherent - case 0x3f: - peek_byte(cpu, REG_PC); - stack_irq_registers(cpu, 1); - instruction_posthook(cpu); - take_interrupt(cpu, 0, MC6809_INT_VEC_SWI3); - cpu->state = mc6809_state_label_a; - continue; - - // 0x1183, 0x1193, 0x11a3, 0x11b3 CMPU - // 0x118c, 0x119c, 0x11ac, 0x11bc CMPS - case 0x83: case 0x93: case 0xa3: case 0xb3: - case 0x8c: case 0x9c: case 0xac: case 0xbc: { - unsigned tmp1, tmp2; - tmp1 = !(op & 0x08) ? REG_U : REG_S; - switch ((op >> 4) & 3) { - case 0: tmp2 = word_immediate(cpu); break; - case 1: tmp2 = word_direct(cpu); break; - case 2: tmp2 = word_indexed(cpu); break; - case 3: tmp2 = word_extended(cpu); break; - default: tmp2 = 0; break; - } - (void)op_sub16(cpu, tmp1, tmp2); - NVMA_CYCLE; - } break; - - // Illegal instruction - default: - NVMA_CYCLE; - break; - } - break; - } - - // Certain illegal instructions cause the CPU to lock up: - case mc6809_state_hcf: - NVMA_CYCLE; - continue; - - } - - cpu->nmi_active = cpu->nmi_latch; - cpu->firq_active = cpu->firq_latch; - cpu->irq_active = cpu->irq_latch; - instruction_posthook(cpu); - continue; - - } while (0); // (cpu->running); - -} - -static void mc6809_jump(struct MC6809 *cpu, uint16_t pc) { - REG_PC = pc; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Common 6809 functions - */ - -#include "mc6809_common.c" - -/* - * Data reading & writing - */ - -/* Compute effective address */ - -static uint16_t ea_direct(struct MC6809 *cpu) { - unsigned ea = REG_DP << 8 | fetch_byte(cpu, REG_PC++); - NVMA_CYCLE; - return ea; -} - -static uint16_t ea_extended(struct MC6809 *cpu) { - unsigned ea = fetch_word(cpu, REG_PC); - REG_PC += 2; - NVMA_CYCLE; - return ea; -} - -static uint16_t ea_indexed(struct MC6809 *cpu) { - unsigned ea; - uint16_t reg; - unsigned postbyte = byte_immediate(cpu); - switch ((postbyte >> 5) & 3) { - case 0: reg = REG_X; break; - case 1: reg = REG_Y; break; - case 2: reg = REG_U; break; - case 3: reg = REG_S; break; - default: reg = 0; break; - } - if ((postbyte & 0x80) == 0) { - peek_byte(cpu, REG_PC); - NVMA_CYCLE; - return reg + sex5(postbyte & 0x1f); - } - switch (postbyte & 0x0f) { - case 0x00: ea = reg; reg += 1; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; break; - case 0x01: ea = reg; reg += 2; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x02: reg -= 1; ea = reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; break; - case 0x03: reg -= 2; ea = reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x04: ea = reg; peek_byte(cpu, REG_PC); break; - case 0x05: ea = reg + sex8(RREG_B); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x07: // illegal - case 0x06: ea = reg + sex8(RREG_A); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; - case 0x08: ea = byte_immediate(cpu); ea = sex8(ea) + reg; NVMA_CYCLE; break; - case 0x09: ea = word_immediate(cpu); ea = ea + reg; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x0a: ea = REG_PC | 0xff; break; - case 0x0b: ea = reg + REG_D; peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC + 1); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x0c: ea = byte_immediate(cpu); ea = sex8(ea) + REG_PC; NVMA_CYCLE; break; - case 0x0d: ea = word_immediate(cpu); ea = ea + REG_PC; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; - case 0x0e: ea = 0xffff; break; // illegal - case 0x0f: ea = word_immediate(cpu); NVMA_CYCLE; break; - default: ea = 0; break; - } - if (postbyte & 0x10) { - ea = fetch_word(cpu, ea); - NVMA_CYCLE; - } - switch ((postbyte >> 5) & 3) { - case 0: REG_X = reg; break; - case 1: REG_Y = reg; break; - case 2: REG_U = reg; break; - case 3: REG_S = reg; break; - } - return ea; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Interrupt handling - */ - -static void push_irq_registers(struct MC6809 *cpu) { - NVMA_CYCLE; - push_s_word(cpu, REG_PC); - push_s_word(cpu, REG_U); - push_s_word(cpu, REG_Y); - push_s_word(cpu, REG_X); - push_s_byte(cpu, REG_DP); - push_s_byte(cpu, RREG_B); - push_s_byte(cpu, RREG_A); - push_s_byte(cpu, REG_CC); -} - -static void push_firq_registers(struct MC6809 *cpu) { - NVMA_CYCLE; - push_s_word(cpu, REG_PC); - push_s_byte(cpu, REG_CC); -} - -static void stack_irq_registers(struct MC6809 *cpu, _Bool entire) { - if (entire) { - REG_CC |= CC_E; - push_irq_registers(cpu); - } else { - REG_CC &= ~CC_E; - push_firq_registers(cpu); - } -} - -static void take_interrupt(struct MC6809 *cpu, uint8_t mask, uint16_t vec) { - REG_CC |= mask; - NVMA_CYCLE; - DELEGATE_SAFE_CALL1(cpu->interrupt_hook, vec); - REG_PC = fetch_word(cpu, vec); - NVMA_CYCLE; -} - -static void instruction_posthook(struct MC6809 *cpu) { - DELEGATE_SAFE_CALL0(cpu->instruction_posthook); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * ALU operations - */ - -/* Illegal 6809 8-bit inherent operations */ - -static uint8_t op_negcom(struct MC6809 *cpu, uint8_t in) { - unsigned out = ~in + (~REG_CC & 1); - CLR_NZVC; - SET_NZVC8(0, in, out); - return out; -} - -/* Illegal 6809 8-bit arithmetic operations */ - -static uint8_t op_discard(struct MC6809 *cpu, uint8_t a, uint8_t b) { - (void)b; - CLR_NZV; - REG_CC |= CC_N; - return a; -} diff --git a/src/mc6809/mc6809.h b/src/mc6809/mc6809.h deleted file mode 100644 index c8643eb2..00000000 --- a/src/mc6809/mc6809.h +++ /dev/null @@ -1,111 +0,0 @@ -/* XRoar - a Dragon/Tandy Coco emulator - * Copyright (C) 2003-2016 Ciaran Anscomb - * - * See COPYING.GPL for redistribution conditions. */ - -#ifndef XROAR_MC6809_H_ -#define XROAR_MC6809_H_ - -#include "config.h" - -#include - -#include "pl-endian.h" - -#include "delegate.h" - -#define MC6809_VARIANT_MC6809 (0x00006809) - -#define MC6809_INT_VEC_RESET (0xfefe) -#define MC6809_INT_VEC_NMI (0xfefc) -#define MC6809_INT_VEC_SWI (0xfefa) -#define MC6809_INT_VEC_IRQ (0xfef8) -#define MC6809_INT_VEC_FIRQ (0xfef6) -#define MC6809_INT_VEC_SWI2 (0xfef4) -#define MC6809_INT_VEC_SWI3 (0xfef2) - -#define MC6809_COMPAT_STATE_NORMAL (0) -#define MC6809_COMPAT_STATE_SYNC (1) -#define MC6809_COMPAT_STATE_CWAI (2) -#define MC6809_COMPAT_STATE_DONE_INSTRUCTION (11) -#define MC6809_COMPAT_STATE_HCF (12) - -/* MPU state. Represents current position in the high-level flow chart from - * the data sheet (figure 14). */ -enum mc6809_state { - mc6809_state_label_a = MC6809_COMPAT_STATE_NORMAL, - mc6809_state_sync = MC6809_COMPAT_STATE_SYNC, - mc6809_state_dispatch_irq = MC6809_COMPAT_STATE_CWAI, - mc6809_state_label_b, - mc6809_state_reset, - mc6809_state_reset_check_halt, - mc6809_state_next_instruction, - mc6809_state_instruction_page_2, - mc6809_state_instruction_page_3, - mc6809_state_cwai_check_halt, - mc6809_state_sync_check_halt, - mc6809_state_done_instruction = MC6809_COMPAT_STATE_DONE_INSTRUCTION, - mc6809_state_hcf = MC6809_COMPAT_STATE_HCF -}; - -/* Interface shared with all 6809-compatible CPUs */ -struct MC6809 { - // Variant - uint32_t variant; - - /* Interrupt lines */ - _Bool halt, nmi, firq, irq; - uint8_t D; - - /* Methods */ - - void (*free)(struct MC6809 *cpu); - void (*reset)(struct MC6809 *cpu); - void (*run)(struct MC6809 *cpu); - void (*jump)(struct MC6809 *cpu, uint16_t pc); - - /* External handlers */ - - /* Memory access cycle */ - DELEGATE_T2(void, bool, uint16) mem_cycle; - /* Called just before instruction fetch if non-NULL */ - DELEGATE_T0(void) instruction_hook; - /* Called after instruction is executed */ - DELEGATE_T0(void) instruction_posthook; - /* Called just before an interrupt vector is read */ - DELEGATE_T1(void, int) interrupt_hook; - - /* Internal state */ - - enum mc6809_state state; - _Bool running; - - /* Registers */ - uint8_t reg_cc, reg_dp; - uint16_t reg_d; - uint16_t reg_x, reg_y, reg_u, reg_s, reg_pc; - /* Interrupts */ - _Bool nmi_armed; - _Bool nmi_latch, firq_latch, irq_latch; - _Bool nmi_active, firq_active, irq_active; -}; - -#if __BYTE_ORDER == __BIG_ENDIAN -# define MC6809_REG_HI (0) -# define MC6809_REG_LO (1) -#else -# define MC6809_REG_HI (1) -# define MC6809_REG_LO (0) -#endif - -#define MC6809_REG_A(cpu) (*((uint8_t *)&cpu->reg_d + MC6809_REG_HI)) -#define MC6809_REG_B(cpu) (*((uint8_t *)&cpu->reg_d + MC6809_REG_LO)) - -extern inline void MC6809_HALT_SET(struct MC6809 *cpu, _Bool val); -extern inline void MC6809_NMI_SET(struct MC6809 *cpu, _Bool val); -extern inline void MC6809_FIRQ_SET(struct MC6809 *cpu, _Bool val); -extern inline void MC6809_IRQ_SET(struct MC6809 *cpu, _Bool val); - -struct MC6809 *mc6809_new(void); - -#endif /* XROAR_MC6809_H_ */ diff --git a/src/mc6809/mc6809_common.c b/src/mc6809/mc6809_common.c deleted file mode 100644 index 94c79a3d..00000000 --- a/src/mc6809/mc6809_common.c +++ /dev/null @@ -1,314 +0,0 @@ -/* XRoar - a Dragon/Tandy Coco emulator - * Copyright (C) 2003-2016 Ciaran Anscomb - * - * See COPYING.GPL for redistribution conditions. */ - -/* - * This file is included directly into other source files. It provides - * functions common across 6809 ISA CPUs. - */ - -/* Memory interface */ - -static uint8_t fetch_byte(struct MC6809 *cpu, uint16_t a) { - cpu->nmi_latch |= (cpu->nmi_armed && cpu->nmi); - cpu->firq_latch = cpu->firq; - cpu->irq_latch = cpu->irq; - DELEGATE_CALL2(cpu->mem_cycle, 1, a); - return cpu->D; -} - -static uint16_t fetch_word(struct MC6809 *cpu, uint16_t a) { - unsigned v = fetch_byte(cpu, a) << 8; - return v | fetch_byte(cpu, a+1); -} - -static void store_byte(struct MC6809 *cpu, uint16_t a, uint8_t d) { - cpu->nmi_latch |= (cpu->nmi_armed && cpu->nmi); - cpu->firq_latch = cpu->firq; - cpu->irq_latch = cpu->irq; - cpu->D = d; - DELEGATE_CALL2(cpu->mem_cycle, 0, a); -} - -/* Read & write various addressing modes */ - -static uint8_t byte_immediate(struct MC6809 *cpu) { - return fetch_byte(cpu, REG_PC++); -} - -static uint8_t byte_direct(struct MC6809 *cpu) { - unsigned ea = ea_direct(cpu); - return fetch_byte(cpu, ea); -} - -static uint8_t byte_extended(struct MC6809 *cpu) { - unsigned ea = ea_extended(cpu); - return fetch_byte(cpu, ea); -} - -static uint8_t byte_indexed(struct MC6809 *cpu) { - unsigned ea = ea_indexed(cpu); - return fetch_byte(cpu, ea); -} - -static uint16_t word_immediate(struct MC6809 *cpu) { - unsigned v = fetch_byte(cpu, REG_PC++) << 8; - return v | fetch_byte(cpu, REG_PC++); -} - -static uint16_t word_direct(struct MC6809 *cpu) { - unsigned ea = ea_direct(cpu); - return fetch_word(cpu, ea); -} - -static uint16_t word_extended(struct MC6809 *cpu) { - unsigned ea = ea_extended(cpu); - return fetch_word(cpu, ea); -} - -static uint16_t word_indexed(struct MC6809 *cpu) { - unsigned ea = ea_indexed(cpu); - return fetch_word(cpu, ea); -} - -static uint16_t short_relative(struct MC6809 *cpu) { - return sex8(byte_immediate(cpu)); -} - -/* Stack operations */ - -static void push_s_byte(struct MC6809 *cpu, uint8_t v) { - store_byte(cpu, --REG_S, v); -} - -static void push_s_word(struct MC6809 *cpu, uint16_t v) { - store_byte(cpu, --REG_S, v); - store_byte(cpu, --REG_S, v >> 8); -} - -static uint8_t pull_s_byte(struct MC6809 *cpu) { - return fetch_byte(cpu, REG_S++); -} - -static uint16_t pull_s_word(struct MC6809 *cpu) { - unsigned val = fetch_byte(cpu, REG_S++); - return (val << 8) | fetch_byte(cpu, REG_S++); -} - -static void push_u_byte(struct MC6809 *cpu, uint8_t v) { - store_byte(cpu, --REG_U, v); -} - -static void push_u_word(struct MC6809 *cpu, uint16_t v) { - store_byte(cpu, --REG_U, v); - store_byte(cpu, --REG_U, v >> 8); -} - -static uint8_t pull_u_byte(struct MC6809 *cpu) { - return fetch_byte(cpu, REG_U++); -} - -static uint16_t pull_u_word(struct MC6809 *cpu) { - unsigned val = fetch_byte(cpu, REG_U++); - return (val << 8) | fetch_byte(cpu, REG_U++); -} - -/* 8-bit inherent operations */ - -static uint8_t op_neg(struct MC6809 *cpu, uint8_t in) { - unsigned out = ~in + 1; - CLR_NZVC; - SET_NZVC8(0, in, out); - return out; -} - -static uint8_t op_com(struct MC6809 *cpu, uint8_t in) { - unsigned out = ~in; - CLR_NZV; - SET_NZ8(out); - REG_CC |= CC_C; - return out; -} - -static uint8_t op_lsr(struct MC6809 *cpu, uint8_t in) { - unsigned out = in >> 1; - CLR_NZC; - REG_CC |= (in & 1); - SET_Z(out); - return out; -} - -static uint8_t op_ror(struct MC6809 *cpu, uint8_t in) { - unsigned out = (in >> 1) | ((REG_CC & 1) << 7); - CLR_NZC; - REG_CC |= (in & 1); - SET_NZ8(out); - return out; -} - -static uint8_t op_asr(struct MC6809 *cpu, uint8_t in) { - unsigned out = (in >> 1) | (in & 0x80); - CLR_NZC; - REG_CC |= (in & 1); - SET_NZ8(out); - return out; -} - -static uint8_t op_asl(struct MC6809 *cpu, uint8_t in) { - unsigned out = in << 1; - CLR_NZVC; - SET_NZVC8(in, in, out); - return out; -} - -static uint8_t op_rol(struct MC6809 *cpu, uint8_t in) { - unsigned out = (in << 1) | (REG_CC & 1); - CLR_NZVC; - SET_NZVC8(in, in, out); - return out; -} - -static uint8_t op_dec(struct MC6809 *cpu, uint8_t in) { - unsigned out = in - 1; - CLR_NZV; - SET_NZ8(out); - if (out == 0x7f) REG_CC |= CC_V; - return out; -} - -static uint8_t op_inc(struct MC6809 *cpu, uint8_t in) { - unsigned out = in + 1; - CLR_NZV; - SET_NZ8(out); - if (out == 0x80) REG_CC |= CC_V; - return out; -} - -static uint8_t op_tst(struct MC6809 *cpu, uint8_t in) { - CLR_NZV; - SET_NZ8(in); - return in; -} - -static uint8_t op_clr(struct MC6809 *cpu, uint8_t in) { - (void)in; - CLR_NVC; - REG_CC |= CC_Z; - return 0; -} - -/* 8-bit arithmetic operations */ - -static uint8_t op_sub(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a - b; - CLR_NZVC; - SET_NZVC8(a, b, out); - return out; -} - -static uint8_t op_sbc(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a - b - (REG_CC & CC_C); - CLR_NZVC; - SET_NZVC8(a, b, out); - return out; -} - -static uint8_t op_and(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a & b; - CLR_NZV; - SET_NZ8(out); - return out; -} - -static uint8_t op_ld(struct MC6809 *cpu, uint8_t a, uint8_t b) { - (void)a; - CLR_NZV; - SET_NZ8(b); - return b; -} - -static uint8_t op_eor(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a ^ b; - CLR_NZV; - SET_NZ8(out); - return out; -} - -static uint8_t op_adc(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a + b + (REG_CC & CC_C); - CLR_HNZVC; - SET_NZVC8(a, b, out); - SET_H(a, b, out); - return out; -} - -static uint8_t op_or(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a | b; - CLR_NZV; - SET_NZ8(out); - return out; -} - -static uint8_t op_add(struct MC6809 *cpu, uint8_t a, uint8_t b) { - unsigned out = a + b; - CLR_HNZVC; - SET_NZVC8(a, b, out); - SET_H(a, b, out); - return out; -} - -/* 16-bit arithmetic operations */ - -static uint16_t op_sub16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a - b; - CLR_NZVC; - SET_NZVC16(a, b, out); - return out; -} - -static uint16_t op_ld16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - (void)a; - CLR_NZV; - SET_NZ16(b); - return b; -} - -static uint16_t op_add16(struct MC6809 *cpu, uint16_t a, uint16_t b) { - unsigned out = a + b; - CLR_NZVC; - SET_NZVC16(a, b, out); - return out; -} - -/* Various utility functions */ - -/* Sign extend 5 bits into 16 bits */ -static uint16_t sex5(unsigned v) { - return (v & 0x0f) - (v & 0x10); -} - -/* Sign extend 8 bits into 16 bits */ -static uint16_t sex8(unsigned v) { - uint8_t tmp = v; - return (int16_t)(*((int8_t *)&tmp)); -} - -/* Determine branch condition from op-code */ -static _Bool branch_condition(struct MC6809 const *cpu, unsigned op) { - _Bool cond; - _Bool invert = op & 1; - switch ((op >> 1) & 7) { - default: - case 0x0: cond = 1; break; // BRA, !BRN - case 0x1: cond = !(REG_CC & (CC_Z|CC_C)); break; // BHI, !BLS - case 0x2: cond = !(REG_CC & CC_C); break; // BCC, BHS, !BCS, !BLO - case 0x3: cond = !(REG_CC & CC_Z); break; // BNE, !BEQ - case 0x4: cond = !(REG_CC & CC_V); break; // BVC, !BVS - case 0x5: cond = !(REG_CC & CC_N); break; // BPL, !BMI - case 0x6: cond = !((REG_CC ^ (REG_CC << 2)) & CC_N); break; // BGE, !BLT - case 0x7: cond = !(((REG_CC&(CC_N|CC_Z)) ^ ((REG_CC&CC_V) << 2))); break; // BGT, !BLE - } - return cond != invert; -} - diff --git a/src/mc6809/mc6809_common.h b/src/mc6809/mc6809_common.h deleted file mode 100644 index 58ed0823..00000000 --- a/src/mc6809/mc6809_common.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Memory interface */ - -static uint8_t fetch_byte(struct MC6809 *cpu, uint16_t a); -static void store_byte(struct MC6809 *cpu, uint16_t a, uint8_t d); -static uint16_t fetch_word(struct MC6809 *cpu, uint16_t a); -#define peek_byte(c,a) ((void)fetch_byte(c,a)) -#define NVMA_CYCLE (peek_byte(cpu, 0xffff)) - -/* Read & write various addressing modes */ - -static uint8_t byte_immediate(struct MC6809 *cpu); -static uint8_t byte_direct(struct MC6809 *cpu); -static uint8_t byte_extended(struct MC6809 *cpu); -static uint8_t byte_indexed(struct MC6809 *cpu); -static uint16_t word_immediate(struct MC6809 *cpu); -static uint16_t word_direct(struct MC6809 *cpu); -static uint16_t word_extended(struct MC6809 *cpu); -static uint16_t word_indexed(struct MC6809 *cpu); - -static uint16_t short_relative(struct MC6809 *cpu); -#define long_relative word_immediate - -/* Stack operations */ - -static void push_s_byte(struct MC6809 *cpu, uint8_t v); -static void push_s_word(struct MC6809 *cpu, uint16_t v); -static uint8_t pull_s_byte(struct MC6809 *cpu); -static uint16_t pull_s_word(struct MC6809 *cpu); - -static void push_u_byte(struct MC6809 *cpu, uint8_t v); -static void push_u_word(struct MC6809 *cpu, uint16_t v); -static uint8_t pull_u_byte(struct MC6809 *cpu); -static uint16_t pull_u_word(struct MC6809 *cpu); - -/* 8-bit inherent operations */ - -static uint8_t op_neg(struct MC6809 *cpu, uint8_t in); -static uint8_t op_com(struct MC6809 *cpu, uint8_t in); -static uint8_t op_lsr(struct MC6809 *cpu, uint8_t in); -static uint8_t op_ror(struct MC6809 *cpu, uint8_t in); -static uint8_t op_asr(struct MC6809 *cpu, uint8_t in); -static uint8_t op_asl(struct MC6809 *cpu, uint8_t in); -static uint8_t op_rol(struct MC6809 *cpu, uint8_t in); -static uint8_t op_dec(struct MC6809 *cpu, uint8_t in); -static uint8_t op_inc(struct MC6809 *cpu, uint8_t in); -static uint8_t op_tst(struct MC6809 *cpu, uint8_t in); -static uint8_t op_clr(struct MC6809 *cpu, uint8_t in); - -/* 8-bit arithmetic operations */ - -static uint8_t op_sub(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_sbc(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_and(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_ld(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_eor(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_adc(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_or(struct MC6809 *cpu, uint8_t a, uint8_t b); -static uint8_t op_add(struct MC6809 *cpu, uint8_t a, uint8_t b); - -/* 16-bit arithmetic operations */ - -static uint16_t op_sub16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_ld16(struct MC6809 *cpu, uint16_t a, uint16_t b); -static uint16_t op_add16(struct MC6809 *cpu, uint16_t a, uint16_t b); - -/* Various utility functions */ - -static uint16_t sex5(unsigned v); -static uint16_t sex8(unsigned v); -static _Bool branch_condition(struct MC6809 const *cpu, unsigned op); - diff --git a/src/mc6809/pl-endian.h b/src/mc6809/pl-endian.h deleted file mode 100644 index 978e2992..00000000 --- a/src/mc6809/pl-endian.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - -Missing endian.h -Copyright 2014-2015, Ciaran Anscomb - -This is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation; either version 2.1 of the License, or (at your -option) any later version. - -If endian.h was not found by configure, it should have performed a test -or made an assumption, and HAVE_BIG_ENDIAN will be defined accordingly. - -*/ - -#ifndef PL_ENDIAN_H__ubnPKXx9bODus -#define PL_ENDIAN_H__ubnPKXx9bODus - -#ifdef HAVE_ENDIAN_H -#include -#endif - -#ifndef __BIG_ENDIAN -#define __BIG_ENDIAN 4321 -#endif -#ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN 1234 -#endif - -#ifndef __BYTE_ORDER -#ifdef HAVE_BIG_ENDIAN -#define __BYTE_ORDER __BIG_ENDIAN -#else -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif -#endif - -#endif /* PL_ENDIAN_H__ubnPKXx9bODus */ diff --git a/src/mc6809/xalloc.h b/src/mc6809/xalloc.h deleted file mode 100644 index 3176721e..00000000 --- a/src/mc6809/xalloc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - -Memory allocation with checking -Copyright 2014-2015, Ciaran Anscomb - -This is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation; either version 2.1 of the License, or (at your -option) any later version. - -A small set of convenience functions that wrap standard system calls and -provide out of memory checking. See Gnulib for a far more complete set. - -*/ - -#ifndef XALLOC_H__yqbm4hifLvT2k -#define XALLOC_H__yqbm4hifLvT2k - -#include - -void *xmalloc(size_t s); -void *xzalloc(size_t s); -void *xrealloc(void *p, size_t s); - -void *xmemdup(const void *p, size_t s); -char *xstrdup(const char *str); - -#endif /* XALLOC_H__yqbm4hifLvT2k */ diff --git a/src/mc6809/xmalloc.c b/src/mc6809/xmalloc.c deleted file mode 100644 index eb433dd3..00000000 --- a/src/mc6809/xmalloc.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - -Memory allocation with checking -Copyright 2014-2015, Ciaran Anscomb - -This is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the -Free Software Foundation; either version 2.1 of the License, or (at your -option) any later version. - -*/ - -#include "config.h" - -#include -#include -#include - -#include "xalloc.h" - -void *xmalloc(size_t s) { - void *mem = malloc(s); - if (!mem) { - perror(NULL); - printf("xmalloc failed\r\n"); - //exit(EXIT_FAILURE); - } - return mem; -} - -void *xzalloc(size_t s) { - void *mem = xmalloc(s); - memset(mem, 0, s); - return mem; -} - -void *xrealloc(void *p, size_t s) { - void *mem = realloc(p, s); - if (!mem && s != 0) { - perror(NULL); - printf("xmalloc failed\r\n"); - // exit(EXIT_FAILURE); - } - return mem; -} - -void *xmemdup(const void *p, size_t s) { - if (!p) - return NULL; - void *mem = xmalloc(s); - memcpy(mem, p, s); - return mem; -} - -char *xstrdup(const char *str) { - return xmemdup(str, strlen(str) + 1); -} diff --git a/src/mc6809sc/mc6809.c b/src/mc6809sc/mc6809.c deleted file mode 100644 index b88e3e16..00000000 --- a/src/mc6809sc/mc6809.c +++ /dev/null @@ -1,3442 +0,0 @@ -/******************************************** -* -* Copyright 2012 by Sean Conner. All Rights Reserved. -* -* This library is free software; you can redistribute it and/or modify it -* under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 3 of the License, or (at your -* option) any later version. -* -* This library is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -* License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this library; if not, see . -* -* Comments, questions and criticisms can be sent to: sean@conman.org -* -*********************************************/ - -//#include -#include -//#include - -#define assert(...) - -//#define assert(test) {if (!(test)) printf("Assert failed at %s, line %d.", __FILE__, __LINE__);} - -#include "mc6809.h" - -/**************************************************************************/ - -static int page2 (mc6809__t *const) __attribute__((nonnull)); -static int page3 (mc6809__t *const) __attribute__((nonnull)); - -static mc6809byte__t op_neg (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_com (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_lsr (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_ror (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_asr (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_lsl (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_rol (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_dec (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_inc (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static void op_tst (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_clr (mc6809__t *const) __attribute__((nonnull)); - -static mc6809byte__t op_sub (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static void op_cmp (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_sbc (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_and (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static void op_bit (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static void op_ldst (mc6809__t *const,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_eor (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_adc (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_or (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); -static mc6809byte__t op_add (mc6809__t *const,const mc6809byte__t,const mc6809byte__t) __attribute__((nonnull)); - -static mc6809addr__t op_sub16 (mc6809__t *const,const mc6809addr__t,const mc6809addr__t) __attribute__((nonnull)); -static void op_cmp16 (mc6809__t *const,const mc6809addr__t,const mc6809addr__t) __attribute__((nonnull)); -static void op_ldst16 (mc6809__t *const,const mc6809addr__t) __attribute__((nonnull)); -static mc6809addr__t op_add16 (mc6809__t *const,const mc6809addr__t,const mc6809addr__t) __attribute__((nonnull)); - -/***************************************************************************/ - -static inline bool bhs(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return !cpu->cc.c; -} - -static inline bool blo(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.c; -} - -static inline bool bhi(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return !cpu->cc.c && !cpu->cc.z; -} - -static inline bool bls(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.c || cpu->cc.z; -} - -static inline bool bne(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return !cpu->cc.z; -} - -static inline bool beq(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.z; -} - -static inline bool bge(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.n == cpu->cc.v; -} - -static inline bool blt(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.n != cpu->cc.v; -} - -static inline bool bgt(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return (cpu->cc.n == cpu->cc.v) && !cpu->cc.z; -} - -static inline bool ble(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.z || (cpu->cc.n != cpu->cc.v); -} - -static inline bool bpl(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return !cpu->cc.n; -} - -static inline bool bmi(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.n; -} - -static inline bool bvc(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return !cpu->cc.v; -} - -static inline bool bvs(mc6809__t *const cpu) -{ - assert(cpu != NULL); - return cpu->cc.v; -} - -/**************************************************************************/ - -void mc6809_reset(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->cycles = 0; - cpu->nmi_armed = false; - cpu->nmi = false; - cpu->firq = false; - cpu->irq = false; - cpu->cwai = false; - cpu->sync = false; - cpu->page2 = false; - cpu->page3 = false; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_RESET,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_RESET + 1,false); - cpu->dp = 0; - cpu->cc.e = false; - cpu->cc.f = true; - cpu->cc.h = false; - cpu->cc.i = true; - cpu->cc.n = false; - cpu->cc.z = false; - cpu->cc.v = false; - cpu->cc.c = false; - cpu->instpc = cpu->pc.w; - cpu->ea.w = 0; -} - -/***************************************************************************/ - -int mc6809_run(mc6809__t *const cpu) -{ - int rc; - - assert(cpu != NULL); - - do - rc = mc6809_step(cpu); - while (rc == 0); - - return rc; -} - -/**************************************************************************/ - -int mc6809_step(mc6809__t *const cpu) -{ - mc6809word__t d16; - mc6809byte__t data; - bool e; - volatile int rc; - - assert(cpu != NULL); - - rc = setjmp(cpu->err); - if (rc != 0) return rc; - - if (cpu->nmi && cpu->nmi_armed) - { - cpu->nmi = false; - if (!cpu->cwai) - { - cpu->cycles += 19; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - } - cpu->cc.f = true; - cpu->cc.i = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_NMI,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_NMI + 1,false); - cpu->cwai = false; - return 0; - } - else if (cpu->firq && !cpu->cc.f) - { - cpu->firq = false; - if (!cpu->cwai) - { - cpu->cycles += 10; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = false; - } - cpu->cc.f = true; - cpu->cc.i = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_FIRQ,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_FIRQ + 1,false); - cpu->cwai = false; - return 0; - } - else if (cpu->irq && !cpu->cc.i) - { - cpu->irq = false; - if (!cpu->cwai) - { - cpu->cycles += 19; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - } - cpu->cc.i = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_IRQ,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_IRQ + 1,false); - cpu->cwai = false; - return 0; - } - - cpu->cycles++; - if (cpu->cwai) - return 0; - - cpu->sync = false; - cpu->instpc = cpu->pc.w; - cpu->inst = (*cpu->read)(cpu,cpu->pc.w++,true); - - /*------------------------------------------------------------------ - ; While the cycle counts may appear to be one less than stated in the - ; manual, the additional cycle has already been calculated above. - ;--------------------------------------------------------------------*/ - - switch(cpu->inst) - { - case 0x00: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_neg(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x01: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x02: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x03: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_com(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x04: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x05: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x06: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_ror(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x07: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_asr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x08: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsl(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x09: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_rol(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x0A: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_dec(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x0B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x0C: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_inc(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x0D: - cpu->cycles += 5; - mc6809_direct(cpu); - op_tst(cpu,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x0E: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->pc.w = cpu->ea.w; - break; - - case 0x0F: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->read) (cpu,cpu->ea.w,false); - (*cpu->write)(cpu,cpu->ea.w,op_clr(cpu)); - break; - - case 0x10: - return page2(cpu); - - case 0x11: - return page3(cpu); - - case 0x12: - cpu->cycles++; - break; - - case 0x13: - cpu->cycles++; - cpu->sync = true; - break; - - case 0x14: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x15: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x16: - cpu->cycles += 4; - mc6809_lrelative(cpu); - cpu->pc.w += cpu->ea.w; - break; - - case 0x17: - cpu->cycles += 8; - mc6809_lrelative(cpu); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - cpu->pc.w += cpu->ea.w; - break; - - case 0x18: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x19: /* DAA */ - cpu->cycles++; - { - mc6809byte__t msn = cpu->A >> 4; - mc6809byte__t lsn = cpu->A & 0x0F; - mc6809byte__t cf = 0; - bool h = cpu->cc.h; - bool c = cpu->cc.c; - - if (cpu->cc.c || (msn > 9) || ((msn > 8) && (lsn > 9))) - cf |= 0x60; - if (cpu->cc.h || (lsn > 9)) - cf |= 0x06; - - cpu->A = op_add(cpu,cpu->A,cf); - cpu->cc.h = h; - cpu->cc.c = cpu->cc.c | c; - cpu->cc.v = false; - } - break; - - case 0x1A: - cpu->cycles += 2; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - data |= mc6809_cctobyte(cpu); - mc6809_bytetocc(cpu,data); - break; - - case 0x1B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x1C: - cpu->cycles += 2; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - data &= mc6809_cctobyte(cpu); - mc6809_bytetocc(cpu,data); - break; - - case 0x1D: - cpu->cycles++; - cpu->A = (cpu->B > 0x7F) ? 0xFF: 0x00; - cpu->cc.n = (cpu->d.w > 0x7FFF); - cpu->cc.z = (cpu->d.w == 0x0000); - cpu->cc.v = false; - break; - - case 0x1E: - cpu->cycles += 7; - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - - if ((d16.b[LSB] & 0x88) == 0x00) - { - mc6809addr__t *src; - mc6809addr__t *dest; - mc6809addr__t tmp; - - switch(d16.b[LSB] & 0xF0) - { - case 0x00: src = &cpu->d.w; break; - case 0x10: src = &cpu->X.w; break; - case 0x20: src = &cpu->Y.w; break; - case 0x30: src = &cpu->U.w; break; - case 0x40: src = &cpu->S.w; break; - case 0x50: src = &cpu->pc.w; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_EXG); - return 0; - } - - switch(d16.b[LSB] & 0x0F) - { - case 0x00: dest = &cpu->d.w; break; - case 0x01: dest = &cpu->X.w; break; - case 0x02: dest = &cpu->Y.w; break; - case 0x03: dest = &cpu->U.w; break; - case 0x04: dest = &cpu->S.w; cpu->nmi_armed = true; break; - case 0x05: dest = &cpu->pc.w; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_EXG); - return 0; - } - - tmp = *src; - *src = *dest; - *dest = tmp; - } - else if ((d16.b[LSB] & 0x88) == 0x88) - { - mc6809byte__t *src; - mc6809byte__t *dest; - mc6809byte__t tmp; - mc6809byte__t ccs; - mc6809byte__t ccd; - - switch(d16.b[LSB] & 0xF0) - { - case 0x80: src = &cpu->A; break; - case 0x90: src = &cpu->B; break; - case 0xA0: src = &ccs; ccs = mc6809_cctobyte(cpu); break; - case 0xB0: src = &cpu->dp; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_EXG); - return 0; - } - - switch(d16.b[LSB] & 0x0F) - { - case 0x08: dest = &cpu->A; break; - case 0x09: dest = &cpu->B; break; - case 0x0A: dest = &ccd; ccd = mc6809_cctobyte(cpu); break; - case 0x0B: dest = &cpu->dp; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_EXG); - return 0; - } - - tmp = *src; - *src = *dest; - *dest = tmp; - - if (src == &ccs) mc6809_bytetocc(cpu,ccs); - if (dest == &ccd) mc6809_bytetocc(cpu,ccd); - } - else - (*cpu->fault)(cpu,MC6809_FAULT_EXG); - break; - - case 0x1F: - cpu->cycles += 6; - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - - if ((d16.b[LSB] & 0x88) == 0x00) - { - switch(d16.b[LSB] & 0xF0) - { - case 0x00: cpu->ea.w = cpu->d.w; break; - case 0x10: cpu->ea.w = cpu->X.w; break; - case 0x20: cpu->ea.w = cpu->Y.w; break; - case 0x30: cpu->ea.w = cpu->U.w; break; - case 0x40: cpu->ea.w = cpu->S.w; cpu->nmi_armed = true; break; - case 0x50: cpu->ea.w = cpu->pc.w; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_TFR); - return 0; - } - - switch(d16.b[LSB] & 0x0F) - { - case 0x00: cpu->d.w = cpu->ea.w; break; - case 0x01: cpu->X.w = cpu->ea.w; break; - case 0x02: cpu->Y.w = cpu->ea.w; break; - case 0x03: cpu->U.w = cpu->ea.w; break; - case 0x04: cpu->S.w = cpu->ea.w; cpu->nmi_armed = true; break; - case 0x05: cpu->pc.w = cpu->ea.w; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_TFR); - return 0; - } - } - else if ((d16.b[LSB] & 0x88) == 0x88) - { - switch(d16.b[LSB] & 0xF0) - { - case 0x80: data = cpu->A; break; - case 0x90: data = cpu->B; break; - case 0xA0: data = mc6809_cctobyte(cpu); break; - case 0xB0: data = cpu->dp; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_TFR); - return 0; - } - - switch(d16.b[LSB] & 0x0F) - { - case 0x08: cpu->A = data; break; - case 0x09: cpu->B = data; break; - case 0x0A: mc6809_bytetocc(cpu,data); break; - case 0x0B: cpu->dp = data; break; - default: - (*cpu->fault)(cpu,MC6809_FAULT_TFR); - return 0; - } - } - else - (*cpu->fault)(cpu,MC6809_FAULT_TFR); - break; - - case 0x20: - cpu->cycles += 2; - mc6809_relative(cpu); - cpu->pc.w += cpu->ea.w; - break; - - case 0x21: - cpu->cycles += 2; - mc6809_relative(cpu); - break; - - case 0x22: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bhi(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x23: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bls(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x24: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bhs(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x25: - cpu->cycles += 2; - mc6809_relative(cpu); - if (blo(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x26: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bne(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x27: - cpu->cycles += 2; - mc6809_relative(cpu); - if (beq(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x28: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bvc(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x29: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bvs(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2A: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bpl(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2B: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bmi(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2C: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bge(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2D: - cpu->cycles += 2; - mc6809_relative(cpu); - if (blt(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2E: - cpu->cycles += 2; - mc6809_relative(cpu); - if (bgt(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x2F: - cpu->cycles += 2; - mc6809_relative(cpu); - if (ble(cpu)) - cpu->pc.w += cpu->ea.w; - break; - - case 0x30: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->X.w = cpu->ea.w; - cpu->cc.z = (cpu->X.w == 0x0000); - break; - - case 0x31: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->Y.w = cpu->ea.w; - cpu->cc.z = (cpu->Y.w == 0x0000); - break; - - case 0x32: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->S.w = cpu->ea.w; - cpu->nmi_armed = true; - break; - - case 0x33: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->U.w = cpu->ea.w; - break; - - case 0x34: - cpu->cycles += 4; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - if (data & 0x80) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - } - if (data & 0x40) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - } - if (data & 0x20) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - } - if (data & 0x10) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - } - if (data & 0x08) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - } - if (data & 0x04) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - } - if (data & 0x02) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - } - if (data & 0x01) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - } - break; - - case 0x35: - cpu->cycles += 4; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - if (data & 0x01) - { - cpu->cycles++; - mc6809_bytetocc(cpu,(*cpu->read)(cpu,cpu->S.w++,false)); - } - if (data & 0x02) - { - cpu->cycles++; - cpu->A = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x04) - { - cpu->cycles++; - cpu->B = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x08) - { - cpu->cycles++; - cpu->dp = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x10) - { - cpu->cycles += 2; - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x20) - { - cpu->cycles += 2; - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x40) - { - cpu->cycles += 2; - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - } - if (data & 0x80) - { - cpu->cycles += 2; - cpu->pc.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - } - break; - - case 0x36: - cpu->cycles += 4; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - if (data & 0x80) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->U.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->U.w,cpu->pc.b[MSB]); - } - if (data & 0x40) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->U.w,cpu->S.b[LSB]); - (*cpu->write)(cpu,--cpu->U.w,cpu->S.b[MSB]); - } - if (data & 0x20) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->U.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->U.w,cpu->Y.b[MSB]); - } - if (data & 0x10) - { - cpu->cycles += 2; - (*cpu->write)(cpu,--cpu->U.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->U.w,cpu->X.b[MSB]); - } - if (data & 0x08) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->U.w,cpu->dp); - } - if (data & 0x04) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->U.w,cpu->B); - } - if (data & 0x02) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->U.w,cpu->A); - } - if (data & 0x01) - { - cpu->cycles++; - (*cpu->write)(cpu,--cpu->U.w,mc6809_cctobyte(cpu)); - } - break; - - case 0x37: - cpu->cycles += 4; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - if (data & 0x01) - { - cpu->cycles++; - mc6809_bytetocc(cpu,(*cpu->read)(cpu,cpu->U.w++,false)); - } - if (data & 0x02) - { - cpu->cycles++; - cpu->A = (*cpu->read)(cpu,cpu->U.w++,false); - } - if (data & 0x04) - { - cpu->cycles++; - cpu->B = (*cpu->read)(cpu,cpu->U.w++,false); - } - if (data & 0x08) - { - cpu->cycles++; - cpu->dp = (*cpu->read)(cpu,cpu->U.w++,false); - } - if (data & 0x10) - { - cpu->cycles += 2; - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->U.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->U.w++,false); - } - if (data & 0x20) - { - cpu->cycles += 2; - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->U.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->U.w++,false); - } - if (data & 0x40) - { - cpu->cycles += 2; - cpu->S.b[MSB] = (*cpu->read)(cpu,cpu->U.w++,false); - cpu->S.b[LSB] = (*cpu->read)(cpu,cpu->U.w++,false); - cpu->nmi_armed = true; - } - if (data & 0x80) - { - cpu->cycles += 2; - cpu->pc.b[MSB] = (*cpu->read)(cpu,cpu->U.w++,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,cpu->U.w++,false); - } - break; - - case 0x38: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x39: - cpu->cycles += 4; - cpu->pc.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - break; - - case 0x3A: - cpu->cycles += 2; - d16.b[LSB] = cpu->B; - d16.b[MSB] = 0; - cpu->X.w += d16.w; - break; - - case 0x3B: - cpu->cycles += 5; - e = cpu->cc.e; - mc6809_bytetocc(cpu,(*cpu->read)(cpu,cpu->S.w++,false)); - if (e) - { - cpu->cycles += 9; - cpu->A = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->B = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->dp = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - } - cpu->pc.b[MSB] = (*cpu->read)(cpu,cpu->S.w++,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,cpu->S.w++,false); - break; - - case 0x3C: - cpu->cycles += 20; - data = (*cpu->read)(cpu,cpu->pc.w++,true); - mc6809_bytetocc(cpu,mc6809_cctobyte(cpu) & data); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - cpu->cwai = true; - break; - - case 0x3D: - cpu->cycles += 10; - cpu->cc.c = (cpu->B & 0x80) == 0x80; - cpu->d.w = (mc6809addr__t)cpu->A * (mc6809addr__t)cpu->B; - cpu->cc.z = (cpu->d.w == 0x0000); - break; - - case 0x3E: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x3F: - cpu->cycles += 18; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - cpu->cc.f = true; - cpu->cc.i = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI + 1,false); - break; - - case 0x40: - cpu->cycles++; - cpu->A = op_neg(cpu,cpu->A); - break; - - case 0x41: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x42: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x43: - cpu->cycles++; - cpu->A = op_com(cpu,cpu->A); - break; - - case 0x44: - cpu->cycles++; - cpu->A = op_lsr(cpu,cpu->A); - break; - - case 0x45: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x46: - cpu->cycles++; - cpu->A = op_ror(cpu,cpu->A); - break; - - case 0x47: - cpu->cycles++; - cpu->A = op_asr(cpu,cpu->A); - break; - - case 0x48: - cpu->cycles++; - cpu->A = op_lsl(cpu,cpu->A); - break; - - case 0x49: - cpu->cycles++; - cpu->A = op_rol(cpu,cpu->A); - break; - - case 0x4A: - cpu->cycles++; - cpu->A = op_dec(cpu,cpu->A); - break; - - case 0x4B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x4C: - cpu->cycles++; - cpu->A = op_inc(cpu,cpu->A); - break; - - case 0x4D: - cpu->cycles++; - op_tst(cpu,cpu->A); - break; - - case 0x4E: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x4F: - cpu->cycles++; - cpu->A = op_clr(cpu); - break; - - case 0x50: - cpu->cycles++; - cpu->B = op_neg(cpu,cpu->B); - break; - - case 0x51: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x52: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x53: - cpu->cycles++; - cpu->B = op_com(cpu,cpu->B); - break; - - case 0x54: - cpu->cycles++; - cpu->B = op_lsr(cpu,cpu->B); - break; - - case 0x55: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x56: - cpu->cycles++; - cpu->B = op_ror(cpu,cpu->B); - break; - - case 0x57: - cpu->cycles++; - cpu->B = op_asr(cpu,cpu->B); - break; - - case 0x58: - cpu->cycles++; - cpu->B = op_lsl(cpu,cpu->B); - break; - - case 0x59: - cpu->cycles++; - cpu->B = op_rol(cpu,cpu->B); - break; - - case 0x5A: - cpu->cycles++; - cpu->B = op_dec(cpu,cpu->B); - break; - - case 0x5B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x5C: - cpu->cycles++; - cpu->B = op_inc(cpu,cpu->B); - break; - - case 0x5D: - cpu->cycles++; - op_tst(cpu,cpu->B); - break; - - case 0x5E: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x5F: - cpu->cycles++; - cpu->B = op_clr(cpu); - break; - - case 0x60: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_neg(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x61: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x62: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x63: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_com(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x64: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x65: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x66: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_ror(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x67: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_asr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x68: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsl(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x69: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_rol(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x6A: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_dec(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x6B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x6C: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_inc(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x6D: - cpu->cycles += 5; - mc6809_indexed(cpu); - op_tst(cpu,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x6E: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->pc.w = cpu->ea.w; - break; - - case 0x6F: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->read) (cpu,cpu->ea.w,false); - (*cpu->write)(cpu,cpu->ea.w,op_clr(cpu)); - break; - - case 0x70: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_neg(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x71: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x72: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x73: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_com(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x74: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x75: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x76: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_ror(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x77: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_asr(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x78: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_lsl(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x79: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_rol(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x7A: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_dec(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x7B: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x7C: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,op_inc(cpu,(*cpu->read)(cpu,cpu->ea.w,false))); - break; - - case 0x7D: - cpu->cycles += 6; - mc6809_extended(cpu); - op_tst(cpu,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x7E: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->pc.w = cpu->ea.w; - break; - - case 0x7F: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->read) (cpu,cpu->ea.w,false); - (*cpu->write)(cpu,cpu->ea.w,op_clr(cpu)); - break; - - case 0x80: - cpu->cycles++; - cpu->A = op_sub(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x81: - cpu->cycles++; - op_cmp(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x82: - cpu->cycles++; - cpu->A = op_sbc(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x83: - cpu->cycles += 3; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->d.w = op_sub16(cpu,cpu->d.w,d16.w); - break; - - case 0x84: - cpu->cycles++; - cpu->A = op_and(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x85: - cpu->cycles++; - op_bit(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x86: - cpu->cycles++; - cpu->A = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst(cpu,cpu->A); - break; - - case 0x87: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x88: - cpu->cycles++; - cpu->A = op_eor(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x89: - cpu->cycles++; - cpu->A = op_adc(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x8A: - cpu->cycles++; - cpu->A = op_or(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x8B: - cpu->cycles++; - cpu->A = op_add(cpu,cpu->A,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0x8C: - cpu->cycles += 3; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_cmp16(cpu,cpu->X.w,d16.w); - break; - - case 0x8D: - cpu->cycles += 6; - mc6809_relative(cpu); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - cpu->pc.w += cpu->ea.w; - break; - - case 0x8E: - cpu->cycles += 2; - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst16(cpu,cpu->X.w); - break; - - case 0x8F: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0x90: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_sub(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x91: - cpu->cycles += 3; - mc6809_direct(cpu); - op_cmp(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x92: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_sbc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x93: - cpu->cycles += 5; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_sub16(cpu,cpu->d.w,d16.w); - break; - - case 0x94: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_and(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x95: - cpu->cycles += 3; - mc6809_direct(cpu); - op_bit(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x96: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->A); - break; - - case 0x97: - cpu->cycles += 3; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->A); - op_ldst(cpu,cpu->A); - break; - - case 0x98: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_eor(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x99: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_adc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x9A: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_or(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x9B: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->A = op_add(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0x9C: - cpu->cycles += 5; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->X.w,d16.w); - break; - - case 0x9D: - cpu->cycles += 6; - mc6809_direct(cpu); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - cpu->pc.w = cpu->ea.w; - break; - - case 0x9E: - cpu->cycles += 4; - mc6809_direct(cpu); - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->X.w); - break; - - case 0x9F: - cpu->cycles += 4; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->X.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->X.b[LSB]); - op_ldst16(cpu,cpu->X.w); - break; - - case 0xA0: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_sub(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA1: - cpu->cycles += 3; - mc6809_indexed(cpu); - op_cmp(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA2: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_sbc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA3: - cpu->cycles += 5; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_sub16(cpu,cpu->d.w,d16.w); - break; - - case 0xA4: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_and(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA5: - cpu->cycles += 3; - mc6809_indexed(cpu); - op_bit(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA6: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->A); - break; - - case 0xA7: - cpu->cycles += 3; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->A); - op_ldst(cpu,cpu->A); - break; - - case 0xA8: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_eor(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xA9: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_adc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xAA: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_or(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xAB: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->A = op_add(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xAC: - cpu->cycles += 5; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->X.w,d16.w); - break; - - case 0xAD: - cpu->cycles += 6; - mc6809_indexed(cpu); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - cpu->pc.w = cpu->ea.w; - break; - - case 0xAE: - cpu->cycles += 4; - mc6809_indexed(cpu); - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->X.w); - break; - - case 0xAF: - cpu->cycles += 4; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->X.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->X.b[LSB]); - op_ldst16(cpu,cpu->X.w); - break; - - case 0xB0: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_sub(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB1: - cpu->cycles += 4; - mc6809_extended(cpu); - op_cmp(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB2: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_sbc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB3: - cpu->cycles += 6; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_sub16(cpu,cpu->d.w,d16.w); - break; - - case 0xB4: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_and(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB5: - cpu->cycles += 4; - mc6809_extended(cpu); - op_bit(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB6: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->A); - break; - - case 0xB7: - cpu->cycles += 4; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->A); - op_ldst(cpu,cpu->A); - break; - - case 0xB8: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_eor(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xB9: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_adc(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xBA: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_or(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xBB: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->A = op_add(cpu,cpu->A,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xBC: - cpu->cycles += 6; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->X.w,d16.w); - break; - - case 0xBD: - cpu->cycles += 7; - mc6809_extended(cpu); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - cpu->pc.w = cpu->ea.w; - break; - - case 0xBE: - cpu->cycles += 5; - mc6809_extended(cpu); - cpu->X.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->X.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->X.w); - break; - - case 0xBF: - cpu->cycles += 5; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->X.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->X.b[LSB]); - op_ldst16(cpu,cpu->X.w); - break; - - case 0xC0: - cpu->cycles++; - cpu->B = op_sub(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC1: - cpu->cycles++; - op_cmp(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC2: - cpu->cycles++; - cpu->B = op_sbc(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC3: - cpu->cycles += 3; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->d.w = op_add16(cpu,cpu->d.w,d16.w); - break; - - case 0xC4: - cpu->cycles++; - cpu->B = op_and(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC5: - cpu->cycles++; - op_bit(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC6: - cpu->cycles++; - cpu->B = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst(cpu,cpu->B); - break; - - case 0xC7: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0xC8: - cpu->cycles++; - cpu->B = op_eor(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xC9: - cpu->cycles++; - cpu->B = op_adc(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xCA: - cpu->cycles++; - cpu->B = op_or(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xCB: - cpu->cycles++; - cpu->B = op_add(cpu,cpu->B,(*cpu->read)(cpu,cpu->pc.w++,true)); - break; - - case 0xCC: - cpu->cycles += 2; - cpu->A = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->B = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xCD: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0xCE: - cpu->cycles += 2; - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst16(cpu,cpu->U.w); - break; - - case 0xCF: - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - - case 0xD0: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_sub(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD1: - cpu->cycles += 3; - mc6809_direct(cpu); - op_cmp(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD2: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_sbc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD3: - cpu->cycles += 5; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_add16(cpu,cpu->d.w,d16.w); - break; - - case 0xD4: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_and(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD5: - cpu->cycles += 3; - mc6809_direct(cpu); - op_bit(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD6: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->B); - break; - - case 0xD7: - cpu->cycles += 3; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst(cpu,cpu->B); - break; - - case 0xD8: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_eor(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xD9: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_adc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xDA: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_or(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xDB: - cpu->cycles += 3; - mc6809_direct(cpu); - cpu->B = op_add(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xDC: - cpu->cycles += 4; - mc6809_direct(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xDD: - cpu->cycles += 6; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->A); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xDE: - cpu->cycles += 4; - mc6809_direct(cpu); - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xDF: - cpu->cycles += 4; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->U.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->U.b[LSB]); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xE0: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_sub(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE1: - cpu->cycles += 3; - mc6809_indexed(cpu); - op_cmp(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE2: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_sbc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE3: - cpu->cycles += 5; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_add16(cpu,cpu->d.w,d16.w); - break; - - case 0xE4: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_and(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE5: - cpu->cycles += 3; - mc6809_indexed(cpu); - op_bit(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE6: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->B); - break; - - case 0xE7: - cpu->cycles += 3; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst(cpu,cpu->B); - break; - - case 0xE8: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_eor(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xE9: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_adc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xEA: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_or(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xEB: - cpu->cycles += 3; - mc6809_indexed(cpu); - cpu->B = op_add(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xEC: - cpu->cycles += 4; - mc6809_indexed(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xED: - cpu->cycles += 6; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->A); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xEE: - cpu->cycles += 4; - mc6809_indexed(cpu); - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->U.w); - break; - - case 0xEF: - cpu->cycles += 4; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->U.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->U.b[LSB]); - op_ldst16(cpu,cpu->U.w); - break; - - case 0xF0: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_sub(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF1: - cpu->cycles += 4; - mc6809_extended(cpu); - op_cmp(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF2: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_sbc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF3: - cpu->cycles += 6; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->d.w = op_add16(cpu,cpu->d.w,d16.w); - break; - - case 0xF4: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_and(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF5: - cpu->cycles += 4; - mc6809_extended(cpu); - op_bit(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF6: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst(cpu,cpu->B); - break; - - case 0xF7: - cpu->cycles += 4; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst(cpu,cpu->B); - break; - - case 0xF8: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_eor(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xF9: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_adc(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xFA: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_or(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xFB: - cpu->cycles += 4; - mc6809_extended(cpu); - cpu->B = op_add(cpu,cpu->B,(*cpu->read)(cpu,cpu->ea.w,false)); - break; - - case 0xFC: - cpu->cycles += 5; - mc6809_extended(cpu); - cpu->A = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->B = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xFD: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->A); - (*cpu->write)(cpu,cpu->ea.w,cpu->B); - op_ldst16(cpu,cpu->d.w); - break; - - case 0xFE: - cpu->cycles += 5; - mc6809_extended(cpu); - cpu->U.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->U.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->U.w); - break; - - case 0xFF: - cpu->cycles += 5; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->U.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->U.b[LSB]); - op_ldst16(cpu,cpu->U.w); - break; - - default: - assert(0); - (*cpu->fault)(cpu,MC6809_FAULT_INTERNAL_ERROR); - break; - } - - return 0; -} - -/************************************************************************/ - -static int page2(mc6809__t *const cpu) -{ - mc6809word__t d16; - - assert(cpu != NULL); - - cpu->page2 = true; - cpu->inst = (*cpu->read)(cpu,cpu->pc.w++,true); - - /*----------------------------------------------------------------------- - ; While the cycle counts may appear to be one less than stated in the - ; manual, the addtional cycle has already been calculated via the - ; mc6809_step() function (the same applies for the page3() routine). - ;-----------------------------------------------------------------------*/ - - switch(cpu->inst) - { - case 0x21: - cpu->cycles += 4; - mc6809_lrelative(cpu); - break; - - case 0x22: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bhi(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x23: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bls(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x24: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bhs(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x25: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (blo(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x26: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bne(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x27: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (beq(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x28: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bvc(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x29: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bvs(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2A: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bpl(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2B: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bmi(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2C: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bge(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2D: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (blt(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2E: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bgt(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x2F: - cpu->cycles += 4; - mc6809_lrelative(cpu); - if (bhi(cpu)) - { - cpu->cycles++; - cpu->pc.w += cpu->ea.w; - } - break; - - case 0x3F: - cpu->cycles += 19; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI2,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI2 + 1,false); - break; - - case 0x83: - cpu->cycles += 4; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_cmp16(cpu,cpu->d.w,d16.w); - break; - - case 0x8C: - cpu->cycles += 4; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_cmp16(cpu,cpu->Y.w,d16.w); - break; - - case 0x8E: - cpu->cycles += 3; - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0x93: - cpu->cycles += 6; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->d.w,d16.w); - break; - - case 0x9C: - cpu->cycles += 6; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->Y.w,d16.w); - break; - - case 0x9E: - cpu->cycles += 5; - mc6809_direct(cpu); - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0x9F: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->Y.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->Y.b[LSB]); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0xA3: - cpu->cycles += 6; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->d.w,d16.w); - break; - - case 0xAC: - cpu->cycles += 6; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->Y.w,d16.w); - break; - - case 0xAE: - cpu->cycles += 5; - mc6809_indexed(cpu); - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0xAF: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->Y.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->Y.b[LSB]); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0xB3: - cpu->cycles += 6; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->d.w,d16.w); - break; - - case 0xBC: - cpu->cycles += 6; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->Y.w,d16.w); - break; - - case 0xBE: - cpu->cycles += 5; - mc6809_extended(cpu); - cpu->Y.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->Y.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0xBF: - cpu->cycles += 5; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->Y.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->Y.b[LSB]); - op_ldst16(cpu,cpu->Y.w); - break; - - case 0xCE: - cpu->cycles += 3; - cpu->S.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->S.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_ldst16(cpu,cpu->S.w); - cpu->nmi_armed = true; - break; - - case 0xDE: - cpu->cycles += 5; - mc6809_direct(cpu); - cpu->S.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->S.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->S.w); - cpu->nmi_armed = true; - break; - - case 0xDF: - cpu->cycles += 5; - mc6809_direct(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->S.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->S.b[LSB]); - op_ldst16(cpu,cpu->S.w); - break; - - case 0xEE: - cpu->cycles += 5; - mc6809_indexed(cpu); - cpu->S.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->S.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->S.w); - cpu->nmi_armed = true; - break; - - case 0xEF: - cpu->cycles += 5; - mc6809_indexed(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->S.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->S.b[LSB]); - op_ldst16(cpu,cpu->S.w); - break; - - case 0xFE: - cpu->cycles += 6; - mc6809_extended(cpu); - cpu->S.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - cpu->S.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_ldst16(cpu,cpu->S.w); - cpu->nmi_armed = true; - break; - - case 0xFF: - cpu->cycles += 6; - mc6809_extended(cpu); - (*cpu->write)(cpu,cpu->ea.w++,cpu->S.b[MSB]); - (*cpu->write)(cpu,cpu->ea.w,cpu->S.b[LSB]); - op_ldst16(cpu,cpu->S.w); - break; - - default: - cpu->cycles++; - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - } - - cpu->page2 = false; - return 0; -} - -/************************************************************************/ - -static int page3(mc6809__t *const cpu) -{ - mc6809word__t d16; - - assert(cpu != NULL); - - cpu->page3 = true; - cpu->inst = (*cpu->read)(cpu,cpu->pc.w++,true); - - /*----------------------------------------------------------------- - ; see the comment in mc6809_step() for an explanation on cycle counts - ;------------------------------------------------------------------*/ - - switch(cpu->inst) - { - case 0x3F: - cpu->cycles += 19; - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->pc.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->U.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->Y.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[LSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->X.b[MSB]); - (*cpu->write)(cpu,--cpu->S.w,cpu->dp); - (*cpu->write)(cpu,--cpu->S.w,cpu->B); - (*cpu->write)(cpu,--cpu->S.w,cpu->A); - (*cpu->write)(cpu,--cpu->S.w,mc6809_cctobyte(cpu)); - cpu->cc.e = true; - cpu->pc.b[MSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI3,false); - cpu->pc.b[LSB] = (*cpu->read)(cpu,MC6809_VECTOR_SWI3 + 1,false); - break; - - case 0x83: - cpu->cycles += 4; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_cmp16(cpu,cpu->U.w,d16.w); - break; - - case 0x8C: - cpu->cycles += 4; - d16.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - op_cmp16(cpu,cpu->S.w,d16.w); - break; - - case 0x93: - cpu->cycles += 6; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->U.w,d16.w); - break; - - case 0x9C: - cpu->cycles += 6; - mc6809_direct(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->S.w,d16.w); - break; - - case 0xA3: - cpu->cycles += 6; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->U.w,d16.w); - break; - - case 0xAC: - cpu->cycles += 6; - mc6809_indexed(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->S.w,d16.w); - break; - - case 0xB3: - cpu->cycles += 7; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->U.w,d16.w); - break; - - case 0xBC: - cpu->cycles += 7; - mc6809_extended(cpu); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - op_cmp16(cpu,cpu->S.w,d16.w); - break; - - default: - cpu->cycles++; - (*cpu->fault)(cpu,MC6809_FAULT_INSTRUCTION); - break; - } - - cpu->page3 = false; - return 0; -} - -/***********************************************************************/ - -void mc6809_direct(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->ea.b[MSB] = cpu->dp; - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); -} - -/***********************************************************************/ - -void mc6809_relative(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[MSB] = (cpu->ea.b[LSB] > 0x7F) ? 0xFF : 0x00; -} - -/***********************************************************************/ - -void mc6809_lrelative(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); -} - -/*********************************************************************/ - -void mc6809_extended(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); -} - -/***********************************************************************/ - -void mc6809_indexed(mc6809__t *const cpu) -{ - mc6809word__t d16; - mc6809byte__t mode; - int reg; - int off; - - assert(cpu != NULL); - - mode = (*cpu->read)(cpu,cpu->pc.w++,true); - reg = (mode & 0x60) >> 5; - off = (mode & 0x1F); - - if (mode < 0x80) - { - cpu->cycles++; - cpu->ea.w = (mc6809addr__t)off; - if (cpu->ea.w > 15) cpu->ea.w |= 0xFFE0; - cpu->ea.w += cpu->index[reg].w; - return; - } - - switch(off) - { - case 0x00: - cpu->cycles += 2; - cpu->ea.w = cpu->index[reg].w++; - break; - - case 0x01: - cpu->cycles += 3; - cpu->ea.w = cpu->index[reg].w; - cpu->index[reg].w += 2; - break; - - case 0x02: - cpu->cycles += 2; - cpu->ea.w = --cpu->index[reg].w; - break; - - case 0x03: - cpu->cycles += 3; - cpu->index[reg].w -= 2; - cpu->ea.w = cpu->index[reg].w; - break; - - case 0x04: - cpu->ea.w = cpu->index[reg].w; - break; - - case 0x05: - cpu->cycles++; - cpu->ea.b[LSB] = cpu->B; - cpu->ea.b[MSB] = (cpu->B < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->index[reg].w; - break; - - case 0x06: - cpu->cycles++; - cpu->ea.b[LSB] = cpu->A; - cpu->ea.b[MSB] = (cpu->A < 0x80) ? 0x00: 0xFF; - cpu->ea.w += cpu->index[reg].w; - break; - - case 0x07: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x08: - cpu->cycles++; - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[MSB] = (cpu->ea.b[LSB] < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->index[reg].w; - break; - - case 0x09: - cpu->cycles += 4; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.w += cpu->index[reg].w; - break; - - case 0x0A: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x0B: - cpu->cycles += 4; - cpu->ea.w = cpu->index[reg].w + cpu->d.w; - break; - - case 0x0C: - cpu->cycles++; - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[MSB] = (cpu->ea.b[LSB] < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->pc.w; - break; - - case 0x0D: - cpu->cycles += 5; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.w += cpu->pc.w; - break; - - case 0x0E: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x0F: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x10: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x11: - cpu->cycles += 6; - cpu->ea.w = cpu->index[reg].w; - cpu->index[reg].w += 2; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x12: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x13: - cpu->cycles += 6; - cpu->index[reg].w -= 2; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->index[reg].w,false); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->index[reg].w + 1,false); - break; - - case 0x14: - cpu->cycles += 3; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->index[reg].w,false); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->index[reg].w + 1,false); - break; - - case 0x15: - cpu->cycles += 4; - cpu->ea.b[LSB] = cpu->B; - cpu->ea.b[MSB] = (cpu->B < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->index[reg].w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x16: - cpu->cycles += 4; - cpu->ea.b[LSB] = cpu->A; - cpu->ea.b[MSB] = (cpu->A < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->index[reg].w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x17: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x18: - cpu->cycles += 4; - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[MSB] = (cpu->ea.b[LSB] < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->index[reg].w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x19: - cpu->cycles += 7; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.w += cpu->index[reg].w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x1A: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x1B: - cpu->cycles += 7; - cpu->ea.w = cpu->d.w; - cpu->ea.w += cpu->index[reg].w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x1C: - cpu->cycles += 4; - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[MSB] = (cpu->ea.b[LSB] < 0x80) ? 0x00 : 0xFF; - cpu->ea.w += cpu->pc.w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x1D: - cpu->cycles += 8; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.w += cpu->pc.w; - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - break; - - case 0x1E: - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - case 0x1F: - if (reg == 0) - { - cpu->cycles += 5; - cpu->ea.b[MSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - cpu->ea.b[LSB] = (*cpu->read)(cpu,cpu->pc.w++,true); - d16.b[MSB] = (*cpu->read)(cpu,cpu->ea.w++,false); - d16.b[LSB] = (*cpu->read)(cpu,cpu->ea.w,false); - cpu->ea.w = d16.w; - } - else - (*cpu->fault)(cpu,MC6809_FAULT_ADDRESS_MODE); - break; - - default: - assert(0); - (*cpu->fault)(cpu,MC6809_FAULT_INTERNAL_ERROR); - break; - } -} - -/*************************************************************************/ - -mc6809byte__t mc6809_cctobyte(mc6809__t *const cpu) -{ - mc6809byte__t r = 0; - - assert(cpu != NULL); - - if (cpu->cc.c) r |= 0x01; - if (cpu->cc.v) r |= 0x02; - if (cpu->cc.z) r |= 0x04; - if (cpu->cc.n) r |= 0x08; - if (cpu->cc.i) r |= 0x10; - if (cpu->cc.h) r |= 0x20; - if (cpu->cc.f) r |= 0x40; - if (cpu->cc.e) r |= 0x80; - - return r; -} - -/************************************************************************/ - -void mc6809_bytetocc(mc6809__t *const cpu,mc6809byte__t r) -{ - assert(cpu != NULL); - - cpu->cc.c = ((r & 0x01) != 0); - cpu->cc.v = ((r & 0x02) != 0); - cpu->cc.z = ((r & 0x04) != 0); - cpu->cc.n = ((r & 0x08) != 0); - cpu->cc.i = ((r & 0x10) != 0); - cpu->cc.h = ((r & 0x20) != 0); - cpu->cc.f = ((r & 0x40) != 0); - cpu->cc.e = ((r & 0x80) != 0); -} - -/*************************************************************************/ - -static mc6809byte__t op_neg(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = -src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = (src == 0x80); - cpu->cc.c = (src != 0x00); // Fix by DMB, was (src > 0x7F) - return res; -} - -/*************************************************************************/ - -static mc6809byte__t op_com(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = ~src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = false; - cpu->cc.c = true; - return res; -} - -/*************************************************************************/ - -static mc6809byte__t op_lsr(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src >> 1; - cpu->cc.n = false; - cpu->cc.z = (res == 0x00); - cpu->cc.c = (src & 0x01) == 0x01; - return res; -} - -/*************************************************************************/ - -static mc6809byte__t op_ror(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src >> 1; - res |= cpu->cc.c ? 0x80 : 0x00; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = (src & 0x01) == 0x01; - return res; -} - -/*************************************************************************/ - -static mc6809byte__t op_asr(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src >> 1; - res |= (src > 0x7F) ? 0x80 : 0x00; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = (src & 0x01) == 0x01; - return res; -} - -/*************************************************************************/ - -static mc6809byte__t op_lsl(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src << 1; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = ((src ^ res) & 0x80) == 0x80; - cpu->cc.c = (src > 0x7F); - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_rol(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src << 1; - res |= cpu->cc.c ? 0x01 : 0x00; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = ((src ^ res) & 0x80) == 0x80; - cpu->cc.c = (src > 0x7F); - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_dec(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src - 1; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = (src == 0x80); - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_inc(mc6809__t *const cpu,const mc6809byte__t src) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = src + 1; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = (src == 0x7F); - return res; -} - -/************************************************************************/ - -static void op_tst(mc6809__t *const cpu,const mc6809byte__t src) -{ - assert(cpu != NULL); - - cpu->cc.n = (src > 0x7F); - cpu->cc.z = (src == 0x00); - cpu->cc.v = false; -} - -/************************************************************************/ - -static mc6809byte__t op_clr(mc6809__t *const cpu) -{ - assert(cpu != NULL); - - cpu->cc.n = false; - cpu->cc.z = true; - cpu->cc.v = false; - cpu->cc.c = false; - return 0; -} - -/************************************************************************/ - -static mc6809byte__t op_sub( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - mc6809byte__t ci; - - assert(cpu != NULL); - - res = dest - src; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = src > dest; - cpu->cc.v = ((ci & 0x80) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - -static void op_cmp( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - mc6809byte__t ci; - - assert(cpu != NULL); - - res = dest - src; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = src > dest; - cpu->cc.v = ((ci & 0x80) != 0) ^ cpu->cc.c; -} - -/************************************************************************/ - -static mc6809byte__t op_sbc( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - mc6809byte__t ci; - - assert(cpu != NULL); - assert(cpu->cc.c <= 1); - - res = dest - src - cpu->cc.c; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = src >= dest; - cpu->cc.v = ((ci & 0x80) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_and( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = dest & src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = false; - return res; -} - -/************************************************************************/ - -static void op_bit( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = dest & src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = false; -} - -/************************************************************************/ - -static void op_ldst( - mc6809__t *const cpu, - const mc6809byte__t dest -) -{ - assert(cpu != NULL); - - cpu->cc.n = (dest > 0x7F); - cpu->cc.z = (dest == 0x00); - cpu->cc.v = false; -} - -/************************************************************************/ - -static mc6809byte__t op_eor( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = dest ^ src; - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.v = false; - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_adc( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - mc6809byte__t ci; - - assert(cpu != NULL); - assert(cpu->cc.c <= 1); - - res = dest + src + cpu->cc.c; - ci = res ^ dest ^ src; - cpu->cc.h = (ci & 0x10); - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = (res < dest) || (res < src); // Fix by DMB, was (res <= dest) || (res <= src), incorrect when src==dest==cin==0 - cpu->cc.v = ((ci & 0x80) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_or( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - - assert(cpu != NULL); - - res = dest | src; - cpu->cc.n = (res > 0x7f); - cpu->cc.z = (res == 0x00); - cpu->cc.v = false; - return res; -} - -/************************************************************************/ - -static mc6809byte__t op_add( - mc6809__t *const cpu, - const mc6809byte__t dest, - const mc6809byte__t src -) -{ - mc6809byte__t res; - mc6809byte__t ci; - - assert(cpu != NULL); - - res = dest + src; - ci = res ^ dest ^ src; - cpu->cc.h = (ci & 0x10); - cpu->cc.n = (res > 0x7F); - cpu->cc.z = (res == 0x00); - cpu->cc.c = (res < dest) || (res < src); - cpu->cc.v = ((ci & 0x80) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - -static mc6809addr__t op_sub16( - mc6809__t *const cpu, - const mc6809addr__t dest, - const mc6809addr__t src -) -{ - mc6809addr__t res; - mc6809addr__t ci; - - assert(cpu != NULL); - - res = dest - src; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7FFF); - cpu->cc.z = (res == 0x0000); - cpu->cc.c = src > dest; - cpu->cc.v = ((ci & 0x8000) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - -static void op_cmp16( - mc6809__t *const cpu, - const mc6809addr__t dest, - const mc6809addr__t src -) -{ - mc6809addr__t res; - mc6809addr__t ci; - - assert(cpu != NULL); - - res = dest - src; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7FFF); - cpu->cc.z = (res == 0x0000); - cpu->cc.c = src > dest; - cpu->cc.v = ((ci & 0x8000) != 0) ^ cpu->cc.c; -} - -/************************************************************************/ - -static void op_ldst16( - mc6809__t *const cpu, - const mc6809addr__t data -) -{ - assert(cpu != NULL); - cpu->cc.n = (data > 0x7FFF); - cpu->cc.z = (data == 0x0000); - cpu->cc.v = false; -} - -/************************************************************************/ - -static mc6809addr__t op_add16( - mc6809__t *const cpu, - const mc6809addr__t dest, - const mc6809addr__t src -) -{ - mc6809addr__t res; - mc6809addr__t ci; - - assert(cpu != NULL); - - res = dest + src; - ci = res ^ dest ^ src; - cpu->cc.n = (res > 0x7FFF); - cpu->cc.z = (res == 0x0000); - cpu->cc.c = (res < dest) || (res < src); - cpu->cc.v = ((ci & 0x8000) != 0) ^ cpu->cc.c; - return res; -} - -/************************************************************************/ - diff --git a/src/mc6809sc/mc6809.h b/src/mc6809sc/mc6809.h deleted file mode 100644 index 982d0cdc..00000000 --- a/src/mc6809sc/mc6809.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************** -* -* Copyright 2012 by Sean Conner. All Rights Reserved. -* -* This library is free software; you can redistribute it and/or modify it -* under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 3 of the License, or (at your -* option) any later version. -* -* This library is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -* License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this library; if not, see . -* -* Comments, questions and criticisms can be sent to: sean@conman.org -* -*********************************************/ - -#ifndef MC6809_H -#define MC6809_H - -#include -#include -#include - -#ifndef __GNUC__ -# define __attribute__(x) -#endif - -#define __i386 - -#if defined(__i386) -# define MSB 1 -# define LSB 0 -#elif defined(__x86_64) -# define MSB 1 -# define LSB 0 -#else -# error You need to define the byte order -#endif - -/************************************************************************/ - -#define MC6809_VECTOR_RSVP 0xFEF0 -#define MC6809_VECTOR_SWI3 0xFEF2 -#define MC6809_VECTOR_SWI2 0xFEF4 -#define MC6809_VECTOR_FIRQ 0xFEF6 -#define MC6809_VECTOR_IRQ 0xFEF8 -#define MC6809_VECTOR_SWI 0xFEFA -#define MC6809_VECTOR_NMI 0xFEFC -#define MC6809_VECTOR_RESET 0xFEFE - -/************************************************************************/ - -typedef enum -{ - MC6809_FAULT_INTERNAL_ERROR = 1, - MC6809_FAULT_INSTRUCTION, - MC6809_FAULT_ADDRESS_MODE, - MC6809_FAULT_EXG, - MC6809_FAULT_TFR, - MC6809_FAULT_user -} mc6809fault__t; - -typedef uint8_t mc6809byte__t; -typedef uint16_t mc6809addr__t; -typedef union -{ - mc6809byte__t b[2]; - mc6809addr__t w; -} mc6809word__t; - -typedef struct mc6809 -{ - mc6809word__t pc; - mc6809word__t index[4]; - mc6809word__t d; - mc6809byte__t dp; - struct - { - bool e; - bool f; - bool h; - bool i; - bool n; - bool z; - bool v; - bool c; - } cc; - - unsigned long cycles; - mc6809addr__t instpc; - mc6809word__t ea; - mc6809byte__t inst; - bool nmi_armed; - bool nmi; - bool firq; - bool irq; - bool cwai; - bool sync; - bool page2; - bool page3; - jmp_buf err; - - void *user; - mc6809byte__t (*read) (struct mc6809 *,mc6809addr__t,bool); - void (*write)(struct mc6809 *,mc6809addr__t,mc6809byte__t); - void (*fault)(struct mc6809 *,mc6809fault__t); -} mc6809__t; - -#define X index[0] -#define Y index[1] -#define U index[2] -#define S index[3] -#define A d.b[MSB] -#define B d.b[LSB] - -/**********************************************************************/ - -void mc6809_reset (mc6809__t *const) __attribute__((nonnull)); -int mc6809_run (mc6809__t *const) __attribute__((nonnull)); -int mc6809_step (mc6809__t *const) __attribute__((nonnull)); - -mc6809byte__t mc6809_cctobyte (mc6809__t *const) __attribute__((nonnull)); -void mc6809_bytetocc (mc6809__t *const,mc6809byte__t) __attribute__((nonnull)); - -void mc6809_direct (mc6809__t *const) __attribute__((nonnull)); -void mc6809_relative (mc6809__t *const) __attribute__((nonnull)); -void mc6809_lrelative(mc6809__t *const) __attribute__((nonnull)); -void mc6809_extended (mc6809__t *const) __attribute__((nonnull)); -void mc6809_indexed (mc6809__t *const) __attribute__((nonnull)); - -/**********************************************************************/ - -#endif From 24b48b061033eb3c4261d6ccdfa839b2a8b226b1 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 19:09:23 +0000 Subject: [PATCH 075/149] Finish off changing to new FIQ tube handler. Tidy --- src/copro-32016.c | 11 ++++++----- src/copro-80186.c | 19 ++++++++++--------- src/copro-arm2.c | 18 ++++++++++-------- src/copro-lib6502.c | 22 ++++++++++++---------- src/copro-mc6809nc.c | 20 +++++++++----------- src/copro-z80.c | 10 ++++++---- src/tube-client.c | 2 +- src/tube-ula.c | 3 +-- 8 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/copro-32016.c b/src/copro-32016.c index 6fec4863..5815308f 100644 --- a/src/copro-32016.c +++ b/src/copro-32016.c @@ -36,6 +36,7 @@ static void copro_32016_reset() { void copro_32016_emulator() { unsigned int last_rst = 0; + unsigned int rst; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -48,10 +49,10 @@ void copro_32016_emulator() { // might need to reduce if we see LATEs tubecycles = 8; n32016_exec(); - if (tube_irq & 7) { - unsigned int rst = tube_irq & 4; + rst = tube_irq & RESET_BIT ; + if (rst) { // Reset the processor on active edge of rst - if (rst && !last_rst) { + if (!last_rst) { // Exit if the copro has changed if (copro != last_copro) { break; @@ -59,9 +60,9 @@ void copro_32016_emulator() { copro_32016_reset(); } // NMI is edge sensitive, so only check after mailbox activity - // Note: 32016 uses tube_irq directly, so no nmi code here - last_rst = rst; + // Note: 32016 uses tube_irq directly, so no nmi code here } + last_rst = rst; // IRQ is level sensitive, so check between every instruction // Note: 32016 uses tube_irq directly, so no irq code here } diff --git a/src/copro-80186.c b/src/copro-80186.c index 1e27b468..422b029a 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -36,6 +36,7 @@ void copro_80186_tube_write(uint16_t addr, uint8_t data) { void copro_80186_emulator() { unsigned int last_rst = 0; + unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -46,26 +47,26 @@ void copro_80186_emulator() while (1) { exec86(1); - - if (tube_irq & 7) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT) ; + if (tube_irq_copy) { // Reset the processor on active edge of rst - if (rst && !last_rst) { + if ( (tube_irq_copy & RESET_BIT) && !last_rst) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_80186_reset(); } + last_rst = (tube_irq_copy & RESET_BIT); + // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { + if (tube_irq_copy & NMI_BIT) { intcall86(2); + tube_ack_nmi(); } - last_rst = rst; - + // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { + if (tube_irq_copy & IRQ_BIT) { if (ifl) { intcall86(12); } diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 0697a177..094d260b 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -147,6 +147,7 @@ static void copro_arm2_reset() void copro_arm2_emulator() { unsigned int last_rst = 0; + unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -157,25 +158,26 @@ void copro_arm2_emulator() while (1) { arm2_execute_run(1); - if (tube_irq & 7) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT); + if (tube_irq_copy ) { // Reset the processor on active edge of rst - if (rst && !last_rst) { + if ( (tube_irq_copy & RESET_BIT) && !last_rst) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_arm2_reset(); } + last_rst = (tube_irq_copy & RESET_BIT); + // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { + if (tube_irq_copy & NMI_BIT) { arm2_execute_set_input(ARM_FIRQ_LINE, 1); + tube_ack_nmi(); } - last_rst = rst; - + // IRQ is level sensitive, so check between every instruction - arm2_execute_set_input(ARM_IRQ_LINE, tube_irq & 1); + arm2_execute_set_input(ARM_IRQ_LINE, tube_irq_copy & IRQ_BIT); } } } diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index d159d9d0..7a4cd33f 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -20,7 +20,7 @@ #include "copro-lib6502.h" #include "startup.h" -int tracing=0; +const int tracing=0; static void copro_lib6502_poweron_reset(M6502 *mpu) { // Wipe memory @@ -55,25 +55,27 @@ static int last_copro; static int copro_lib6502_poll(M6502 *mpu) { static unsigned int last_rst = 0; - if (tube_irq & 7) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; + unsigned int tube_irq_copy; + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT ); + if (tube_irq_copy) { // Reset the processor on a rst going inactive - if (rst && !last_rst) { + if ( ( tube_irq_copy & RESET_BIT ) && !last_rst) { // Exit if the copro has changed if (copro != last_copro) { return 1; } - copro_lib6502_reset(mpu); + copro_lib6502_reset(mpu); } + last_rst = ( tube_irq_copy & RESET_BIT ); + // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { + if ( tube_irq_copy & NMI_BIT) { M6502_nmi(mpu); + tube_ack_nmi(); } - last_rst = rst; - + // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { + if (tube_irq_copy & IRQ_BIT) { if (!(mpu->registers->p & 4)) { M6502_irq(mpu); } diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 1d4e986f..1fc7a00d 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -77,9 +77,9 @@ static void copro_mc6809_reset() { void copro_mc6809nc_emulator() { - unsigned int last_rst = 0; - + unsigned int tube_irq_copy; + // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -90,27 +90,25 @@ void copro_mc6809nc_emulator() { // Execute emulator for one instruction mc6809nc_execute(1); - - if (tube_irq & 7) { - unsigned int nmi = tube_irq & 2; - unsigned int rst = tube_irq & 4; + tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT); + if (tube_irq_copy) { // Reset the processor on active edge of rst - if (rst && !last_rst) { + if (( tube_irq_copy & RESET_BIT ) && !last_rst) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_mc6809_reset(); } + last_rst = tube_irq_copy & RESET_BIT ; // NMI is edge sensitive, so only check after mailbox activity - if (nmi) { + if ( tube_irq_copy & NMI_BIT ) { mc6809nc_request_irq(1); + tube_ack_nmi(); } - last_rst = rst; - // IRQ is level sensitive, so check between every instruction - if (tube_irq & 1) { + if ( tube_irq_copy & IRQ_BIT ) { mc6809nc_request_firq(1); } } diff --git a/src/copro-z80.c b/src/copro-z80.c index 7877cddf..aa5fe1a8 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -326,6 +326,7 @@ static void copro_z80_reset() { void copro_z80_emulator() { unsigned int last_rst = 0; + unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -337,10 +338,11 @@ void copro_z80_emulator() { // Execute emulator for one instruction simz80_execute(1); - if (tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT)) { + 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 & RESET_BIT) { + if (tube_irq_copy & RESET_BIT) { if (!last_rst) { // Exit if the copro has changed if (copro != last_copro) { @@ -354,14 +356,14 @@ void copro_z80_emulator() } // NMI is edge sensitive, - if (tube_irq & NMI_BIT) { + if (tube_irq_copy & NMI_BIT) { overlay_rom = 1; simz80_NMI(); tube_ack_nmi(); } // IRQ is level sensitive, - if (tube_irq & IRQ_BIT) { + if (tube_irq_copy & IRQ_BIT) { // check if the emulator IRQ is enabled if (simz80_is_IRQ_enabled()) { simz80_IRQ(); diff --git a/src/tube-client.c b/src/tube-client.c index 5ce9f158..9b203c34 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -62,7 +62,7 @@ static const char * emulator_names[] = { static const func_ptr emulator_functions[] = { copro_65tube_emulator, copro_65tube_emulator, -#if DEBUG +#if 1 copro_lib6502_emulator, copro_lib6502_emulator, #else diff --git a/src/tube-ula.c b/src/tube-ula.c index 7071ec2f..c75bff1c 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -168,8 +168,7 @@ void tube_ack_nmi(void) tube_irq &= ~NMI_BIT; if ((cpsr & 0xc0) != 0xc0) { _enable_interrupts(); - } - + } } void copro_command_excute(unsigned char copro_command,unsigned char val) From 3b1bd199876ff0b7ed75381320451877b836e455 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 19:35:50 +0000 Subject: [PATCH 076/149] Remove tabs I accidently commited --- src/tube-client.c | 14 +++++++------- src/tube-ula.c | 36 ++++++++++++++++-------------------- src/tube.S | 10 +++++----- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/tube-client.c b/src/tube-client.c index 9b203c34..d8757d62 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -146,14 +146,14 @@ void run_core() { // In case the VFP unit is not enabled #ifdef DEBUG int i; - RPI_AuxMiniUartWrite('C'); - RPI_AuxMiniUartWrite('O'); - RPI_AuxMiniUartWrite('R'); - RPI_AuxMiniUartWrite('E'); + RPI_AuxMiniUartWrite('C'); + RPI_AuxMiniUartWrite('O'); + RPI_AuxMiniUartWrite('R'); + RPI_AuxMiniUartWrite('E'); i = _get_core(); - RPI_AuxMiniUartWrite('0' + i); - RPI_AuxMiniUartWrite('\r'); - RPI_AuxMiniUartWrite('\n'); + RPI_AuxMiniUartWrite('0' + i); + RPI_AuxMiniUartWrite('\r'); + RPI_AuxMiniUartWrite('\n'); #endif enable_MMU_and_IDCaches(); diff --git a/src/tube-ula.c b/src/tube-ula.c index c75bff1c..6ce76e1a 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -576,7 +576,7 @@ int tube_io_handler(uint32_t mail) int rnw; int ntube; int nrst; - + #ifdef USE_HW_MAILBOX // Sequence numbers are currently 4 bits, and are stored in bits 12..15 int act_seq_num; @@ -586,20 +586,20 @@ int tube_io_handler(uint32_t mail) #endif // Toggle the LED on each tube access static int led = 0; - if (led) { - LED_OFF(); - } else { - LED_ON(); - } - led = ~led; -#ifdef USE_GPU - + if (led) { + LED_OFF(); + } else { + LED_ON(); + } + led = ~led; +#ifdef USE_GPU + if ((mail >> 12) & 1) // Check for Reset { tube_irq |= RESET_BIT; return tube_irq; // Set reset Flag } - else + else { addr = (mail>>8) & 7; if ( ( (mail >>11 ) & 1) == 0) { // Check read write flag @@ -607,10 +607,9 @@ int tube_io_handler(uint32_t mail) } else { tube_host_read(addr); } - - return tube_irq ; + return tube_irq ; } -#else +#else addr = 0; if (mail & A0_MASK) { addr += 1; @@ -650,7 +649,7 @@ int tube_io_handler(uint32_t mail) LOG_WARN("OVERRUN: A=%d; D=%02X; RNW=%d; NTUBE=%d; nRST=%d\r\n", addr, data, rnw, ntube, nrst); } #endif - + if (mail & GLITCH_MASK) { LOG_WARN("GLITCH: A=%d; D=%02X; RNW=%d; NTUBE=%d; nRST=%d\r\n", addr, data, rnw, ntube, nrst); @@ -670,7 +669,7 @@ int tube_io_handler(uint32_t mail) #if TEST_MODE LOG_INFO("A=%d; D=%02X; RNW=%d; NTUBE=%d; nRST=%d\r\n", addr, data, rnw, ntube, nrst); #endif - + if (nrst == 0 || (tube_enabled && (HSTAT1 & HBIT_5))) { return tube_irq | 4; } else { @@ -761,9 +760,7 @@ void tube_init_hardware() tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; - hp1 = hp2 = hp4 = hp3[0]= hp3[1]=0; - } int tube_is_rst_active() { @@ -877,7 +874,7 @@ void start_vc_ula() LOG_DEBUG("VidCore r2 = %08x\r\n", r2); LOG_DEBUG("VidCore r3 = %08x\r\n", r3); LOG_DEBUG("VidCore r4 = %08x\r\n", r4); - LOG_DEBUG("VidCore r5 = %08x\r\n", r5); + LOG_DEBUG("VidCore r5 = %08x\r\n", r5); RPI_PropertyInit(); RPI_PropertyAddTag(TAG_EXECUTE_CODE,func,r0,r1,r2,r3,r4,r5); RPI_PropertyProcessNoCheck(); @@ -893,6 +890,5 @@ void start_vc_ula() // LOG_DEBUG("%08x ?\r\n", r0); // } // } - -} +} diff --git a/src/tube.S b/src/tube.S index 33bddd7a..3bd63279 100644 --- a/src/tube.S +++ b/src/tube.S @@ -30,13 +30,13 @@ arm_fiq_handler_flag1: push {r0-r7,r14} ldr r0, [r12] // Get Mailbox data - BL tube_io_handler - ldr r10,=tube_irq + BL tube_io_handler + ldr r10,=tube_irq pop {r0-r7,r14} - ldr r10,[r10] + ldr r10,[r10] tst r10, #FAST6502_BIT // see if we should signal the 6502 Core - tstne r10,#RESET_BIT+NMI_BIT+IRQ_BIT - orrne instrREG, instrREG, #1024 + tstne r10,#RESET_BIT+NMI_BIT+IRQ_BIT + orrne instrREG, instrREG, #1024 subs pc, lr, #4 From b5c9e316e0fb30e9e3c8c08c19ea8cf1d2466793 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 20:10:31 +0000 Subject: [PATCH 077/149] USE_MEM --- src/copro-arm2.c | 16 ++++++++++++++++ src/copro-mc6809nc.c | 8 ++++++++ src/copro-z80.c | 4 ++-- src/cpu80186/mem80186.c | 12 ++++++++++-- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 094d260b..201b1077 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -43,7 +43,11 @@ UINT8 copro_arm2_read8(int addr) switch (type) { case 0: +#if USE_MEMORY_POINTER return *(UINT8*) (arm2_ram + (addr & RAM_MASK8)); +#else + return *(UINT8*) ( (addr & RAM_MASK8)); +#endif case 1: return tube_parasite_read((addr >> 2) & 7); case 3: @@ -66,7 +70,11 @@ UINT32 copro_arm2_read32(int addr) switch (type) { case 0: +#if USE_MEMORY_POINTER result = *(UINT32*) (arm2_ram + (addr & RAM_MASK32)); +#else + result = *(UINT32*) ((addr & RAM_MASK32)); +#endif break; case 1: result = tube_parasite_read((addr >> 2) & 7); @@ -98,7 +106,11 @@ void copro_arm2_write8(int addr, UINT8 data) switch (type) { case 0: +#if USE_MEMORY_POINTER *(UINT8*) (arm2_ram + (addr & RAM_MASK8)) = data; +#else + *(UINT8*) ( (addr & RAM_MASK8)) = data; +#endif break; case 1: tube_parasite_write((addr >> 2) & 7, data); @@ -112,7 +124,11 @@ void copro_arm2_write32(int addr, UINT32 data) switch (type) { case 0: +#if USE_MEMORY_POINTER *(UINT32*) (arm2_ram + (addr & RAM_MASK32)) = data; +#else + *(UINT32*) ( (addr & RAM_MASK32)) = data; +#endif break; case 1: tube_parasite_write((addr >> 2) & 7, data); diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 1fc7a00d..2d4b4a55 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -30,7 +30,11 @@ void copro_mc6809nc_write(uint16_t addr, uint8_t data) { overlay_rom = 0; tube_parasite_write(addr & 7, data); } else { +#ifdef USE_MEMORY_POINTER copro_mc6809_ram[addr & 0xffff] = data; +#else + *(unsigned char *)(addr & 0xffff) = data; +#endif } if (debug) { printf("Wr %04x=%02x\r\n", addr, data); @@ -45,7 +49,11 @@ uint8_t copro_mc6809nc_read(uint16_t addr) { } else if (overlay_rom) { data = copro_mc6809_rom[addr & 0x7ff]; } else { +#if USE_MEMORY_POINTER data = copro_mc6809_ram[addr & 0xffff]; +#else + data = *(unsigned char *)(addr & 0xffff); +#endif } if (debug) { printf("Rd %04x=%02x\r\n", addr, data); diff --git a/src/copro-z80.c b/src/copro-z80.c index aa5fe1a8..10532c32 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -286,7 +286,7 @@ int copro_z80_read_mem(unsigned int addr) { return copro_z80_ram[addr & 0xffff]; #else return *(unsigned char *)(addr & 0xffff); -#endif +#endif } } @@ -295,7 +295,7 @@ void copro_z80_write_mem(unsigned int addr, unsigned char data) { copro_z80_ram[addr & 0xffff] = data; #else *(unsigned char *)(addr & 0xffff) = data; -#endif +#endif } int copro_z80_read_io(unsigned int addr) { diff --git a/src/cpu80186/mem80186.c b/src/cpu80186/mem80186.c index 77f55e8f..a3908b55 100644 --- a/src/cpu80186/mem80186.c +++ b/src/cpu80186/mem80186.c @@ -38,7 +38,11 @@ void write86(uint32_t addr32, uint8_t value) { addr32 &= 0xFFFFFF; if (addr32 < 0xF0000) { - RAM[addr32] = value; +#if USE_MEMORY_POINTER + RAM[addr32] = value; +#else + *(unsigned char *)(addr32) = value; +#endif } } @@ -50,7 +54,11 @@ void writew86(uint32_t addr32, uint16_t value) uint8_t read86(uint32_t addr32) { - return (RAM[addr32 & 0xFFFFF]); +#if USE_MEMORY_POINTER + return (RAM[addr32 & 0xFFFFF]); +#else + return *(unsigned char *)(addr32& 0xFFFFF) ; +#endif } uint16_t readw86(uint32_t addr32) From d0a7bae12bcde3bbf23a38bb44e346847a128c60 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 20:35:19 +0000 Subject: [PATCH 078/149] Make cppcheck happy --- src/performance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/performance.c b/src/performance.c index 013dbcdc..bee55df8 100644 --- a/src/performance.c +++ b/src/performance.c @@ -213,7 +213,7 @@ int benchmark() { perf_counters_t pct; unsigned char mem1[1024*1024]; unsigned char mem2[1024*1024]; - + mem2[0]=0; #if defined(RPI2) || defined(RPI3) pct.num_counters = 6; pct.type[0] = PERF_TYPE_L1I_CACHE; From 2be8cc844b90562c60d656c71dfeefbca1516d6a Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 22 Mar 2017 20:54:02 +0000 Subject: [PATCH 079/149] Fix cppcheck warning --- src/mc6809nc/mc6809.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index 927ad11f..46fa00f0 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -764,7 +764,7 @@ static void daa (void) res += 0x60; C |= (res & 0x100); - A = N = Z = res &= 0xff; + A = N = Z = (res & 0xff); OV = 0; /* fix this */ cpu_clk -= 2; From 11bc6d40bff8f931a11a1b515e2b2a41bf2db10d Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 24 Mar 2017 17:56:58 +0000 Subject: [PATCH 080/149] Fixed NMI bug that causes tube-transfer tests to fail Change-Id: I413c0c0cbd3ee0427ddda037e71dc27d562e8420 --- src/tube-ula.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 6ce76e1a..8569beb7 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -286,14 +286,14 @@ static void tube_host_write(uint16_t addr, uint8_t val) // only if we are now enabling NMIs do we possibly set NMI flag. // NB NMIs are edge sensitive so this doesn't create extra false edges - if (val & 0x10) { + if (val & 0x08) { if (!(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq |= NMI_BIT; if ( (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq |= NMI_BIT; } } } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); - if (val & 0x10) tube_irq &= ~NMI_BIT; // if we are turning off NMI clear NMI flag + if (val & 0x08) tube_irq &= ~NMI_BIT; // if we are turning off NMI clear NMI flag } if ( HSTAT1 & HBIT_5) { From ded51bafbd517646cdf7b2d5d4de60efc12e903d Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 24 Mar 2017 20:34:45 +0000 Subject: [PATCH 081/149] Fix cppcheck warnings, Use PRIx32 and PRIu32 --- src/darm/darm.c | 17 +++++++++-------- src/darm/thumb2.c | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/darm/darm.c b/src/darm/darm.c index b04b1673..972cc3ca 100644 --- a/src/darm/darm.c +++ b/src/darm/darm.c @@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "darm.h" #include "darm-internal.h" @@ -623,7 +624,7 @@ int darm_reglist(uint16_t reglist, char *out) void darm_dump(const darm_t *d) { printf( - "encoded: 0x%08lx\n" + "encoded: 0x%08"PRIx32"\n" "instr: I_%s\n" "instr-type: T_%s\n", d->w, darm_mnemonic_name(d->instr), @@ -649,11 +650,11 @@ void darm_dump(const darm_t *d) PRINT_REG(RdLo); if(d->I == B_SET) { - printf("imm: 0x%08lx %lu\n", d->imm, d->imm); + printf("imm: 0x%08"PRIx32" %"PRIu32"\n", d->imm, d->imm); } #define PRINT_FLAG(flag, comment, comment2) if(d->flag != B_INVLD) \ - printf("%s: %lu (%s)\n", #flag, d->flag, \ + printf("%s: %"PRIu32" (%s)\n", #flag, d->flag, \ d->flag == B_SET ? comment : comment2) PRINT_FLAG(B, "swap one byte", "swap four bytes"); @@ -678,14 +679,14 @@ void darm_dump(const darm_t *d) } if(d->rotate != 0) { - printf("rotate: %lu\n", d->rotate); + printf("rotate: %"PRIu32"\n", d->rotate); } if(d->shift_type != S_INVLD) { if(d->Rs == R_INVLD) { printf( "type: %s (shift type)\n" - "shift: %-2lu (shift constant)\n", + "shift: %-2"PRIu32" (shift constant)\n", darm_shift_type_name(d->shift_type), d->shift); } else { @@ -699,8 +700,8 @@ void darm_dump(const darm_t *d) if(d->lsb != 0 || d->width != 0) { printf( - "lsb: %lu\n" - "width: %lu\n", + "lsb: %"PRIu32"\n" + "width: %"PRIu32"\n", d->lsb, d->width); } @@ -710,7 +711,7 @@ void darm_dump(const darm_t *d) printf("reglist: %s\n", reglist); } if (d->sat_imm != 0) { - printf("sat_imm: 0x%08lx %lu\n", d->sat_imm, d->sat_imm); + printf("sat_imm: 0x%08"PRIx32" %"PRIu32"\n", d->sat_imm, d->sat_imm); } if(d->opc1 != 0 || d->opc2 != 0 || d->coproc != 0) { diff --git a/src/darm/thumb2.c b/src/darm/thumb2.c index a6bceb76..aef901df 100644 --- a/src/darm/thumb2.c +++ b/src/darm/thumb2.c @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "darm.h" #include "darm-internal.h" #include "thumb-tbl.h" @@ -627,7 +628,7 @@ char *darm_thumb2_str(darm_t *d) } if(d->I == B_SET) { - offset += sprintf(stringbuf+offset, "#0x%lx", d->imm); + offset += sprintf(stringbuf+offset, "#0x%"PRIx32, d->imm); } return stringbuf; From d1fbe189533d1035df0eb6a3d6ef5029634ab173 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 25 Mar 2017 11:28:40 +0000 Subject: [PATCH 082/149] Reworked write of tube ctrl reg to eliminate corner cases Change-Id: I1cb92e090a758003bc98b92264eebfcc93062f3a --- src/tube-ula.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 8569beb7..fd0c5d92 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -272,10 +272,15 @@ static void tube_host_write(uint16_t addr, uint8_t val) { switch (addr & 7) { - case 0: /*Register 1 stat*/ - + case 0: /*Register 1 control/status*/ + if (!(tube_irq & TUBE_ENABLE_BIT)) return; + + // Evaluate NMI before the control register written + int nmi1 = 0; + if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) nmi1 = 1; + if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) nmi1 = 1; if (val & 0x80) { // Implement software tube reset @@ -283,17 +288,9 @@ static void tube_host_write(uint16_t addr, uint8_t val) tube_reset(); } else { HSTAT1 |= BYTE_TO_WORD(val & 0x3F); - - // only if we are now enabling NMIs do we possibly set NMI flag. - // NB NMIs are edge sensitive so this doesn't create extra false edges - if (val & 0x08) { - if (!(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) tube_irq |= NMI_BIT; - if ( (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) tube_irq |= NMI_BIT; - } } } else { HSTAT1 &= ~BYTE_TO_WORD(val & 0x3F); - if (val & 0x08) tube_irq &= ~NMI_BIT; // if we are turning off NMI clear NMI flag } if ( HSTAT1 & HBIT_5) { @@ -301,6 +298,18 @@ static void tube_host_write(uint16_t addr, uint8_t val) } else { tube_irq &= ~RESET_BIT; } + + // Evaluate NMI again after the control register written + int nmi2 = 0; + if ((HSTAT1 & HBIT_3) && !(HSTAT1 & HBIT_4) && ((hp3pos > 0) || (ph3pos == 0))) nmi2 = 1; + if ((HSTAT1 & HBIT_3) && (HSTAT1 & HBIT_4) && ((hp3pos > 1) || (ph3pos == 0))) nmi2 = 1; + + // Only propagate significant rising edges + if (!nmi1 && nmi2) tube_irq |= NMI_BIT; + + // And disable regardless + if (!nmi2) tube_irq &= ~(NMI_BIT); + tube_irq &= ~(IRQ_BIT); if ((HSTAT1 & HBIT_1) && (PSTAT1 & 128)) tube_irq |= IRQ_BIT; if ((HSTAT1 & HBIT_2) && (PSTAT4 & 128)) tube_irq |= IRQ_BIT; From 99e4d339b6fb74342915e918afdfb3cb7596983b Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 25 Mar 2017 11:29:16 +0000 Subject: [PATCH 083/149] Fixed reset hang issue with several Co Pros Change-Id: I82a761d5ccba2aca5952bb62bf56fd78a606692a --- src/copro-80186.c | 2 ++ src/copro-arm2.c | 4 +++- src/copro-lib6502.c | 2 ++ src/copro-mc6809nc.c | 4 +++- src/copro-z80.c | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/copro-80186.c b/src/copro-80186.c index 422b029a..3341a01f 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -71,6 +71,8 @@ void copro_80186_emulator() intcall86(12); } } + } else { + last_rst = 0; } } } diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 201b1077..e92895b5 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -194,6 +194,8 @@ void copro_arm2_emulator() // IRQ is level sensitive, so check between every instruction arm2_execute_set_input(ARM_IRQ_LINE, tube_irq_copy & IRQ_BIT); - } + } else { + last_rst = 0; + } } } diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index 7a4cd33f..9e2596c5 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -80,6 +80,8 @@ static int copro_lib6502_poll(M6502 *mpu) { M6502_irq(mpu); } } + } else { + last_rst = 0; } return 0; } diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 2d4b4a55..bff297ca 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -119,6 +119,8 @@ void copro_mc6809nc_emulator() if ( tube_irq_copy & IRQ_BIT ) { mc6809nc_request_firq(1); } - } + } else { + last_rst = 0; + } } } diff --git a/src/copro-z80.c b/src/copro-z80.c index 10532c32..bf94973c 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -369,6 +369,8 @@ void copro_z80_emulator() simz80_IRQ(); } } + } else { + last_rst = 0; } } } From 104bcc53651287cad717f02fbbc3b3f35dec51a0 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 25 Mar 2017 17:14:04 +0000 Subject: [PATCH 084/149] Debugger: Added memory hooks for 6809 and arm2 Change-Id: I5937e501d084378cd198767fa85cc0c5d2556148 --- src/copro-arm2.c | 214 ++++++++++++++++++++++------------------ src/copro-mc6809nc.c | 23 +++-- src/debugger/debugger.c | 33 +++++-- src/mame/arm_debug.c | 2 - 4 files changed, 160 insertions(+), 112 deletions(-) diff --git a/src/copro-arm2.c b/src/copro-arm2.c index 67ce0bba..7f98eb6a 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -18,6 +18,11 @@ #include "startup.h" #include "tube-client.h" +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "mame/arm_debug.h" +#endif + #define RAM_MASK8 ((UINT32) 0x003fffff) #define ROM_MASK8 ((UINT32) 0x00003fff) #define RAM_MASK32 ((UINT32) 0x003ffffc) @@ -32,120 +37,137 @@ UINT8 * arm2_ram; #define R15 arm2_getR15() -UINT8 copro_arm2_read8(int addr) -{ - if (addr <= RAM_MASK8) - { - return arm2_ram[addr]; - } - - int type = (addr >> 24) & 3; - switch (type) - { - case 0: - return *(UINT8*) (arm2_ram + (addr & RAM_MASK8)); - case 1: - return tube_parasite_read((addr >> 2) & 7); - case 3: - return *(UINT8*) (tuberom_arm_v100+(addr & ROM_MASK8)); - } - return 0; - +UINT8 copro_arm2_read8(int addr) { + UINT8 result; + + if (addr <= RAM_MASK8) { + result = arm2_ram[addr]; + } else { + int type = (addr >> 24) & 3; + switch (type) { + case 0: + result = *(UINT8*) (arm2_ram + (addr & RAM_MASK8)); + break; + case 1: + result = tube_parasite_read((addr >> 2) & 7); + break; + case 3: + result = *(UINT8*) (tuberom_arm_v100+(addr & ROM_MASK8)); + break; + default: + result = 0; + break; + } + } +#ifdef INCLUDE_DEBUGGER + if (arm2_debug_enabled) { + debug_memread(&arm2_cpu_debug, addr, result, 4); + } +#endif + return result; } -UINT32 copro_arm2_read32(int addr) -{ - UINT32 result; - - if ((addr & ~RAM_MASK32) == 0) - { - return *(UINT32*) (arm2_ram + addr); - } - - int type = (addr >> 24) & 3; - switch (type) - { - case 0: - result = *(UINT32*) (arm2_ram + (addr & RAM_MASK32)); - break; - case 1: - result = tube_parasite_read((addr >> 2) & 7); - break; - case 3: - result = *(UINT32*) (tuberom_arm_v100+(addr & ROM_MASK32)); - break; - default: - result = 0; - } - /* Unaligned reads rotate the word, they never combine words */ - if (addr & 3) - { - if (ARM_DEBUG_CORE && (addr & 1)) - logerror("%08x: Unaligned byte read %08x\n", R15, addr); - if ((addr & 3) == 1) - return ((result & 0x000000ff) << 24) | ((result & 0xffffff00) >> 8); - if ((addr & 3) == 2) - return ((result & 0x0000ffff) << 16) | ((result & 0xffff0000) >> 16); - if ((addr & 3) == 3) - return ((result & 0x00ffffff) << 8) | ((result & 0xff000000) >> 24); - } - return result; +UINT32 copro_arm2_read32(int addr) { + UINT32 result; + + if ((addr & ~RAM_MASK32) == 0) { + result = *(UINT32*) (arm2_ram + addr); + } else { + int type = (addr >> 24) & 3; + switch (type) { + case 0: + result = *(UINT32*) (arm2_ram + (addr & RAM_MASK32)); + break; + case 1: + result = tube_parasite_read((addr >> 2) & 7); + break; + case 3: + result = *(UINT32*) (tuberom_arm_v100+(addr & ROM_MASK32)); + break; + default: + result = 0; + break; + } + } + /* Unaligned reads rotate the word, they never combine words */ + if (addr & 3) { + if (ARM_DEBUG_CORE && (addr & 1)) + logerror("%08x: Unaligned byte read %08x\n", R15, addr); + if ((addr & 3) == 1) { + result = ((result & 0x000000ff) << 24) | ((result & 0xffffff00) >> 8); + } else if ((addr & 3) == 2) { + result = ((result & 0x0000ffff) << 16) | ((result & 0xffff0000) >> 16); + } else if ((addr & 3) == 3) { + result = ((result & 0x00ffffff) << 8) | ((result & 0xff000000) >> 24); + } + } +#ifdef INCLUDE_DEBUGGER + if (arm2_debug_enabled) { + debug_memread(&arm2_cpu_debug, addr, result, 4); + } +#endif + return result; } void copro_arm2_write8(int addr, UINT8 data) { - int type = (addr >> 24) & 3; - switch (type) - { - case 0: +#ifdef INCLUDE_DEBUGGER + if (arm2_debug_enabled) { + debug_memwrite(&arm2_cpu_debug, addr, data, 1); + } +#endif + int type = (addr >> 24) & 3; + switch (type) { + case 0: *(UINT8*) (arm2_ram + (addr & RAM_MASK8)) = data; - break; - case 1: + break; + case 1: tube_parasite_write((addr >> 2) & 7, data); - break; - } + break; + } } -void copro_arm2_write32(int addr, UINT32 data) -{ - int type = (addr >> 24) & 3; - switch (type) - { - case 0: +void copro_arm2_write32(int addr, UINT32 data) { +#ifdef INCLUDE_DEBUGGER + if (arm2_debug_enabled) { + debug_memwrite(&arm2_cpu_debug, addr, data, 4); + } +#endif + int type = (addr >> 24) & 3; + switch (type) { + case 0: *(UINT32*) (arm2_ram + (addr & RAM_MASK32)) = data; - break; - case 1: + break; + case 1: tube_parasite_write((addr >> 2) & 7, data); - break; - } - /* Unaligned writes are treated as normal writes */ - if (addr & 3) - printf("%08x: Unaligned write %08x\n", R15, addr); + break; + } + /* Unaligned writes are treated as normal writes */ + if (addr & 3) { + printf("%08x: Unaligned write %08x\n", R15, addr); + } } -static void copro_arm2_poweron_reset() -{ - // Wipe memory - arm2_ram = copro_mem_reset(ARM_RAM_SIZE); +static void copro_arm2_poweron_reset() { + // Wipe memory + arm2_ram = copro_mem_reset(ARM_RAM_SIZE); } -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); - // Reset the ARM device - arm2_device_reset(); - // Wait for rst become inactive before continuing to execute - tube_wait_for_rst_release(); - // Reset ARM performance counters - tube_reset_performance_counters(); +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); + // Reset the ARM device + arm2_device_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_arm2_emulator() -{ +void copro_arm2_emulator() { static unsigned int last_rst = 0; // Remember the current copro so we can exit if it changes diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index 55be2968..cfc722fd 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -17,24 +17,30 @@ #include "mc6809nc/mc6809.h" #include "tube-client.h" +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "mc6809nc/mc6809_debug.h" +#endif + static int overlay_rom = 0; static unsigned char *copro_mc6809_ram; static unsigned char *copro_mc6809_rom = tuberom_6809_jgh_1_0; -static int debug = 0; - void copro_mc6809nc_write(uint16_t addr, uint8_t data) { +#ifdef INCLUDE_DEBUGGER + if (mc6809nc_debug_enabled) + { + debug_memwrite(&mc6809nc_cpu_debug, addr, data, 1); + } +#endif if ((addr & 0xFFF0) == 0xFEE0) { overlay_rom = 0; tube_parasite_write(addr & 7, data); } else { copro_mc6809_ram[addr & 0xffff] = data; } - if (debug) { - printf("Wr %04x=%02x\r\n", addr, data); - } } uint8_t copro_mc6809nc_read(uint16_t addr) { @@ -47,9 +53,12 @@ uint8_t copro_mc6809nc_read(uint16_t addr) { } else { data = copro_mc6809_ram[addr & 0xffff]; } - if (debug) { - printf("Rd %04x=%02x\r\n", addr, data); +#ifdef INCLUDE_DEBUGGER + if (mc6809nc_debug_enabled) + { + debug_memread(&mc6809nc_cpu_debug, addr, data, 1); } +#endif return data; } diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index e78d876a..bac91f2b 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -171,6 +171,21 @@ cpu_debug_t *getCpu() { return cpu_debug_list[copro]; } +static int internal = 0; + +static uint32_t memread(cpu_debug_t *cpu, uint32_t addr) { + internal = 1; + uint32_t result = cpu->memread(addr); + internal = 0; + return result; +} + +static void memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { + internal = 1; + cpu->memwrite(addr, value); + internal = 0; +} + /******************************************************** * Hooks from CPU Emulation ********************************************************/ @@ -244,11 +259,15 @@ static inline void generic_memory_access(cpu_debug_t *cpu, uint32_t addr, uint32 } void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { - generic_memory_access(cpu, addr, value, size, "Mem Rd", mem_rd_breakpoints); + if (!internal) { + generic_memory_access(cpu, addr, value, size, "Mem Rd", mem_rd_breakpoints); + } }; void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { - generic_memory_access(cpu, addr, value, size, "Mem Wr", mem_wr_breakpoints); + if (!internal) { + generic_memory_access(cpu, addr, value, size, "Mem Wr", mem_wr_breakpoints); + } }; void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { @@ -408,7 +427,7 @@ static void doCmdFill(char *params) { printf("Wr: %x to %x = %02x\r\n", start, end, data); for (i = start; i <= end; i++) { - cpu->memwrite(i, data); + memwrite(cpu, i, data); } } @@ -422,7 +441,7 @@ static void doCmdCrc(char *params) { unsigned int crc = 0; sscanf(params, "%x %x", &start, &end); for (i = start; i <= end; i++) { - data = cpu->memread(i); + data = memread(cpu, i); for (j = 0; j < 8; j++) { crc = crc << 1; crc = crc | (data & 1); @@ -441,7 +460,7 @@ static void doCmdMem(char *params) { sscanf(params, "%x", &memAddr); for (i = 0; i < 0x100; i+= 16) { for (j = 0; j < 16; j++) { - row[j] = cpu->memread(memAddr + i + j); + row[j] = memread(cpu, memAddr + i + j); } printf("%04x ", memAddr + i); for (j = 0; j < 16; j++) { @@ -465,7 +484,7 @@ static void doCmdReadMem(char *params) { unsigned int addr; unsigned int data; sscanf(params, "%x", &addr); - data = cpu->memread(addr); + data = memread(cpu, addr); printf("Rd: %x = %02x\r\n", addr, data); } @@ -475,7 +494,7 @@ static void doCmdWriteMem(char *params) { unsigned int data; sscanf(params, "%x %x", &addr, &data); printf("Wr: %x = %02x\r\n", addr, data); - cpu->memwrite(addr++, data); + memwrite(cpu, addr++, data); } diff --git a/src/mame/arm_debug.c b/src/mame/arm_debug.c index f2b7f489..625e7d9b 100644 --- a/src/mame/arm_debug.c +++ b/src/mame/arm_debug.c @@ -93,13 +93,11 @@ static int dbg_debug_enable(int newvalue) { // CPU's usual memory read function for data. static uint32_t dbg_memread(uint32_t addr) { - // TODO: use the internal version so the debugger doesn't get notified return copro_arm2_read8(addr); }; // CPU's usual memory write function. static void dbg_memwrite(uint32_t addr, uint32_t value) { - // TODO: use the internal version so the debugger doesn't get notified copro_arm2_write8(addr, value); }; From d5cb5e540cc8f0aa12fb7417b4323bb8b5d88d96 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 25 Mar 2017 19:11:20 +0000 Subject: [PATCH 085/149] 80x86: Added debugger support Change-Id: Ic44b0a1fabc96e976f500c515610b97a99909c3c --- src/CMakeLists.txt | 2 + src/cpu80186/cpu80186.c | 27 ++++ src/cpu80186/cpu80186.h | 7 + src/cpu80186/cpu80186_debug.c | 250 ++++++++++++++++++++++++++++++++++ src/cpu80186/cpu80186_debug.h | 6 + src/cpu80186/iop80186.c | 30 +++- src/cpu80186/mem80186.c | 18 ++- src/cpu_debug.h | 4 + src/debugger/debugger.c | 132 ++++++++++++++++-- 9 files changed, 455 insertions(+), 21 deletions(-) create mode 100644 src/cpu80186/cpu80186_debug.c create mode 100644 src/cpu80186/cpu80186_debug.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2cf233b6..69008a8e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -239,6 +239,8 @@ file( GLOB debugger_files mc6809nc/mc6809_debug.c mc6809nc/mc6809_dis.c mc6809nc/mc6809_dis.h + cpu80186/cpu80186_debug.c + cpu80186/cpu80186_debug.h ) if( ${DEBUG} ) diff --git a/src/cpu80186/cpu80186.c b/src/cpu80186/cpu80186.c index 2435274b..3b46d8cb 100644 --- a/src/cpu80186/cpu80186.c +++ b/src/cpu80186/cpu80186.c @@ -42,6 +42,11 @@ #include "mem80186.h" #include "iop80186.h" +#ifdef INCLUDE_DEBUGGER +#include "cpu80186_debug.h" +#include "../cpu_debug.h" +#endif + uint64_t curtimer, lasttimer, timerfreq; uint8_t byteregtable[8] = @@ -95,6 +100,20 @@ void intcall86(uint8_t intnum); of = (temp16 >> 11) & 1; \ } +#ifdef INCLUDE_DEBUGGER +uint32_t getinstraddr86() { + return segbase(savecs) + saveip; +} + +uint16_t getflags86() { + return makeflagsword(); +} + +void putflags86(uint16_t value) { + decodeflagsword(value); +} +#endif + #ifdef TRACE_N extern int i386_dasm_one(); unsigned int trace_data[TRACE_N]; @@ -1520,6 +1539,14 @@ void exec86(uint32_t execloops) savecs = segregs[regcs]; saveip = ip; opcode = getmem8(segregs[regcs], ip); + +#ifdef INCLUDE_DEBUGGER + if (cpu80186_debug_enabled) + { + debug_preexec(&cpu80186_cpu_debug, segbase(savecs) + saveip); + } +#endif + #ifdef TRACE_N trace_instruction(savecs, saveip); #endif diff --git a/src/cpu80186/cpu80186.h b/src/cpu80186/cpu80186.h index b6a54112..c130a4ed 100644 --- a/src/cpu80186/cpu80186.h +++ b/src/cpu80186/cpu80186.h @@ -84,3 +84,10 @@ extern void intcall86(uint8_t intnum); extern uint8_t ifl; extern uint16_t ip; extern uint16_t segregs[]; + +#ifdef INCLUDE_DEBUGGER +extern union _bytewordregs_ regs; +extern uint32_t getinstraddr86(); +extern uint16_t getflags86(); +extern void putflags86(uint16_t value); +#endif diff --git a/src/cpu80186/cpu80186_debug.c b/src/cpu80186/cpu80186_debug.c new file mode 100644 index 00000000..89f18d36 --- /dev/null +++ b/src/cpu80186/cpu80186_debug.c @@ -0,0 +1,250 @@ +#include +#include +#include +#include + +#include "../cpu_debug.h" + +#include "cpu80186.h" +#include "mem80186.h" +#include "iop80186.h" +#include "cpu80186_debug.h" + +#define MAXOPLEN 6 + +extern int i386_dasm_one(); + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +int cpu80186_debug_enabled = 0; + +enum register_numbers { + i_IP, + i_FLAGS, + i_AX, + i_BX, + i_CX, + i_DX, + i_DI, + i_SI, + i_BP, + i_SP, + i_CS, + i_DS, + i_ES, + i_SS +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "IP", + "FLAGS", + "AX", + "BX", + "CX", + "DX", + "DI", + "SI", + "BP", + "SP", + "CS", + "DS", + "ES", + "SS", + NULL +}; + +// enable/disable debugging on this CPU, returns previous value. +static int dbg_debug_enable(int newvalue) { + int oldvalue = cpu80186_debug_enabled; + cpu80186_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_memread(uint32_t addr) { + return read86(addr); +}; + +// CPU's usual memory write function. +static void dbg_memwrite(uint32_t addr, uint32_t value) { + write86(addr, value); +}; + +// CPU's usual IO read function for data. +static uint32_t dbg_ioread(uint32_t addr) { + return portin(addr); +}; + +// CPU's usual IO write function. +static void dbg_iowrite(uint32_t addr, uint32_t value) { + portout(addr, value); +}; + +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + char instr[100]; + int oplen = i386_dasm_one(instr, addr, 0, 0) & 0xffff; + int len = snprintf(buf, bufsize, "%06"PRIx32" ", addr); + buf += len; + bufsize -= len; + for (int i = 0; i < MAXOPLEN; i++) { + if (i < oplen) { + len = snprintf(buf, bufsize, "%02x ", read86(addr + i)); + } else { + len = snprintf(buf, bufsize, " "); + } + buf += len; + bufsize -= len; + } + strncpy(buf, instr, bufsize); + return addr + oplen; +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + switch (which) { + case i_IP: + return ip; + case i_FLAGS: + return getflags86(); + case i_AX: + return getreg16(regax); + case i_BX: + return getreg16(regbx); + case i_CX: + return getreg16(regcx); + case i_DX: + return getreg16(regdx); + case i_DI: + return getreg16(regdi); + case i_SI: + return getreg16(regsi); + case i_BP: + return getreg16(regbp); + case i_SP: + return getreg16(regsp); + case i_CS: + return getsegreg(regcs); + case i_DS: + return getsegreg(regds); + case i_ES: + return getsegreg(reges); + case i_SS: + return getsegreg(regss); + } + return 0; +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + switch (which) { + case i_IP: + ip = value; + break; + case i_FLAGS: + putflags86(value); + break; + case i_AX: + putreg16(regax, value); + break; + case i_BX: + putreg16(regbx, value); + break; + case i_CX: + putreg16(regcx, value); + break; + case i_DX: + putreg16(regdx, value); + break; + case i_DI: + putreg16(regdi, value); + break; + case i_SI: + putreg16(regsi, value); + break; + case i_BP: + putreg16(regbp, value); + break; + case i_SP: + putreg16(regsp, value); + break; + case i_CS: + putsegreg(regcs, value); + break; + case i_DS: + putsegreg(regds, value); + break; + case i_ES: + putsegreg(reges, value); + break; + case i_SS: + putsegreg(regss, value); + break; + } +}; + +static const char* flagname = "O D I T S Z * A * P * C "; + +// Print register value in CPU standard form. +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + if (which == i_FLAGS) { + int i; + int bit; + char c; + const char *flagnameptr = flagname; + int psr = dbg_reg_get(which); + + if (bufsize < 40) { + strncpy(buf, "buffer too small!!!", bufsize); + } + + bit = 0x800; + for (i = 0; i < 12; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + 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 getinstraddr86(); +} + +cpu_debug_t cpu80186_cpu_debug = { + .cpu_name = "80x86", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .ioread = dbg_ioread, + .iowrite = dbg_iowrite, + .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 +}; diff --git a/src/cpu80186/cpu80186_debug.h b/src/cpu80186/cpu80186_debug.h new file mode 100644 index 00000000..62d21ef8 --- /dev/null +++ b/src/cpu80186/cpu80186_debug.h @@ -0,0 +1,6 @@ +#include "../cpu_debug.h" + +extern int cpu80186_debug_enabled; + +extern cpu_debug_t cpu80186_cpu_debug; + diff --git a/src/cpu80186/iop80186.c b/src/cpu80186/iop80186.c index 7953344e..9b5f02b8 100644 --- a/src/cpu80186/iop80186.c +++ b/src/cpu80186/iop80186.c @@ -28,6 +28,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "../copro-80186.h" #include "iop80186.h" +#ifdef INCLUDE_DEBUGGER +#include "../cpu_debug.h" +#include "cpu80186_debug.h" +#endif + #define TUBE_ACCESS(ADDRESS) (((ADDRESS) & 0xFFF1) == 0x0080) #define TUBE_CONVERT(PORT) ((PORT >> 1) & 0x0007) @@ -44,19 +49,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. void portout(uint16_t portnum, uint8_t value) { - if (TUBE_ACCESS(portnum)) - { +#ifdef INCLUDE_DEBUGGER + if (cpu80186_debug_enabled) { + debug_iowrite(&cpu80186_cpu_debug, portnum, value, 1); + } +#endif + if (TUBE_ACCESS(portnum)) { copro_80186_tube_write(TUBE_CONVERT(portnum), value); } } uint8_t portin(uint16_t portnum) { - if (TUBE_ACCESS(portnum)) - { - return copro_80186_tube_read(TUBE_CONVERT(portnum)); - } - return 0xFF; + uint8_t value; + if (TUBE_ACCESS(portnum)) { + value = copro_80186_tube_read(TUBE_CONVERT(portnum)); + } else { + value = 0xFF; + } +#ifdef INCLUDE_DEBUGGER + if (cpu80186_debug_enabled) { + debug_ioread(&cpu80186_cpu_debug, portnum, value, 1); + } +#endif + return value; } uint16_t portin16(uint16_t portnum) diff --git a/src/cpu80186/mem80186.c b/src/cpu80186/mem80186.c index 77f55e8f..c12884d9 100644 --- a/src/cpu80186/mem80186.c +++ b/src/cpu80186/mem80186.c @@ -28,6 +28,11 @@ #include "Client86_v1_01.h" #include "../tube-client.h" +#ifdef INCLUDE_DEBUGGER +#include "../cpu_debug.h" +#include "cpu80186_debug.h" +#endif + #ifdef DECLARE_RAM uint8_t* RAM;//[ONE_MEG]; #else @@ -37,6 +42,11 @@ uint8_t* RAM = (uint8_t*) m186_RamBase; void write86(uint32_t addr32, uint8_t value) { addr32 &= 0xFFFFFF; +#ifdef INCLUDE_DEBUGGER + if (cpu80186_debug_enabled) { + debug_memwrite(&cpu80186_cpu_debug, addr32, value, 1); + } +#endif if (addr32 < 0xF0000) { RAM[addr32] = value; } @@ -50,7 +60,13 @@ void writew86(uint32_t addr32, uint16_t value) uint8_t read86(uint32_t addr32) { - return (RAM[addr32 & 0xFFFFF]); + uint8_t value = RAM[addr32 & 0xFFFFF]; +#ifdef INCLUDE_DEBUGGER + if (cpu80186_debug_enabled) { + debug_memread(&cpu80186_cpu_debug, addr32, value, 1); + } +#endif + return value; } uint16_t readw86(uint32_t addr32) diff --git a/src/cpu_debug.h b/src/cpu_debug.h index 094b758a..19de302f 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -11,6 +11,8 @@ typedef struct { int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. uint32_t (*memread)(uint32_t addr); // CPU's usual memory read function for data. void (*memwrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. + uint32_t (*ioread)(uint32_t addr); // CPU's usual memory read function for data. + void (*iowrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. uint32_t (*disassemble)(uint32_t addr, char *buf, size_t bufsize); // disassemble one line, returns next address const char **reg_names; // NULL pointer terminated list of register names. uint32_t (*reg_get)(int which); // Get a register - which is the index into the names above @@ -23,6 +25,8 @@ typedef struct { extern void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); extern void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); +extern void debug_ioread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); +extern void debug_iowrite (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); extern void debug_preexec (cpu_debug_t *cpu, uint32_t addr); #endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index bac91f2b..5d9fd20c 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -9,12 +9,15 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" +#include "../cpu80186/cpu80186_debug.h" #include "../mc6809nc/mc6809_debug.h" #include "../mame/arm_debug.h" #include "../NS32016/32016_debug.h" #define USE_LINENOISE +#define HAS_IO (getCpu()->ioread != NULL) + static const char * prompt_str = ">> "; extern unsigned int copro; @@ -28,7 +31,7 @@ cpu_debug_t *cpu_debug_list[] = { NULL, // 5 Z80 NULL, // 4 Z80 NULL, // 7 Z80 - NULL, // 8 80x86 + &cpu80186_cpu_debug, // 8 80x86 &mc6809nc_cpu_debug, // 9 6809 NULL, // 10 unused NULL, // 11 unused @@ -39,6 +42,7 @@ cpu_debug_t *cpu_debug_list[] = { }; #define NUM_CMDS 19 +#define NUM_IO_CMDS 6 // The Atom CRC Polynomial #define CRC_POLY 0x002d @@ -71,9 +75,13 @@ typedef struct { static breakpoint_t exec_breakpoints[MAXBKPTS + 1]; static breakpoint_t mem_rd_breakpoints[MAXBKPTS + 1]; static breakpoint_t mem_wr_breakpoints[MAXBKPTS + 1]; +static breakpoint_t io_rd_breakpoints[MAXBKPTS + 1]; +static breakpoint_t io_wr_breakpoints[MAXBKPTS + 1]; static void doCmdBreakI(char *params); +static void doCmdBreakRdIO(char *params); static void doCmdBreakRdMem(char *params); +static void doCmdBreakWrIO(char *params); static void doCmdBreakWrMem(char *params); static void doCmdClear(char *params); static void doCmdContinue(char *params); @@ -83,21 +91,24 @@ static void doCmdFill(char *params); static void doCmdHelp(char *params); static void doCmdList(char *params); static void doCmdMem(char *params); +static void doCmdReadIO(char *params); static void doCmdReadMem(char *params); static void doCmdRegs(char *params); static void doCmdStep(char *params); static void doCmdTrace(char *params); static void doCmdWatchI(char *params); +static void doCmdWatchRdIO(char *params); static void doCmdWatchRdMem(char *params); +static void doCmdWatchWrIO(char *params); static void doCmdWatchWrMem(char *params); +static void doCmdWriteIO(char *params); static void doCmdWriteMem(char *params); - // The command process accepts abbreviated forms, for example // if h is entered, then help will match. // Must be kept in step with dbgCmdFuncs (just below) -static char *dbgCmdStrings[NUM_CMDS] = { +static char *dbgCmdStrings[NUM_CMDS + NUM_IO_CMDS] = { "help", "continue", "step", @@ -109,6 +120,7 @@ static char *dbgCmdStrings[NUM_CMDS] = { "rdm", "wrm", "trace", + "clear", "blist", "breakx", "watchx", @@ -116,11 +128,16 @@ static char *dbgCmdStrings[NUM_CMDS] = { "watchrm", "breakwm", "watchwm", - "clear" + "rdio", + "wrio", + "breakri", + "watchri", + "breakwi", + "watchwi", }; // Must be kept in step with dbgCmdStrings (just above) -static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { +static void (*dbgCmdFuncs[NUM_CMDS + NUM_IO_CMDS])(char *params) = { doCmdHelp, doCmdContinue, doCmdStep, @@ -132,6 +149,7 @@ static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { doCmdReadMem, doCmdWriteMem, doCmdTrace, + doCmdClear, doCmdList, doCmdBreakI, doCmdWatchI, @@ -139,7 +157,12 @@ static void (*dbgCmdFuncs[NUM_CMDS])(char *params) = { doCmdWatchRdMem, doCmdBreakWrMem, doCmdWatchWrMem, - doCmdClear + doCmdReadIO, + doCmdWriteIO, + doCmdBreakRdIO, + doCmdWatchRdIO, + doCmdBreakWrIO, + doCmdWatchWrIO }; @@ -186,6 +209,19 @@ static void memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { internal = 0; } +static uint32_t ioread(cpu_debug_t *cpu, uint32_t addr) { + internal = 1; + uint32_t result = cpu->ioread(addr); + internal = 0; + return result; +} + +static void iowrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value) { + internal = 1; + cpu->iowrite(addr, value); + internal = 0; +} + /******************************************************** * Hooks from CPU Emulation ********************************************************/ @@ -270,6 +306,18 @@ void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t siz } }; +void debug_ioread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { + if (!internal) { + generic_memory_access(cpu, addr, value, size, "IO Rd", io_rd_breakpoints); + } +}; + +void debug_iowrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size) { + if (!internal) { + generic_memory_access(cpu, addr, value, size, "IO Wr", io_wr_breakpoints); + } +}; + void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { int show = 0; @@ -368,7 +416,11 @@ static void doCmdHelp(char *params) { printf("PiTubeDirect debugger\r\n"); printf(" cpu = %s\r\n", cpu->cpu_name); printf("Commands:\r\n"); - for (i = 0; i < NUM_CMDS; i++) { + int n = NUM_CMDS; + if (HAS_IO) { + n += NUM_IO_CMDS; + } + for (i = 0; i < n; i++) { printf(" %s\r\n", dbgCmdStrings[i]); } } @@ -485,7 +537,7 @@ static void doCmdReadMem(char *params) { unsigned int data; sscanf(params, "%x", &addr); data = memread(cpu, addr); - printf("Rd: %x = %02x\r\n", addr, data); + printf("Rd Mem: %x = %02x\r\n", addr, data); } static void doCmdWriteMem(char *params) { @@ -493,10 +545,28 @@ static void doCmdWriteMem(char *params) { unsigned int addr; unsigned int data; sscanf(params, "%x %x", &addr, &data); - printf("Wr: %x = %02x\r\n", addr, data); + printf("Wr Mem: %x = %02x\r\n", addr, data); memwrite(cpu, addr++, data); } +static void doCmdReadIO(char *params) { + cpu_debug_t *cpu = getCpu(); + unsigned int addr; + unsigned int data; + sscanf(params, "%x", &addr); + data = ioread(cpu, addr); + printf("Rd IO: %x = %02x\r\n", addr, data); +} + +static void doCmdWriteIO(char *params) { + cpu_debug_t *cpu = getCpu(); + unsigned int addr; + unsigned int data; + sscanf(params, "%x %x", &addr, &data); + printf("Wr IO: %x = %02x\r\n", addr, data); + iowrite(cpu, addr++, data); +} + static void doCmdStep(char *params) { int i = 1; @@ -544,9 +614,13 @@ static void genericList(char *type, breakpoint_t *list) { } static void doCmdList(char *params) { - genericList("Exec", exec_breakpoints); - genericList("Mem Rd", mem_rd_breakpoints); - genericList("Mem Wr", mem_wr_breakpoints); + genericList("Exec", exec_breakpoints); + genericList("Mem Rd", mem_rd_breakpoints); + genericList("Mem Wr", mem_wr_breakpoints); + if (HAS_IO) { + genericList("IO Rd", io_rd_breakpoints); + genericList("IO Wr", io_wr_breakpoints); + } } static void doCmdBreakI(char *params) { @@ -573,6 +647,22 @@ static void doCmdWatchWrMem(char *params) { genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_WATCH); } +static void doCmdBreakRdIO(char *params) { + genericBreakpoint(params, "IO Rd", io_rd_breakpoints, MODE_BREAK); +} + +static void doCmdWatchRdIO(char *params) { + genericBreakpoint(params, "IO Rd", io_rd_breakpoints, MODE_WATCH); +} + +static void doCmdBreakWrIO(char *params) { + genericBreakpoint(params, "IO Wr", io_wr_breakpoints, MODE_BREAK); +} + +static void doCmdWatchWrIO(char *params) { + genericBreakpoint(params, "IO Wr", io_wr_breakpoints, MODE_WATCH); +} + int genericClear(uint32_t addr, char *type, breakpoint_t *list) { @@ -612,6 +702,10 @@ static void doCmdClear(char *params) { found |= genericClear(addr, "Exec", exec_breakpoints); found |= genericClear(addr, "Mem Rd", mem_rd_breakpoints); found |= genericClear(addr, "Mem Wr", mem_wr_breakpoints); + if (HAS_IO) { + found |= genericClear(addr, "IO Rd", io_rd_breakpoints); + found |= genericClear(addr, "IO Wr", io_wr_breakpoints); + } if (!found) { printf("No breakpoints set at %x\r\n", addr); } @@ -639,6 +733,14 @@ static void updateDebugFlag() { if (mem_wr_breakpoints[0].mode != MODE_LAST) { enable = 1; } + if (HAS_IO) { + if (io_rd_breakpoints[0].mode != MODE_LAST) { + enable = 1; + } + if (io_wr_breakpoints[0].mode != MODE_LAST) { + enable = 1; + } + } if (cpu->debug_enable(enable) != enable) { printf("cpu: %s debug enable = %d\r\n", cpu->cpu_name, enable); } @@ -657,7 +759,11 @@ static void dispatchCmd(char *cmd) { while (cmd[cmdLen] >= 'a' && cmd[cmdLen] <= 'z') { cmdLen++; } - for (i = 0; i < NUM_CMDS; i++) { + int n = NUM_CMDS; + if (HAS_IO) { + n += NUM_IO_CMDS; + } + for (i = 0; i < n; i++) { cmdString = dbgCmdStrings[i]; cmdStringLen = strlen(cmdString); minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen; From d8521a25d523b1a4f15b526454a75717b52457d3 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 25 Mar 2017 21:25:17 +0000 Subject: [PATCH 086/149] Simplify copro reset code ( remove the need fro last_rst) --- src/copro-32016.c | 22 +++++++++------------- src/copro-80186.c | 8 ++------ src/copro-arm2.c | 6 +----- src/copro-lib6502.c | 8 ++------ src/copro-mc6809nc.c | 7 ++----- src/copro-z80.c | 21 ++++++--------------- 6 files changed, 22 insertions(+), 50 deletions(-) diff --git a/src/copro-32016.c b/src/copro-32016.c index 5815308f..6832c9a6 100644 --- a/src/copro-32016.c +++ b/src/copro-32016.c @@ -35,8 +35,6 @@ static void copro_32016_reset() { } void copro_32016_emulator() { - unsigned int last_rst = 0; - unsigned int rst; // Remember the current copro so we can exit if it changes int last_copro = copro; @@ -49,20 +47,18 @@ void copro_32016_emulator() { // might need to reduce if we see LATEs tubecycles = 8; n32016_exec(); - rst = tube_irq & RESET_BIT ; - if (rst) { + + if (tube_irq & RESET_BIT ) { // Reset the processor on active edge of rst - if (!last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - break; - } - copro_32016_reset(); + // Exit if the copro has changed + if (copro != last_copro) { + break; } - // NMI is edge sensitive, so only check after mailbox activity - // Note: 32016 uses tube_irq directly, so no nmi code here + copro_32016_reset(); } - last_rst = rst; + // NMI is edge sensitive, so only check after mailbox activity + // Note: 32016 uses tube_irq directly, so no nmi code here + // IRQ is level sensitive, so check between every instruction // Note: 32016 uses tube_irq directly, so no irq code here } diff --git a/src/copro-80186.c b/src/copro-80186.c index 3341a01f..bd48fe3f 100644 --- a/src/copro-80186.c +++ b/src/copro-80186.c @@ -35,7 +35,6 @@ void copro_80186_tube_write(uint16_t addr, uint8_t data) { void copro_80186_emulator() { - unsigned int last_rst = 0; unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes @@ -50,15 +49,14 @@ void copro_80186_emulator() 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) && !last_rst) { + if (tube_irq_copy & RESET_BIT) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_80186_reset(); } - last_rst = (tube_irq_copy & RESET_BIT); - + // NMI is edge sensitive, so only check after mailbox activity if (tube_irq_copy & NMI_BIT) { intcall86(2); @@ -71,8 +69,6 @@ void copro_80186_emulator() intcall86(12); } } - } else { - last_rst = 0; } } } diff --git a/src/copro-arm2.c b/src/copro-arm2.c index e92895b5..83d8a4ae 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -162,7 +162,6 @@ static void copro_arm2_reset() void copro_arm2_emulator() { - unsigned int last_rst = 0; unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes @@ -177,14 +176,13 @@ void copro_arm2_emulator() 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) && !last_rst) { + if ( tube_irq_copy & RESET_BIT ) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_arm2_reset(); } - last_rst = (tube_irq_copy & RESET_BIT); // NMI is edge sensitive, so only check after mailbox activity if (tube_irq_copy & NMI_BIT) { @@ -194,8 +192,6 @@ void copro_arm2_emulator() // IRQ is level sensitive, so check between every instruction arm2_execute_set_input(ARM_IRQ_LINE, tube_irq_copy & IRQ_BIT); - } else { - last_rst = 0; } } } diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index 9e2596c5..73d385fb 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -54,20 +54,18 @@ static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { static int last_copro; static int copro_lib6502_poll(M6502 *mpu) { - static unsigned int last_rst = 0; unsigned int tube_irq_copy; tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT ); if (tube_irq_copy) { // Reset the processor on a rst going inactive - if ( ( tube_irq_copy & RESET_BIT ) && !last_rst) { + if ( tube_irq_copy & RESET_BIT ) { // Exit if the copro has changed if (copro != last_copro) { return 1; } copro_lib6502_reset(mpu); } - last_rst = ( tube_irq_copy & RESET_BIT ); - + // NMI is edge sensitive, so only check after mailbox activity if ( tube_irq_copy & NMI_BIT) { M6502_nmi(mpu); @@ -80,8 +78,6 @@ static int copro_lib6502_poll(M6502 *mpu) { M6502_irq(mpu); } } - } else { - last_rst = 0; } return 0; } diff --git a/src/copro-mc6809nc.c b/src/copro-mc6809nc.c index bff297ca..bdb575b1 100644 --- a/src/copro-mc6809nc.c +++ b/src/copro-mc6809nc.c @@ -85,7 +85,6 @@ static void copro_mc6809_reset() { void copro_mc6809nc_emulator() { - unsigned int last_rst = 0; unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes @@ -101,14 +100,14 @@ void copro_mc6809nc_emulator() 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 ) && !last_rst) { + if ( tube_irq_copy & RESET_BIT ) { // Exit if the copro has changed if (copro != last_copro) { break; } copro_mc6809_reset(); } - last_rst = tube_irq_copy & RESET_BIT ; + // NMI is edge sensitive, so only check after mailbox activity if ( tube_irq_copy & NMI_BIT ) { mc6809nc_request_irq(1); @@ -119,8 +118,6 @@ void copro_mc6809nc_emulator() if ( tube_irq_copy & IRQ_BIT ) { mc6809nc_request_firq(1); } - } else { - last_rst = 0; } } } diff --git a/src/copro-z80.c b/src/copro-z80.c index bf94973c..2a8779de 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -325,7 +325,6 @@ static void copro_z80_reset() { void copro_z80_emulator() { - unsigned int last_rst = 0; unsigned int tube_irq_copy; // Remember the current copro so we can exit if it changes @@ -340,25 +339,19 @@ void copro_z80_emulator() simz80_execute(1); 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) { - if (!last_rst) { - // Exit if the copro has changed - if (copro != last_copro) { - break; - } - copro_z80_reset(); - last_rst = 1; + // Exit if the copro has changed + if (copro != last_copro) { + break; } - } else { - last_rst = 0; + copro_z80_reset(); } // NMI is edge sensitive, if (tube_irq_copy & NMI_BIT) { overlay_rom = 1; - simz80_NMI(); + simz80_NMI(); tube_ack_nmi(); } @@ -368,9 +361,7 @@ void copro_z80_emulator() if (simz80_is_IRQ_enabled()) { simz80_IRQ(); } - } - } else { - last_rst = 0; + } } } } From 8c16308b905db5e6b663386f0da2e6eee6276a38 Mon Sep 17 00:00:00 2001 From: David Banks Date: Mon, 27 Mar 2017 18:44:47 +0100 Subject: [PATCH 087/149] Lib6502: Added debugger support (needs more work) Change-Id: Ie0b2ea2e54d40cd2210a63eb2adcf525ccb40fec --- src/CMakeLists.txt | 2 + src/copro-lib6502.c | 56 ++++++++++- src/copro-lib6502.h | 7 ++ src/debugger/debugger.c | 5 +- src/lib6502.c | 2 - src/lib6502_debug.c | 180 ++++++++++++++++++++++++++++++++++++ src/lib6502_debug.h | 6 ++ src/mc6809nc/mc6809_debug.c | 2 - 8 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 src/lib6502_debug.c create mode 100644 src/lib6502_debug.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69008a8e..a4297f61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -229,6 +229,8 @@ file( GLOB debugger_files debugger/linenoise.c debugger/linenoise.h cpu_debug.h + lib6502_debug.c + lib6502_debug.h NS32016/32016_debug.c NS32016/32016_debug.h mame/arm_debug.c diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index 73d385fb..182ffb00 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -20,7 +20,12 @@ #include "copro-lib6502.h" #include "startup.h" -const int tracing=0; +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#include "lib6502_debug.h" +#endif + +M6502 *copro_lib6502_mpu; static void copro_lib6502_poweron_reset(M6502 *mpu) { // Wipe memory @@ -42,6 +47,35 @@ static void copro_lib6502_reset(M6502 *mpu) { tube_reset_performance_counters(); } + +#ifdef INCLUDE_DEBUGGER + +int copro_lib6502_mem_read(M6502 *mpu, uint16_t addr, uint8_t data) { + if ((addr & 0xfff8) == 0xfef8) { + data = tube_parasite_read(addr); + } else { + data = mpu->memory[addr]; + } + if (lib6502_debug_enabled) { + debug_memread(&lib6502_cpu_debug, addr, data, 1); + } + return data; +} + +int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data) { + if (lib6502_debug_enabled) { + debug_memwrite(&lib6502_cpu_debug, addr, data, 1); + } + if ((addr & 0xfff8) == 0xfef8) { + tube_parasite_write(addr, data); + } else { + mpu->memory[addr] = data;; + } + return 0; +} + +#else + static int copro_lib6502_tube_read(M6502 *mpu, uint16_t addr, uint8_t data) { return tube_parasite_read(addr); } @@ -51,9 +85,16 @@ static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { return 0; } +#endif + static int last_copro; static int copro_lib6502_poll(M6502 *mpu) { +#ifdef INCLUDE_DEBUGGER + if (lib6502_debug_enabled) { + debug_preexec(&lib6502_cpu_debug, mpu->registers->pc); + } +#endif unsigned int tube_irq_copy; tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT ); if (tube_irq_copy) { @@ -83,17 +124,26 @@ static int copro_lib6502_poll(M6502 *mpu) { } void copro_lib6502_emulator() { - uint16_t addr; + uint32_t addr; // Remember the current copro so we can exit if it changes last_copro = copro; - M6502 *mpu= M6502_new(0, 0, 0); + M6502 *mpu = M6502_new(0, 0, 0); + copro_lib6502_mpu = mpu; + +#ifdef INCLUDE_DEBUGGER + for (addr= 0x0000; addr <= 0xffff; addr++) { + M6502_setCallback(mpu, read, addr, copro_lib6502_mem_read); + M6502_setCallback(mpu, write, addr, copro_lib6502_mem_write); + } +#else for (addr= 0xfef8; addr <= 0xfeff; addr++) { M6502_setCallback(mpu, read, addr, copro_lib6502_tube_read); M6502_setCallback(mpu, write, addr, copro_lib6502_tube_write); } +#endif copro_lib6502_poweron_reset(mpu); copro_lib6502_reset(mpu); diff --git a/src/copro-lib6502.h b/src/copro-lib6502.h index 9d533d05..c3e77f1d 100644 --- a/src/copro-lib6502.h +++ b/src/copro-lib6502.h @@ -2,6 +2,13 @@ #ifndef COPRO_LIB6502_H #define COPRO_LIB6502_H +#ifdef INCLUDE_DEBUGGER +#include "lib6502.h" +extern M6502 *copro_lib6502_mpu; +extern int copro_lib6502_mem_read(M6502 *mpu, uint16_t addr, uint8_t data); +extern int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data); +#endif + extern void copro_lib6502_emulator(); #endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 5d9fd20c..efe7f786 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -9,6 +9,7 @@ #include "../rpi-aux.h" #include "../cpu_debug.h" +#include "../lib6502_debug.h" #include "../cpu80186/cpu80186_debug.h" #include "../mc6809nc/mc6809_debug.h" #include "../mame/arm_debug.h" @@ -25,8 +26,8 @@ extern unsigned int copro; cpu_debug_t *cpu_debug_list[] = { NULL, // 0 65tube NULL, // 1 65tube - NULL, // 2 lib6502 - NULL, // 3 lib6502 + &lib6502_cpu_debug, // 2 lib6502 + &lib6502_cpu_debug, // 3 lib6502 NULL, // 4 Z80 NULL, // 5 Z80 NULL, // 4 Z80 diff --git a/src/lib6502.c b/src/lib6502.c index 0db21924..c4f6ce78 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -37,8 +37,6 @@ typedef uint8_t byte; typedef uint16_t word; -extern int tracing; - enum { flagN= (1<<7), /* negative */ flagV= (1<<6), /* overflow */ diff --git a/src/lib6502_debug.c b/src/lib6502_debug.c new file mode 100644 index 00000000..eff36674 --- /dev/null +++ b/src/lib6502_debug.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include + +#include "../cpu_debug.h" + +#include "copro-lib6502.h" +#include "lib6502.h" +#include "lib6502_debug.h" + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +int lib6502_debug_enabled = 0; + +enum register_numbers { + i_A, + i_X, + i_Y, + i_P, + i_S, + i_PC +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "A", + "X", + "Y", + "P", + "S", + "PC", + NULL +}; + +// enable/disable debugging on this CPU, returns previous value. +static int dbg_debug_enable(int newvalue) { + int oldvalue = lib6502_debug_enabled; + lib6502_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_memread(uint32_t addr) { + return copro_lib6502_mem_read(copro_lib6502_mpu, addr, 0); +}; + +// CPU's usual memory write function. +static void dbg_memwrite(uint32_t addr, uint32_t value) { + copro_lib6502_mem_write(copro_lib6502_mpu, addr, value); +}; + +static uint32_t dbg_disassemble(uint32_t addr, char *buf, size_t bufsize) { + char instr[64]; + int oplen = M6502_disassemble(copro_lib6502_mpu, addr, instr); + int len = snprintf(buf, bufsize, "%04"PRIx32" ", addr); + buf += len; + bufsize -= len; + for (int i = 0; i < 3; i++) { + if (i < oplen) { + len = snprintf(buf, bufsize, "%02"PRIx32" ", dbg_memread(addr + i)); + } else { + len = snprintf(buf, bufsize, " "); + } + buf += len; + bufsize -= len; + } + strncpy(buf, instr, bufsize); + return addr + oplen; +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + switch (which) { + case i_A: + return copro_lib6502_mpu->registers->a; + case i_X: + return copro_lib6502_mpu->registers->x; + case i_Y: + return copro_lib6502_mpu->registers->y; + case i_P: + return copro_lib6502_mpu->registers->p; + case i_S: + return copro_lib6502_mpu->registers->s; + case i_PC: + return copro_lib6502_mpu->registers->pc; + default: + return 0; + } +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + switch (which) { + case i_A: + copro_lib6502_mpu->registers->a = value; + break; + case i_X: + copro_lib6502_mpu->registers->x = value; + break; + case i_Y: + copro_lib6502_mpu->registers->y = value; + break; + case i_P: + copro_lib6502_mpu->registers->p = value; + break; + case i_S: + copro_lib6502_mpu->registers->s = value; + break; + case i_PC: + copro_lib6502_mpu->registers->pc = value; + break; + } +}; + +static const char* flagname = "N V * B D I Z C "; + +// Print register value in CPU standard form. +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + if (which == i_P) { + int i; + int bit; + char c; + const char *flagnameptr = flagname; + int psr = dbg_reg_get(which); + + if (bufsize < 40) { + strncpy(buf, "buffer too small!!!", bufsize); + } + + bit = 0x80; + for (i = 0; i < 8; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + return strlen(buf); + } else if (which == i_PC) { + return snprintf(buf, bufsize, "%04"PRIx32, dbg_reg_get(which)); + } else { + return snprintf(buf, bufsize, "%02"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 copro_lib6502_mpu->registers->pc; +} + +cpu_debug_t lib6502_cpu_debug = { + .cpu_name = "lib6502", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .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 +}; diff --git a/src/lib6502_debug.h b/src/lib6502_debug.h new file mode 100644 index 00000000..96c3ea08 --- /dev/null +++ b/src/lib6502_debug.h @@ -0,0 +1,6 @@ +#include "cpu_debug.h" + +extern int lib6502_debug_enabled; + +extern cpu_debug_t lib6502_cpu_debug; + diff --git a/src/mc6809nc/mc6809_debug.c b/src/mc6809nc/mc6809_debug.c index 55dc0c28..eb0503ba 100644 --- a/src/mc6809nc/mc6809_debug.c +++ b/src/mc6809nc/mc6809_debug.c @@ -52,13 +52,11 @@ static int dbg_debug_enable(int newvalue) { // CPU's usual memory read function for data. static uint32_t dbg_memread(uint32_t addr) { - // TODO: use the internal version so the debugger doesn't get notified return read8(addr); }; // CPU's usual memory write function. static void dbg_memwrite(uint32_t addr, uint32_t value) { - // TODO: use the internal version so the debugger doesn't get notified write8(addr, value); }; From 0a2916640d8337546f88fc64e129a95b0146de6a Mon Sep 17 00:00:00 2001 From: David Banks Date: Mon, 27 Mar 2017 18:54:33 +0100 Subject: [PATCH 088/149] Debugger: renamed some commands Change-Id: I0842afda56b6e3e2c4d72c5ae84f0b53c0a8174c --- src/debugger/debugger.c | 114 ++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index efe7f786..7bfc1565 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -79,31 +79,31 @@ static breakpoint_t mem_wr_breakpoints[MAXBKPTS + 1]; static breakpoint_t io_rd_breakpoints[MAXBKPTS + 1]; static breakpoint_t io_wr_breakpoints[MAXBKPTS + 1]; -static void doCmdBreakI(char *params); -static void doCmdBreakRdIO(char *params); -static void doCmdBreakRdMem(char *params); -static void doCmdBreakWrIO(char *params); -static void doCmdBreakWrMem(char *params); +static void doCmdBreak(char *params); +static void doCmdBreakIn(char *params); +static void doCmdBreakOut(char *params); +static void doCmdBreakRd(char *params); +static void doCmdBreakWr(char *params); static void doCmdClear(char *params); static void doCmdContinue(char *params); static void doCmdCrc(char *params); static void doCmdDis(char *params); static void doCmdFill(char *params); static void doCmdHelp(char *params); +static void doCmdIn(char *params); static void doCmdList(char *params); static void doCmdMem(char *params); -static void doCmdReadIO(char *params); -static void doCmdReadMem(char *params); +static void doCmdOut(char *params); +static void doCmdRd(char *params); static void doCmdRegs(char *params); static void doCmdStep(char *params); static void doCmdTrace(char *params); -static void doCmdWatchI(char *params); -static void doCmdWatchRdIO(char *params); -static void doCmdWatchRdMem(char *params); -static void doCmdWatchWrIO(char *params); -static void doCmdWatchWrMem(char *params); -static void doCmdWriteIO(char *params); -static void doCmdWriteMem(char *params); +static void doCmdWatch(char *params); +static void doCmdWatchIn(char *params); +static void doCmdWatchOut(char *params); +static void doCmdWatchRd(char *params); +static void doCmdWatchWr(char *params); +static void doCmdWr(char *params); // The command process accepts abbreviated forms, for example // if h is entered, then help will match. @@ -118,23 +118,23 @@ static char *dbgCmdStrings[NUM_CMDS + NUM_IO_CMDS] = { "fill", "crc", "mem", - "rdm", - "wrm", + "rd", + "wr", "trace", "clear", - "blist", - "breakx", - "watchx", - "breakrm", - "watchrm", - "breakwm", - "watchwm", - "rdio", - "wrio", - "breakri", - "watchri", - "breakwi", - "watchwi", + "list", + "break", + "watch", + "breakr", + "watchr", + "breakw", + "watchw", + "in", + "out", + "breaki", + "watchi", + "breako", + "watcho", }; // Must be kept in step with dbgCmdStrings (just above) @@ -147,23 +147,23 @@ static void (*dbgCmdFuncs[NUM_CMDS + NUM_IO_CMDS])(char *params) = { doCmdFill, doCmdCrc, doCmdMem, - doCmdReadMem, - doCmdWriteMem, + doCmdRd, + doCmdWr, doCmdTrace, doCmdClear, doCmdList, - doCmdBreakI, - doCmdWatchI, - doCmdBreakRdMem, - doCmdWatchRdMem, - doCmdBreakWrMem, - doCmdWatchWrMem, - doCmdReadIO, - doCmdWriteIO, - doCmdBreakRdIO, - doCmdWatchRdIO, - doCmdBreakWrIO, - doCmdWatchWrIO + doCmdBreak, + doCmdWatch, + doCmdBreakRd, + doCmdWatchRd, + doCmdBreakWr, + doCmdWatchWr, + doCmdIn, + doCmdOut, + doCmdBreakIn, + doCmdWatchIn, + doCmdBreakOut, + doCmdWatchOut }; @@ -532,7 +532,7 @@ static void doCmdMem(char *params) { memAddr += 0x100; } -static void doCmdReadMem(char *params) { +static void doCmdRd(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -541,7 +541,7 @@ static void doCmdReadMem(char *params) { printf("Rd Mem: %x = %02x\r\n", addr, data); } -static void doCmdWriteMem(char *params) { +static void doCmdWr(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -550,7 +550,7 @@ static void doCmdWriteMem(char *params) { memwrite(cpu, addr++, data); } -static void doCmdReadIO(char *params) { +static void doCmdIn(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -559,7 +559,7 @@ static void doCmdReadIO(char *params) { printf("Rd IO: %x = %02x\r\n", addr, data); } -static void doCmdWriteIO(char *params) { +static void doCmdOut(char *params) { cpu_debug_t *cpu = getCpu(); unsigned int addr; unsigned int data; @@ -624,43 +624,43 @@ static void doCmdList(char *params) { } } -static void doCmdBreakI(char *params) { +static void doCmdBreak(char *params) { genericBreakpoint(params, "Exec", exec_breakpoints, MODE_BREAK); } -static void doCmdWatchI(char *params) { +static void doCmdWatch(char *params) { genericBreakpoint(params, "Exec", exec_breakpoints, MODE_WATCH); } -static void doCmdBreakRdMem(char *params) { +static void doCmdBreakRd(char *params) { genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_BREAK); } -static void doCmdWatchRdMem(char *params) { +static void doCmdWatchRd(char *params) { genericBreakpoint(params, "Mem Rd", mem_rd_breakpoints, MODE_WATCH); } -static void doCmdBreakWrMem(char *params) { +static void doCmdBreakWr(char *params) { genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_BREAK); } -static void doCmdWatchWrMem(char *params) { +static void doCmdWatchWr(char *params) { genericBreakpoint(params, "Mem Wr", mem_wr_breakpoints, MODE_WATCH); } -static void doCmdBreakRdIO(char *params) { +static void doCmdBreakIn(char *params) { genericBreakpoint(params, "IO Rd", io_rd_breakpoints, MODE_BREAK); } -static void doCmdWatchRdIO(char *params) { +static void doCmdWatchIn(char *params) { genericBreakpoint(params, "IO Rd", io_rd_breakpoints, MODE_WATCH); } -static void doCmdBreakWrIO(char *params) { +static void doCmdBreakOut(char *params) { genericBreakpoint(params, "IO Wr", io_wr_breakpoints, MODE_BREAK); } -static void doCmdWatchWrIO(char *params) { +static void doCmdWatchOut(char *params) { genericBreakpoint(params, "IO Wr", io_wr_breakpoints, MODE_WATCH); } From e91bddef77c27e5372e8d79e08deb3b897dd945a Mon Sep 17 00:00:00 2001 From: David Banks Date: Tue, 28 Mar 2017 18:19:12 +0100 Subject: [PATCH 089/149] 32016 Co Pro: Fixed typo in debugger callback Change-Id: Ie831fc2d6e2127e2524eeb889a2190e7cd1fa913 --- src/NS32016/mem32016.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 42471344..c761b86c 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -165,7 +165,7 @@ uint32_t read_x32(uint32_t addr) #ifdef INCLUDE_DEBUGGER if (n32016_debug_enabled) { - debug_memread(&n32016_cpu_debug, addr, val, 3); + debug_memread(&n32016_cpu_debug, addr, val, 4); } #endif return val; From 49e9633456c800cdf8acb26453b6466e3cffcc6d Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 29 Mar 2017 21:38:50 +0100 Subject: [PATCH 090/149] Change to polling tube_irq each cycle instead of running for a number of cycles --- src/tube.h | 16 ++++++++++++++++ src/yaze/simz80.c | 8 +++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/tube.h b/src/tube.h index e644cc43..dca0bcf4 100644 --- a/src/tube.h +++ b/src/tube.h @@ -4,6 +4,7 @@ #define TUBE_H #include +#include "tube-defs.h" extern volatile unsigned int copro; @@ -13,4 +14,19 @@ extern int arm_speed; extern void arm_fiq_handler_flag1(); +extern volatile int tube_irq; + +#define tubeContinueRunning() (!(tube_irq & (RESET_BIT | NMI_BIT | IRQ_BIT))) + +#define tubeUseCycles(n) + +// In B-Em use the following +// +//#define tubeContinueRunning() (tube_cycles) +// +//#define tubeUseCycles(n) tubecycles -= n +// +//} + + #endif diff --git a/src/yaze/simz80.c b/src/yaze/simz80.c index 43f7ac71..6463a76f 100644 --- a/src/yaze/simz80.c +++ b/src/yaze/simz80.c @@ -40,6 +40,7 @@ static char *perl_params = */ #include "mem_mmu.h" #include "simz80.h" +#include "../tube.h" /* Z80 registers */ static WORD af[2]; /* accumulator and flags (2 banks) */ @@ -140,7 +141,7 @@ static const unsigned char partab[256] = { sp = SP FASTWORK -simz80_execute(int n) +simz80_execute(int tube_cycles) { FASTREG PC = pc; FASTREG AF = af[af_sel]; @@ -156,7 +157,7 @@ simz80_execute(int n) FASTREG tmp2; #endif - while (n--) { + do { switch(GetBYTE_pp(PC)) { case 0x00: /* NOP */ break; @@ -3096,7 +3097,8 @@ simz80_execute(int n) case 0xFF: /* RST 38H */ PUSH(PC); PC = 0x38; } - } + tubeUseCycles(1); + } while (tubeContinueRunning()); /* make registers visible for debugging if interrupted */ SAVE_STATE(); return (PC&0xffff)|0x10000; /* flag non-bios stop */ From 0e26fef9021414608e572b61bb899e008d4f1589 Mon Sep 17 00:00:00 2001 From: dp111 Date: Wed, 29 Mar 2017 22:39:03 +0100 Subject: [PATCH 091/149] Change to polling tube_irq instead of executing n cycles --- src/copro-arm2.c | 2 +- src/cpu80186/cpu80186.c | 9 +++++---- src/mame/arm.c | 8 +++++--- src/tube.h | 4 +++- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/copro-arm2.c b/src/copro-arm2.c index b085934e..247bfa05 100644 --- a/src/copro-arm2.c +++ b/src/copro-arm2.c @@ -224,6 +224,6 @@ void copro_arm2_emulator() { arm2_execute_set_input(ARM_IRQ_LINE, tube_irq_copy & IRQ_BIT); } // IRQ is level sensitive, so check between every instruction - arm2_execute_set_input(ARM_IRQ_LINE, tube_irq & 1); + // arm2_execute_set_input(ARM_IRQ_LINE, tube_irq & 1); } } diff --git a/src/cpu80186/cpu80186.c b/src/cpu80186/cpu80186.c index 3b46d8cb..472489ef 100644 --- a/src/cpu80186/cpu80186.c +++ b/src/cpu80186/cpu80186.c @@ -41,6 +41,7 @@ #include "cpu80186.h" #include "mem80186.h" #include "iop80186.h" +#include "../tube.h" #ifdef INCLUDE_DEBUGGER #include "cpu80186_debug.h" @@ -1491,7 +1492,7 @@ void reset(void) segregs[regcs] = 0xF000; } -void exec86(uint32_t execloops) +void exec86(uint32_t tube_cycles) { uint8_t docontinue; static uint16_t firstip; @@ -1507,8 +1508,7 @@ void exec86(uint32_t execloops) } #endif - while (execloops--) - { + do { if (trap_toggle) { intcall86(1); @@ -3802,5 +3802,6 @@ void exec86(uint32_t execloops) } break; } - } + tubeUseCycles(1); + }while (tubeContinueRunning()); } diff --git a/src/mame/arm.c b/src/mame/arm.c index ded10f52..01fae90d 100644 --- a/src/mame/arm.c +++ b/src/mame/arm.c @@ -20,6 +20,7 @@ #include #include #include "arm.h" +#include "../tube.h" // #define TRACE 1 @@ -268,7 +269,7 @@ void arm2_device_reset() #endif } -void arm2_execute_run(int number) +void arm2_execute_run(int tube_cycles) { #ifdef TRACE int i; @@ -424,9 +425,10 @@ void arm2_execute_run(int number) //arm2_check_irq_state(); - } + tubeUseCycles(1); + } while (tubeContinueRunning()); //while( m_icount > 0 ); - while (number--); + //while (number--); } /* arm_execute */ void arm2_check_irq_state() diff --git a/src/tube.h b/src/tube.h index dca0bcf4..917833a0 100644 --- a/src/tube.h +++ b/src/tube.h @@ -16,6 +16,8 @@ extern void arm_fiq_handler_flag1(); extern volatile int tube_irq; +// For Pi Direct we can just execute cycles until and event + #define tubeContinueRunning() (!(tube_irq & (RESET_BIT | NMI_BIT | IRQ_BIT))) #define tubeUseCycles(n) @@ -24,7 +26,7 @@ extern volatile int tube_irq; // //#define tubeContinueRunning() (tube_cycles) // -//#define tubeUseCycles(n) tubecycles -= n +//#define tubeUseCycles(n) tube_cycles -= n // //} From d5dd20736e2680279d4dfcb2c04befbb6ffb2c90 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 17:41:06 +0100 Subject: [PATCH 092/149] Updated release name to Cobra-dev Change-Id: I25ab7e8d0b85f05905de510dc85bf15b0ef1e0c0 --- src/tube-defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube-defs.h b/src/tube-defs.h index a8d70ce5..af73c268 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -3,7 +3,7 @@ #ifndef TUBE_DEFS_H #define TUBE_DEFS_H -#define RELEASENAME "Boa" +#define RELEASENAME "Cobra-dev" #define NDEBUG From 22651b46d66a3a70bd97be31c2cf114f379875fc Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 17:41:43 +0100 Subject: [PATCH 093/149] Debugger: A few more small bug fixes Change-Id: I2bee4690d33eb2d2a604f41d24a038328eaf1dac --- src/debugger/debugger.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 7bfc1565..35cc4476 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -123,8 +123,8 @@ static char *dbgCmdStrings[NUM_CMDS + NUM_IO_CMDS] = { "trace", "clear", "list", - "break", - "watch", + "breakx", + "watchx", "breakr", "watchr", "breakw", @@ -291,7 +291,7 @@ static inline void generic_memory_access(cpu_debug_t *cpu, uint32_t addr, uint32 printf("%s watchpoint hit at %"PRIx32" : %"PRIx32" = %"PRIx32"\r\n", type, pc, addr, value); prompt(); } - prompt(); + while (stopped); } } @@ -431,7 +431,7 @@ static void doCmdRegs(char *params) { const char **reg = cpu->reg_names; char name[100]; char value[100]; - int num_params = sscanf(params, "%s %s", name, value); + int num_params = sscanf(params, "%100s %100s", name, value); if (num_params > 0) { int i = 0; while (*reg) { @@ -448,7 +448,7 @@ static void doCmdRegs(char *params) { reg++; i++; } - printf("Register %s does not exist in the %s\r\n", strbuf, cpu->cpu_name); + printf("Register %s does not exist in the %s\r\n", name, cpu->cpu_name); } else { int i = 0; while (*reg) { From f07a218e38ce329b93f192205df70a7c48561ca8 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 17:42:48 +0100 Subject: [PATCH 094/149] lib6502 Co Pro - read/write breakpoints correctly implemented Change-Id: Ibb8104d1bb67b07d4e5bcaa3c3e281afa64ddd76 --- src/copro-lib6502.c | 22 +----------------- src/lib6502.c | 54 ++++++++++++++++++++++++++++++++++++++++----- src/lib6502_debug.c | 4 +++- src/lib6502_debug.h | 2 ++ 4 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/copro-lib6502.c b/src/copro-lib6502.c index 182ffb00..e0a6cdcd 100644 --- a/src/copro-lib6502.c +++ b/src/copro-lib6502.c @@ -56,16 +56,10 @@ int copro_lib6502_mem_read(M6502 *mpu, uint16_t addr, uint8_t data) { } else { data = mpu->memory[addr]; } - if (lib6502_debug_enabled) { - debug_memread(&lib6502_cpu_debug, addr, data, 1); - } return data; } int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data) { - if (lib6502_debug_enabled) { - debug_memwrite(&lib6502_cpu_debug, addr, data, 1); - } if ((addr & 0xfff8) == 0xfef8) { tube_parasite_write(addr, data); } else { @@ -74,7 +68,7 @@ int copro_lib6502_mem_write(M6502 *mpu, uint16_t addr, uint8_t data) { return 0; } -#else +#endif static int copro_lib6502_tube_read(M6502 *mpu, uint16_t addr, uint8_t data) { return tube_parasite_read(addr); @@ -85,16 +79,9 @@ static int copro_lib6502_tube_write(M6502 *mpu, uint16_t addr, uint8_t data) { return 0; } -#endif - static int last_copro; static int copro_lib6502_poll(M6502 *mpu) { -#ifdef INCLUDE_DEBUGGER - if (lib6502_debug_enabled) { - debug_preexec(&lib6502_cpu_debug, mpu->registers->pc); - } -#endif unsigned int tube_irq_copy; tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT ); if (tube_irq_copy) { @@ -133,17 +120,10 @@ void copro_lib6502_emulator() { copro_lib6502_mpu = mpu; -#ifdef INCLUDE_DEBUGGER - for (addr= 0x0000; addr <= 0xffff; addr++) { - M6502_setCallback(mpu, read, addr, copro_lib6502_mem_read); - M6502_setCallback(mpu, write, addr, copro_lib6502_mem_write); - } -#else for (addr= 0xfef8; addr <= 0xfeff; addr++) { M6502_setCallback(mpu, read, addr, copro_lib6502_tube_read); M6502_setCallback(mpu, write, addr, copro_lib6502_tube_write); } -#endif copro_lib6502_poweron_reset(mpu); copro_lib6502_reset(mpu); diff --git a/src/lib6502.c b/src/lib6502.c index c4f6ce78..ababcb95 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -34,6 +34,12 @@ #include "lib6502.h" +#ifdef INCLUDE_DEBUGGER +#include "lib6502_debug.h" +#endif + +extern volatile int tube_irq; + typedef uint8_t byte; typedef uint16_t word; @@ -74,6 +80,32 @@ static int elapsed; #endif /* memory access (indirect if callback installed) -- ARGUMENTS ARE EVALUATED MORE THAN ONCE! */ +#ifdef INCLUDE_DEBUGGER + +byte tmpr; + +#define putMemory(ADDR, BYTE) \ + if (lib6502_debug_enabled) { \ + externalise(); \ + debug_memwrite(&lib6502_cpu_debug, ADDR, BYTE, 1); \ + internalise(); \ + } \ + ( writeCallback[ADDR] \ + ? writeCallback[ADDR](mpu, ADDR, BYTE) \ + : (memory[ADDR]= BYTE) ) + +#define getMemory(ADDR) \ + tmpr = ( readCallback[ADDR] \ + ? readCallback[ADDR](mpu, ADDR, 0) \ + : memory[ADDR] ) ; \ + if (lib6502_debug_enabled) { \ + externalise(); \ + debug_memread(&lib6502_cpu_debug, ADDR, tmpr, 1); \ + internalise(); \ + } + +#else + #define putMemory(ADDR, BYTE) \ ( writeCallback[ADDR] \ ? writeCallback[ADDR](mpu, ADDR, BYTE) \ @@ -84,6 +116,8 @@ static int elapsed; ? readCallback[ADDR](mpu, ADDR, 0) \ : memory[ADDR] ) +#endif + /* stack access (always direct) */ #define push(BYTE) (memory[0x0100 + S--]= (BYTE)) @@ -404,7 +438,8 @@ static int elapsed; #define asl(ticks, adrmode) \ adrmode(ticks); \ { \ - unsigned int i= getMemory(ea) << 1; \ + byte B= getMemory(ea); \ + unsigned int i= B << 1; \ putMemory(ea, i); \ fetch(); \ setNZC(i & 0x80, !i, i >> 8); \ @@ -446,7 +481,8 @@ static int elapsed; #define rol(ticks, adrmode) \ adrmode(ticks); \ { \ - word b= (getMemory(ea) << 1) | getC(); \ + byte tmp = getMemory(ea); \ + word b= (tmp << 1) | getC(); \ fetch(); \ putMemory(ea, b); \ setNZC(b & 0x80, !(b & 0xFF), b >> 8); \ @@ -631,7 +667,9 @@ static int elapsed; P |= flagI; \ P &= !flagD; \ { \ - word hdlr= getMemory(0xfffe) + (getMemory(0xffff) << 8); \ + byte blo = getMemory(0xfffe); \ + byte bhi = getMemory(0xffff); \ + word hdlr= blo + (bhi << 8); \ if (mpu->callbacks->call[hdlr]) \ { \ word addr; \ @@ -869,10 +907,16 @@ void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll) register void **itabp= &itab[0]; register void *tpc; -# define pollints() externalise(); if (poll(mpu)) return; internalise() +#ifdef INCLUDE_DEBUGGER +# define nextdebug() if (lib6502_debug_enabled) { lib6502_last_PC = PC - 1; externalise(); debug_preexec(&lib6502_cpu_debug, lib6502_last_PC); internalise(); } +#else +# define nextdebug() +#endif + +# define pollints() if (tube_irq & 7) { externalise(); if (poll(mpu)) return; internalise(); } # define begin() fetch(); next() # define fetch() pollints(); tpc= itabp[memory[PC++]] -# define next() goto *tpc +# define next() nextdebug() goto *tpc # define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) //oops(); next() # define end() diff --git a/src/lib6502_debug.c b/src/lib6502_debug.c index eff36674..007f0d29 100644 --- a/src/lib6502_debug.c +++ b/src/lib6502_debug.c @@ -15,6 +15,8 @@ int lib6502_debug_enabled = 0; +volatile int lib6502_last_PC = 0; + enum register_numbers { i_A, i_X, @@ -162,7 +164,7 @@ static void dbg_reg_parse(int which, char *strval) { }; static uint32_t dbg_get_instr_addr() { - return copro_lib6502_mpu->registers->pc; + return lib6502_last_PC; } cpu_debug_t lib6502_cpu_debug = { diff --git a/src/lib6502_debug.h b/src/lib6502_debug.h index 96c3ea08..5d767fc2 100644 --- a/src/lib6502_debug.h +++ b/src/lib6502_debug.h @@ -2,5 +2,7 @@ extern int lib6502_debug_enabled; +extern volatile int lib6502_last_PC; + extern cpu_debug_t lib6502_cpu_debug; From 18dd036e9672df0d7678b0ac2448d15ad3c73afa Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 20:56:04 +0100 Subject: [PATCH 095/149] Debugger: Added a skip over next (n) command Change-Id: I012eca9ced4eff09de1255fe81828152b0452764 --- src/debugger/debugger.c | 80 +++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 35cc4476..5a8b89a3 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -19,6 +19,8 @@ #define HAS_IO (getCpu()->ioread != NULL) +#define BN_DISABLED 0xFFFFFFFF + static const char * prompt_str = ">> "; extern unsigned int copro; @@ -42,7 +44,7 @@ cpu_debug_t *cpu_debug_list[] = { NULL, // 15 Native ARM }; -#define NUM_CMDS 19 +#define NUM_CMDS 20 #define NUM_IO_CMDS 6 // The Atom CRC Polynomial @@ -93,6 +95,7 @@ static void doCmdHelp(char *params); static void doCmdIn(char *params); static void doCmdList(char *params); static void doCmdMem(char *params); +static void doCmdNext(char *params); static void doCmdOut(char *params); static void doCmdRd(char *params); static void doCmdRegs(char *params); @@ -113,6 +116,7 @@ static char *dbgCmdStrings[NUM_CMDS + NUM_IO_CMDS] = { "help", "continue", "step", + "next", "regs", "dis", "fill", @@ -142,6 +146,7 @@ static void (*dbgCmdFuncs[NUM_CMDS + NUM_IO_CMDS])(char *params) = { doCmdHelp, doCmdContinue, doCmdStep, + doCmdNext, doCmdRegs, doCmdDis, doCmdFill, @@ -187,6 +192,10 @@ static int stepping = 0; static int step_counter; +static uint32_t break_next_addr = BN_DISABLED; + +static uint32_t next_addr; + // The current memory address (e.g. used when disassembling) static unsigned int memAddr = 0; @@ -254,7 +263,7 @@ static void cpu_continue() { static void disassemble_addr(uint32_t addr) { cpu_debug_t *cpu = getCpu(); - cpu->disassemble(addr, strbuf, sizeof(strbuf)); + next_addr = cpu->disassemble(addr, strbuf, sizeof(strbuf)); noprompt(); printf("%s\r\n", &strbuf[0]); prompt(); @@ -322,35 +331,43 @@ void debug_iowrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { int show = 0; - breakpoint_t *ptr = check_for_breakpoints(addr, exec_breakpoints); + if (addr == break_next_addr) { + break_next_addr = BN_DISABLED; + cpu_stop(); + show = 1; - if (ptr) { - if (ptr->mode == MODE_BREAK) { - noprompt(); - printf("Exec breakpoint hit at %"PRIx32"\r\n", addr); - prompt(); - show = 1; + } else { + breakpoint_t *ptr = check_for_breakpoints(addr, exec_breakpoints); - } else { - noprompt(); - printf("Exec watchpoint hit at %"PRIx32"\r\n", addr); - prompt(); + if (ptr) { + if (ptr->mode == MODE_BREAK) { + noprompt(); + printf("Exec breakpoint hit at %"PRIx32"\r\n", addr); + prompt(); + show = 1; + + } else { + noprompt(); + printf("Exec watchpoint hit at %"PRIx32"\r\n", addr); + prompt(); + } } - } - if (stepping) { - if (tracing) { - if (++trace_counter == tracing) { - trace_counter = 0; + if (stepping) { + if (tracing) { + if (++trace_counter == tracing) { + trace_counter = 0; + show = 1; + } + } + if (++step_counter == stepping) { + step_counter = 0; + cpu_stop(); show = 1; } } - if (++step_counter == stepping) { - step_counter = 0; - cpu_stop(); - show = 1; - } } + if (show) { disassemble_addr(addr); } @@ -586,6 +603,13 @@ static void doCmdStep(char *params) { cpu_continue(); } +static void doCmdNext(char *params) { + stepping = 0; + break_next_addr = next_addr; + printf("Skipping to %"PRIx32"\r\n", next_addr); + cpu_continue(); +} + static void doCmdTrace(char *params) { int i = 1; sscanf(params, "%d", &i); @@ -615,6 +639,9 @@ static void genericList(char *type, breakpoint_t *list) { } static void doCmdList(char *params) { + if (break_next_addr != BN_DISABLED) { + printf("Transient\r\n addr:%"PRIx32"\r\n", break_next_addr); + } genericList("Exec", exec_breakpoints); genericList("Mem Rd", mem_rd_breakpoints); genericList("Mem Wr", mem_wr_breakpoints); @@ -700,6 +727,10 @@ static void doCmdClear(char *params) { unsigned int addr = 0; sscanf(params, "%x", &addr); + if (break_next_addr == addr) { + break_next_addr = BN_DISABLED; + found = 1; + } found |= genericClear(addr, "Exec", exec_breakpoints); found |= genericClear(addr, "Mem Rd", mem_rd_breakpoints); found |= genericClear(addr, "Mem Wr", mem_wr_breakpoints); @@ -725,6 +756,9 @@ static void updateDebugFlag() { if (stepping) { enable = 1; } + if (break_next_addr != BN_DISABLED) { + enable = 1; + } if (exec_breakpoints[0].mode != MODE_LAST) { enable = 1; } From 4ab5c2f079c499a79feb14519e285d383ebbe985 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 21:36:31 +0100 Subject: [PATCH 096/149] Debugger: Initial support for traps Change-Id: I4164682ff19d64cb5258dd7c89f5f7625ee72f13 --- src/NS32016/32016_debug.c | 7 ++++++- src/cpu80186/cpu80186_debug.c | 8 +++++++- src/cpu_debug.h | 9 +++++---- src/debugger/debugger.c | 25 ++++++++++++++++++++++++- src/lib6502.c | 10 ++++++++++ src/lib6502_debug.c | 9 ++++++++- src/mame/arm_debug.c | 8 +++++++- src/mc6809nc/mc6809_debug.c | 8 +++++++- 8 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/NS32016/32016_debug.c b/src/NS32016/32016_debug.c index 09fb6630..550f3989 100644 --- a/src/NS32016/32016_debug.c +++ b/src/NS32016/32016_debug.c @@ -58,6 +58,10 @@ static const char *dbg_reg_names[] = { NULL }; +// 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) { @@ -225,6 +229,7 @@ cpu_debug_t n32016_cpu_debug = { .reg_set = dbg_reg_set, .reg_print = dbg_reg_print, .reg_parse = dbg_reg_parse, - .get_instr_addr = dbg_get_instr_addr + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names }; diff --git a/src/cpu80186/cpu80186_debug.c b/src/cpu80186/cpu80186_debug.c index 89f18d36..8cddd681 100644 --- a/src/cpu80186/cpu80186_debug.c +++ b/src/cpu80186/cpu80186_debug.c @@ -56,6 +56,11 @@ static const char *dbg_reg_names[] = { NULL }; +// 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 = cpu80186_debug_enabled; @@ -246,5 +251,6 @@ cpu_debug_t cpu80186_cpu_debug = { .reg_set = dbg_reg_set, .reg_print = dbg_reg_print, .reg_parse = dbg_reg_parse, - .get_instr_addr = dbg_get_instr_addr + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names }; diff --git a/src/cpu_debug.h b/src/cpu_debug.h index 19de302f..bac209ac 100644 --- a/src/cpu_debug.h +++ b/src/cpu_debug.h @@ -9,10 +9,10 @@ typedef struct { const char *cpu_name; // Name/model of CPU. int (*debug_enable)(int newvalue); // enable/disable debugging on this CPU, returns previous value. - uint32_t (*memread)(uint32_t addr); // CPU's usual memory read function for data. + uint32_t (*memread)(uint32_t addr); // CPU's usual memory read function. void (*memwrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. - uint32_t (*ioread)(uint32_t addr); // CPU's usual memory read function for data. - void (*iowrite)(uint32_t addr, uint32_t value); // CPU's usual memory write function. + uint32_t (*ioread)(uint32_t addr); // CPU's usual I/O read function. + void (*iowrite)(uint32_t addr, uint32_t value); // CPU's usual I/O write function. uint32_t (*disassemble)(uint32_t addr, char *buf, size_t bufsize); // disassemble one line, returns next address const char **reg_names; // NULL pointer terminated list of register names. uint32_t (*reg_get)(int which); // Get a register - which is the index into the names above @@ -20,7 +20,7 @@ typedef struct { size_t (*reg_print)(int which, char *buf, size_t bufsize); // Print register value in CPU standard form. 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. } cpu_debug_t; extern void debug_memread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); @@ -28,5 +28,6 @@ extern void debug_memwrite(cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint extern void debug_ioread (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); extern void debug_iowrite (cpu_debug_t *cpu, uint32_t addr, uint32_t value, uint8_t size); extern void debug_preexec (cpu_debug_t *cpu, uint32_t addr); +extern void debug_trap (cpu_debug_t *cpu, uint32_t addr, int reason); #endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 5a8b89a3..d8deb3ad 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -44,7 +44,7 @@ cpu_debug_t *cpu_debug_list[] = { NULL, // 15 Native ARM }; -#define NUM_CMDS 20 +#define NUM_CMDS 21 #define NUM_IO_CMDS 6 // The Atom CRC Polynomial @@ -101,6 +101,7 @@ static void doCmdRd(char *params); static void doCmdRegs(char *params); static void doCmdStep(char *params); static void doCmdTrace(char *params); +static void doCmdTraps(char *params); static void doCmdWatch(char *params); static void doCmdWatchIn(char *params); static void doCmdWatchOut(char *params); @@ -118,6 +119,7 @@ static char *dbgCmdStrings[NUM_CMDS + NUM_IO_CMDS] = { "step", "next", "regs", + "traps", "dis", "fill", "crc", @@ -148,6 +150,7 @@ static void (*dbgCmdFuncs[NUM_CMDS + NUM_IO_CMDS])(char *params) = { doCmdStep, doCmdNext, doCmdRegs, + doCmdTraps, doCmdDis, doCmdFill, doCmdCrc, @@ -374,6 +377,13 @@ void debug_preexec (cpu_debug_t *cpu, uint32_t addr) { while (stopped); }; +void debug_trap(cpu_debug_t *cpu, uint32_t addr, int reason) { + const char *desc = cpu->trap_names[reason]; + noprompt(); + printf("Trap: %s at %"PRIx32"\r\n", desc, addr); + prompt(); +} + /******************************************* * Helpers *******************************************/ @@ -477,6 +487,19 @@ static void doCmdRegs(char *params) { } } +static void doCmdTraps(char *params) { + cpu_debug_t *cpu = getCpu(); + const char **trap = cpu->trap_names; + if (*trap) { + while (*trap) { + printf("%s\r\n", *trap); + trap++; + } + } else { + printf("No traps implemented in %s\r\n", cpu->cpu_name); + } +} + static void doCmdDis(char *params) { cpu_debug_t *cpu = getCpu(); int i; diff --git a/src/lib6502.c b/src/lib6502.c index ababcb95..ab415470 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -104,6 +104,13 @@ byte tmpr; internalise(); \ } +#define trap(ADDR, n) \ + if (lib6502_debug_enabled) { \ + externalise(); \ + debug_trap(&lib6502_cpu_debug, ADDR, n); \ + internalise(); \ + } + #else #define putMemory(ADDR, BYTE) \ @@ -116,6 +123,8 @@ byte tmpr; ? readCallback[ADDR](mpu, ADDR, 0) \ : memory[ADDR] ) +#define trap(ADDR, n) + #endif /* stack access (always direct) */ @@ -660,6 +669,7 @@ byte tmpr; #define brk(ticks, adrmode) \ tick(ticks); \ + trap(PC - 1, 0) \ PC++; \ push(PC >> 8); \ push(PC & 0xff); \ diff --git a/src/lib6502_debug.c b/src/lib6502_debug.c index 007f0d29..53160b96 100644 --- a/src/lib6502_debug.c +++ b/src/lib6502_debug.c @@ -37,6 +37,12 @@ static const char *dbg_reg_names[] = { NULL }; +// NULL pointer terminated list of trap names. +static const char *dbg_trap_names[] = { + "BRK", + NULL +}; + // enable/disable debugging on this CPU, returns previous value. static int dbg_debug_enable(int newvalue) { int oldvalue = lib6502_debug_enabled; @@ -178,5 +184,6 @@ cpu_debug_t lib6502_cpu_debug = { .reg_set = dbg_reg_set, .reg_print = dbg_reg_print, .reg_parse = dbg_reg_parse, - .get_instr_addr = dbg_get_instr_addr + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names }; diff --git a/src/mame/arm_debug.c b/src/mame/arm_debug.c index 625e7d9b..206fa2d8 100644 --- a/src/mame/arm_debug.c +++ b/src/mame/arm_debug.c @@ -84,6 +84,11 @@ static const char *dbg_reg_names[] = { NULL }; +// 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 = arm2_debug_enabled; @@ -218,5 +223,6 @@ cpu_debug_t arm2_cpu_debug = { .reg_set = dbg_reg_set, .reg_print = dbg_reg_print, .reg_parse = dbg_reg_parse, - .get_instr_addr = dbg_get_instr_addr + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names }; diff --git a/src/mc6809nc/mc6809_debug.c b/src/mc6809nc/mc6809_debug.c index eb0503ba..7c16c76b 100644 --- a/src/mc6809nc/mc6809_debug.c +++ b/src/mc6809nc/mc6809_debug.c @@ -43,6 +43,11 @@ static const char *dbg_reg_names[] = { NULL }; +// 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 = mc6809nc_debug_enabled; @@ -189,5 +194,6 @@ cpu_debug_t mc6809nc_cpu_debug = { .reg_set = dbg_reg_set, .reg_print = dbg_reg_print, .reg_parse = dbg_reg_parse, - .get_instr_addr = dbg_get_instr_addr + .get_instr_addr = dbg_get_instr_addr, + .trap_names = dbg_trap_names }; From 7f519686fc8546e87b4136bd141ae0d751840b4f Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 30 Mar 2017 22:50:54 +0100 Subject: [PATCH 097/149] Enable weak pullups on Serial Rx and Tx lines Change-Id: I90e51e2fcb34d2792377ec4f0be2f97a3c927b84 --- src/rpi-aux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index a4676985..d30f3a96 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -120,12 +120,14 @@ void RPI_AuxMiniUartInit(int baud, int bits) RPI_SetGpioPinFunction(RPI_GPIO14, FS_ALT5); RPI_SetGpioPinFunction(RPI_GPIO15, FS_ALT5); + // Enable weak pullups + RPI_GpioBase->GPPUD = 2; // Note: the delay values are important, with 150 the receiver did not work! - RPI_GpioBase->GPPUD = 0; for (i = 0; i < 1000; i++) { } RPI_GpioBase->GPPUDCLK0 = (1 << 14) | (1 << 15); + // Note: the delay values are important, with 150 the receiver did not work! for (i = 0; i < 1000; i++) { } From 29ca6ec13038e8ef72275b4e7d7b4e8d9660a23f Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 31 Mar 2017 19:03:48 +0100 Subject: [PATCH 098/149] Z80 Co Pro: Added debugger support Change-Id: I10f3e7fa91fc7d512f5a8d7e574e72a30ffed8c0 --- src/CMakeLists.txt | 2 + src/copro-z80.c | 35 ++- src/debugger/debugger.c | 9 +- src/yaze/simz80.c | 277 ++++++++++++++++++++++ src/yaze/simz80.h | 9 +- src/yaze/z80dis.c | 497 ++++++++++++++++++++++++++++++++++++++++ src/yaze/z80dis.h | 6 + 7 files changed, 825 insertions(+), 10 deletions(-) create mode 100644 src/yaze/z80dis.c create mode 100644 src/yaze/z80dis.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a4297f61..f361ee5a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -231,6 +231,8 @@ file( GLOB debugger_files cpu_debug.h lib6502_debug.c lib6502_debug.h + yaze/z80dis.c + yaze/z80dis.h NS32016/32016_debug.c NS32016/32016_debug.h mame/arm_debug.c diff --git a/src/copro-z80.c b/src/copro-z80.c index 2a8779de..555228df 100644 --- a/src/copro-z80.c +++ b/src/copro-z80.c @@ -12,6 +12,10 @@ #include "yaze/simz80.h" #include "tube-client.h" +#ifdef INCLUDE_DEBUGGER +#include "cpu_debug.h" +#endif + static int overlay_rom = 0; static unsigned char *copro_z80_ram; @@ -276,21 +280,33 @@ static const unsigned char copro_z80_rom[0x1000] = { }; int copro_z80_read_mem(unsigned int addr) { + unsigned char data; if (addr >= 0x8000) { overlay_rom = 0; } if (overlay_rom) { - return copro_z80_rom[addr & 0xfff]; + data = copro_z80_rom[addr & 0xfff]; } else { #if USE_MEMORY_POINTER - return copro_z80_ram[addr & 0xffff]; + data = copro_z80_ram[addr & 0xffff]; #else - return *(unsigned char *)(addr & 0xffff); + data = *(unsigned char *)(addr & 0xffff); #endif } +#ifdef INCLUDE_DEBUGGER + if (simz80_debug_enabled) { + debug_memread(&simz80_cpu_debug, addr, data, 1); + } +#endif + return data; } void copro_z80_write_mem(unsigned int addr, unsigned char data) { +#ifdef INCLUDE_DEBUGGER + if (simz80_debug_enabled) { + debug_memwrite(&simz80_cpu_debug, addr, data, 1); + } +#endif #ifdef USE_MEMORY_POINTER copro_z80_ram[addr & 0xffff] = data; #else @@ -299,10 +315,21 @@ void copro_z80_write_mem(unsigned int addr, unsigned char data) { } int copro_z80_read_io(unsigned int addr) { - return tube_parasite_read(addr & 7); + unsigned char data = tube_parasite_read(addr & 7); +#ifdef INCLUDE_DEBUGGER + if (simz80_debug_enabled) { + debug_ioread(&simz80_cpu_debug, addr, data, 1); + } +#endif + return data; } void copro_z80_write_io(unsigned int addr, unsigned char data) { +#ifdef INCLUDE_DEBUGGER + if (simz80_debug_enabled) { + debug_iowrite(&simz80_cpu_debug, addr, data, 1); + } +#endif tube_parasite_write(addr & 7, data); } diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index d8deb3ad..8a9f31af 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -10,6 +10,7 @@ #include "../cpu_debug.h" #include "../lib6502_debug.h" +#include "../yaze/simz80.h" #include "../cpu80186/cpu80186_debug.h" #include "../mc6809nc/mc6809_debug.h" #include "../mame/arm_debug.h" @@ -30,10 +31,10 @@ cpu_debug_t *cpu_debug_list[] = { NULL, // 1 65tube &lib6502_cpu_debug, // 2 lib6502 &lib6502_cpu_debug, // 3 lib6502 - NULL, // 4 Z80 - NULL, // 5 Z80 - NULL, // 4 Z80 - NULL, // 7 Z80 + &simz80_cpu_debug, // 4 Z80 + &simz80_cpu_debug, // 5 Z80 + &simz80_cpu_debug, // 6 Z80 + &simz80_cpu_debug, // 7 Z80 &cpu80186_cpu_debug, // 8 80x86 &mc6809nc_cpu_debug, // 9 6809 NULL, // 10 unused diff --git a/src/yaze/simz80.c b/src/yaze/simz80.c index 6463a76f..1ccb4cc6 100644 --- a/src/yaze/simz80.c +++ b/src/yaze/simz80.c @@ -140,6 +140,275 @@ static const unsigned char partab[256] = { iy = IY; \ sp = SP + +/***************************************************** + * CPU Debug Interface + *****************************************************/ + +#ifdef INCLUDE_DEBUGGER + +#include +#include +#include +#include + +#include "../cpu_debug.h" +#include "z80dis.h" + +int simz80_debug_enabled = 0; + +static WORD last_PC = 0; + +enum register_numbers { + i_A, + i_F, + i_BC, + i_DE, + i_HL, + i_A_, + i_F_, + i_BC_, + i_DE_, + i_HL_, + i_IX, + i_IY, + i_SP, + i_PC, + i_IR, + i_IFF1, + i_IFF2 +}; + +// NULL pointer terminated list of register names. +static const char *dbg_reg_names[] = { + "A", + "F", + "BC", + "DE", + "HL", + "A'", + "F'", + "BC'", + "DE'", + "HL'", + "IX", + "IY", + "SP", + "PC", + "IR", + "IFF1", + "IFF2", + NULL +}; + +// 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 = simz80_debug_enabled; + simz80_debug_enabled = newvalue; + return oldvalue; +}; + +// CPU's usual memory read function for data. +static uint32_t dbg_memread(uint32_t addr) { + return copro_z80_read_mem(addr); +}; + +// CPU's usual memory write function. +static void dbg_memwrite(uint32_t addr, uint32_t value) { + copro_z80_write_mem(addr, value); +}; + +// CPU's usual I/O read function for data. +static uint32_t dbg_ioread(uint32_t addr) { + return copro_z80_read_io(addr); +}; + +// CPU's usual I/O write function. +static void dbg_iowrite(uint32_t addr, uint32_t value) { + copro_z80_write_io(addr, value); +}; + +// Get a register - which is the index into the names above +static uint32_t dbg_reg_get(int which) { + switch (which) { + case i_A: + return hreg(af[0]); + case i_F: + return lreg(af[0]); + case i_BC: + return regs[0].bc; + case i_DE: + return regs[0].de; + case i_HL: + return regs[0].hl; + case i_A_: + return hreg(af[1]); + case i_F_: + return lreg(af[1]); + case i_BC_: + return regs[1].bc; + case i_DE_: + return regs[1].de; + case i_HL_: + return regs[1].hl; + case i_IX: + return ix; + case i_IY: + return iy; + case i_SP: + return sp; + case i_PC: + return pc; + case i_IR: + return ir; + case i_IFF1: + return IFF & 1; + case i_IFF2: + return (IFF >> 1) & 1; + default: + return 0; + } +}; + +// Set a register. +static void dbg_reg_set(int which, uint32_t value) { + switch (which) { + case i_A: + Sethreg(af[0], value); + break; + case i_F: + Setlreg(af[0], value); + break; + case i_BC: + regs[0].bc = value; + break; + case i_DE: + regs[0].de = value; + break; + case i_HL: + regs[0].hl = value; + break; + case i_A_: + Sethreg(af[1], value); + break; + case i_F_: + Setlreg(af[1], value); + break; + case i_BC_: + regs[1].bc = value; + break; + case i_DE_: + regs[1].de = value; + break; + case i_HL_: + regs[1].hl = value; + break; + case i_IX: + ix = value; + break; + case i_IY: + iy = value; + break; + case i_SP: + sp = value; + break; + case i_PC: + pc = value; + break; + case i_IR: + ir = value; + break; + case i_IFF1: + IFF &= ~1; + IFF |= value & 1; + break; + case i_IFF2: + IFF &= ~2; + IFF |= (value & 1) << 1; + break; + } +}; + +static const char* flagname = "S Z * H * P N C "; + +// Print register value in CPU standard form. +static size_t dbg_reg_print(int which, char *buf, size_t bufsize) { + if (which == i_F || which == i_F_) { + int i; + int bit; + char c; + const char *flagnameptr = flagname; + int psr = dbg_reg_get(which); + + if (bufsize < 40) { + strncpy(buf, "buffer too small!!!", bufsize); + } + + bit = 0x80; + for (i = 0; i < 8; i++) { + if (psr & bit) { + c = '1'; + } else { + c = '0'; + } + do { + *buf++ = *flagnameptr++; + } while (*flagnameptr != ' '); + flagnameptr++; + *buf++ = ':'; + *buf++ = c; + *buf++ = ' '; + bit >>= 1; + } + return strlen(buf); + } else if (which == i_A || which == i_A_) { + return snprintf(buf, bufsize, "%02"PRIx32, dbg_reg_get(which)); + } else if (which == i_IFF1 || which == i_IFF2) { + return snprintf(buf, bufsize, "%"PRIx32, dbg_reg_get(which)); + } 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 last_PC; +} + +cpu_debug_t simz80_cpu_debug = { + .cpu_name = "simz80", + .debug_enable = dbg_debug_enable, + .memread = dbg_memread, + .memwrite = dbg_memwrite, + .ioread = dbg_ioread, + .iowrite = dbg_iowrite, + .disassemble = z80_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 +}; + +#endif + +/********************************************************** + * Z80 emulation + **********************************************************/ + FASTWORK simz80_execute(int tube_cycles) { @@ -158,6 +427,14 @@ simz80_execute(int tube_cycles) #endif do { +#ifdef INCLUDE_DEBUGGER + if (simz80_debug_enabled) { + last_PC = PC; + SAVE_STATE(); + debug_preexec(&simz80_cpu_debug, last_PC); + LOAD_STATE(); + } +#endif switch(GetBYTE_pp(PC)) { case 0x00: /* NOP */ break; diff --git a/src/yaze/simz80.h b/src/yaze/simz80.h index 0ec2b331..18359d2e 100644 --- a/src/yaze/simz80.h +++ b/src/yaze/simz80.h @@ -39,8 +39,13 @@ extern WORD IFF; */ /* see definitions for memory in mem_mmu.h */ -#ifdef DEBUG -extern volatile int stopsim; +// For FASTWORK +#include "mem_mmu.h" + +#ifdef INCLUDE_DEBUGGER +#include "../cpu_debug.h" +extern int simz80_debug_enabled; +extern cpu_debug_t simz80_cpu_debug; #endif extern FASTWORK simz80(FASTREG PC); diff --git a/src/yaze/z80dis.c b/src/yaze/z80dis.c new file mode 100644 index 00000000..f849e56c --- /dev/null +++ b/src/yaze/z80dis.c @@ -0,0 +1,497 @@ +#include +#include +#include +#include + +#include "mem_mmu.h" +//#include "simz80.h" +#include "z80dis.h" + +#define IBUF_SIZE 20 + +static const char *reg[8] = { "B", "C", "D", "E", "H", "L", "(HL)", "A"}; +static const char *dreg1[4] = { "BC", "DE", "HL", "SP"}; +static const char *dreg2[4] = { "BC", "DE", "HL", "AF"}; +static const char *cond[8] = { "NZ", "Z", "NC", "C", "PO", "PE", "P", "M"}; +static const char *arith[8] = { "ADD A,", "ADC A,", "SUB ", "SBC A,", + "AND ", "XOR ", "OR ","CP "}; +static const char *ins1[8] = { "RLCA","RRCA","RLA","RRA","DAA","CPL","SCF","CCF"}; +static const char *ins2[4] = { "RET", "EXX", "JP (HL)", "LD SP,HL" }; +static const char *ins3[8] = { "RLC","RRC","RL ","RR ","SLA","SRA","???","SRL"}; +static const char *ins4[8] = { "NEG","???","???","???","???","???","???","???"}; +static const char *ins5[8] = { "RETN","RETI","???","???","???","???","???","???"}; +static const char *ins6[8] = { "LD I,A","???","LD A,I","???","RRD","RLD","???","???"}; +static const char *ins7[32] = { "LDI","CPI","INI","OUTI","???","???","???","???", + "LDD","CPD","IND","OUTD","???","???","???","???", + "LDIR","CPIR","INIR","OTIR","???","???","???","???", + "LDDR","CPDR","INDR","OTDR","???","???","???","???"}; +static const char *ins8[8] = { "RLC","RRC","RL","RR","SLA","SRA","???","SRL"}; + +static inline uint32_t unp_misc1(uint32_t addr, uint8_t a, uint8_t d, uint8_t e, const char **ptr, char *ibuf) { + uint16_t opaddr; + + switch(e) { + case 0x00: // relative jumps and assorted. + switch(d) { + case 0x00: + *ptr = "NOP"; + break; + case 0x01: + *ptr = "EX AF,AF'"; + break; + case 0x02: + opaddr = addr + 1; + opaddr += (signed char)GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "DJNZ %4.4Xh", opaddr); + break; + case 0x03: + opaddr = addr + 1; + opaddr += (signed char)GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "JR %4.4Xh", opaddr); + break; + default: + opaddr = addr + 1; + opaddr += (signed char)GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "JR %s,%4.4Xh", cond[d & 3], opaddr); + break; + } + break; + case 0x01: // 16-=bit load immediate/add + if (a & 0x08) { + snprintf(ibuf, IBUF_SIZE, "ADD HL,%s", dreg1[d >> 1]); + } else { + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD %s,%4.4Xh", dreg1[d >> 1], opaddr); + } + break; + case 0x02: // indirect load. + switch(d) { + case 0x00: + *ptr = "LD (BC),A"; + break; + case 0x01: + *ptr = "LD A,(BC)"; + break; + case 0x02: + *ptr = "LD (DE),A"; + break; + case 0x03: + *ptr = "LD A,(DE)"; + break; + case 0x04: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD (%4.4Xh),HL", opaddr); + break; + case 0x05: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD HL,(%4.4Xh)", opaddr); + break; + case 0x06: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD (%4.4Xh),A", opaddr); + break; + case 0x07: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD A,(%4.4Xh)", opaddr); + break; + } + break; + case 0x03: + if(a & 0x08) + snprintf(ibuf, IBUF_SIZE, "DEC %s", dreg1[d >> 1]); + else + snprintf(ibuf, IBUF_SIZE, "INC %s", dreg1[d >> 1]); + break; + case 0x04: + snprintf(ibuf, IBUF_SIZE, "INC %s", reg[d]); + break; + case 0x05: + snprintf(ibuf, IBUF_SIZE, "DEC %s", reg[d]); + break; + case 0x06: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "LD %s,%2.2Xh", reg[d], opaddr); + break; + case 0x07: + *ptr = ins1[d]; + break; + } + return addr; +} + +static inline uint32_t pfx_cb(uint32_t addr, const char **ptr, char *ibuf) { + uint8_t a, d, e; + + a = GetBYTE(addr++); + d = (a >> 3) & 7; + e = a & 7; + switch(a & 0xC0) { + case 0x00: + snprintf(ibuf, IBUF_SIZE, "%s %s", ins3[d], reg[e]); + break; + case 0x40: + snprintf(ibuf, IBUF_SIZE, "BIT %d,%s", d, reg[e]); + break; + case 0x80: + snprintf(ibuf, IBUF_SIZE, "RES %d,%s", d, reg[e]); + break; + case 0xC0: + snprintf(ibuf, IBUF_SIZE, "SET %d,%s", d, reg[e]); + break; + } + return addr; +} + +static inline uint32_t pfx_ed(uint32_t addr, const char **ptr, char *ibuf) { + uint8_t a, d, e; + uint16_t opaddr; + + a = GetBYTE(addr++); + d = (a >> 3) & 7; + e = a & 7; + switch (a & 0xC0) { + case 0x40: + switch (e) { + case 0x00: + snprintf(ibuf, IBUF_SIZE, "IN %s,(C)", reg[d]); + break; + case 0x01: + snprintf(ibuf, IBUF_SIZE, "OUT (C),%s", reg[d]); + break; + case 0x02: + if (d & 1) + snprintf(ibuf, IBUF_SIZE, "ADC HL,%s", dreg1[d >> 1]); + else + snprintf(ibuf, IBUF_SIZE, "SBC HL,%s", dreg1[d >> 1]); + break; + case 0x03: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + if (d & 1) + snprintf(ibuf, IBUF_SIZE, "LD %s,(%4.4Xh)", dreg1[d >> 1], opaddr); + else + snprintf(ibuf, IBUF_SIZE, "LD (%4.4Xh),%s", opaddr, dreg1[d >> 1]); + break; + case 0x04: + *ptr = ins4[d]; + break; + case 0x05: + *ptr = ins5[d]; + break; + case 0x06: + switch(d) { + case 0: + *ptr = "IM 0"; + break; + case 1: + *ptr = "IM 0/1"; + break; + default: + snprintf(ibuf, IBUF_SIZE, "IM %d", d-1); + } + break; + case 0x07: + *ptr = ins6[d]; + break; + } + break; + case 0x80: + *ptr = ins7[a & 0x1F]; + break; + } + return addr; +} + +static inline uint32_t pfx_ireg(uint32_t addr, uint8_t a, const char **ptr, char *ibuf) { + uint8_t d; + uint16_t opaddr, opadd2; + const char *ireg; + + // 0x01 (0xDD) = IX, 0x03 (0xFD) = IY + ireg = (a & 0x20) ? "IY" : "IX"; + a = GetBYTE(addr++); + switch(a) { + case 0x09: + snprintf(ibuf, IBUF_SIZE, "ADD %s,BC", ireg); + break; + case 0x19: + snprintf(ibuf, IBUF_SIZE, "ADD %s,DE", ireg); + break; + case 0x21: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD %s,%4.4Xh", ireg, opaddr); + break; + case 0x22: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD (%4.4Xh),%s", opaddr, ireg); + break; + case 0x23: + snprintf(ibuf, IBUF_SIZE, "INC %s", ireg); + break; + case 0x29: + snprintf(ibuf, IBUF_SIZE, "ADD %s,%s", ireg, ireg); + break; + case 0x2A: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "LD %s,(%4.4Xh)", ireg, opaddr); + break; + case 0x2B: + snprintf(ibuf, IBUF_SIZE, "DEC %s", ireg); + break; + case 0x34: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "INC (%s+%2.2Xh)", ireg, opaddr); + break; + case 0x35: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "DEC (%s+%2.2Xh)", ireg, opaddr); + break; + case 0x36: + opaddr = GetBYTE(addr++); + opadd2 = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "LD (%s+%2.2Xh),%2.2Xh", ireg, opaddr, opadd2); + break; + case 0x39: + snprintf(ibuf, IBUF_SIZE, "ADD %s,SP", ireg); + break; + case 0x46: + case 0x4E: + case 0x56: + case 0x5E: + case 0x66: + case 0x6E: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "LD %s,(%s+%2.2Xh)", reg[(a>>3)&7], ireg, opaddr); + break; + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x77: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "LD (%s+%2.2Xh),%s", ireg, opaddr, reg[a & 7]); + break; + case 0x7E: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "LD A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0x86: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "ADD A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0x8E: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "ADC A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0x96: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "SUB (%s+%2.2Xh)", ireg, opaddr); + break; + case 0x9E: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "SBC A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0xA6: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "AND A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0xAE: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "XOR A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0xB6: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "OR A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0xBE: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "CP A,(%s+%2.2Xh)", ireg, opaddr); + break; + case 0xE1: + snprintf(ibuf, IBUF_SIZE, "POP %s", ireg); + break; + case 0xE3: + snprintf(ibuf, IBUF_SIZE, "EX (SP),%s", ireg); + break; + case 0xE5: + snprintf(ibuf, IBUF_SIZE, "PUSH %s", ireg); + break; + case 0xE9: + snprintf(ibuf, IBUF_SIZE, "JP (%s)", ireg); + break; + case 0xF9: + snprintf(ibuf, IBUF_SIZE, "LD SP,%s", ireg); + break; + case 0xCB: + opaddr = GetBYTE(addr++); + a = GetBYTE(addr++); + d = (a >> 3) & 7; + switch(a & 0xC0) { + case 0x00: + snprintf(ibuf, IBUF_SIZE, "%s (%s+%2.2Xh)", ins8[d], ireg, opaddr); + case 0x40: + snprintf(ibuf, IBUF_SIZE, "BIT %d,(%s+%2.2Xh)", d, ireg, opaddr); + break; + case 0x80: + snprintf(ibuf, IBUF_SIZE, "RES %d,(%s+%2.2Xh)", d, ireg, opaddr); + break; + case 0xC0: + snprintf(ibuf, IBUF_SIZE, "SET %d,(%s+%2.2Xh)", d, ireg, opaddr); + break; + } + break; + } + return addr; +} + +static uint32_t unp_misc2(uint32_t addr, uint8_t a, uint8_t d, uint8_t e, const char **ptr, char *ibuf) { + uint16_t opaddr; + + switch(e) { + case 0x00: + snprintf(ibuf, IBUF_SIZE, "RET %s", cond[d]); + break; + case 0x01: + if(d & 1) + *ptr = ins2[d >> 1]; + else + snprintf(ibuf, IBUF_SIZE, "POP %s", dreg2[d >> 1]); + break; + case 0x02: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "JP %s,%4.4Xh", cond[d], opaddr); + break; + case 0x03: + switch(d) { + case 0x00: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "JP %4.4Xh", opaddr); + break; + case 0x01: + addr = pfx_cb(addr, ptr, ibuf); + break; + case 0x02: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "OUT (%2.2Xh),A", opaddr); + break; + case 0x03: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "IN A,(%2.2Xh)", opaddr); + break; + case 0x04: + *ptr = "EX (SP),HL"; + break; + case 0x05: + *ptr = "EX DE,HL"; + break; + case 0x06: + *ptr = "DI"; + break; + case 0x07: + *ptr = "EI"; + break; + } + break; + case 0x04: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "CALL %s,%4.4Xh", cond[d], opaddr); + break; + case 0x05: + if (d & 1) { + switch(d >> 1) { + case 0x00: + opaddr = GetBYTE(addr++); + opaddr |= (GetBYTE(addr++)<<8); + snprintf(ibuf, IBUF_SIZE, "CALL %4.4Xh", opaddr); + break; + case 0x02: + addr = pfx_ed(addr, ptr, ibuf); + break; + default: + addr = pfx_ireg(addr, a, ptr, ibuf); + break; + } + } else + snprintf(ibuf, IBUF_SIZE, "PUSH %s", dreg2[d >> 1]); + break; + case 0x06: + opaddr = GetBYTE(addr++); + snprintf(ibuf, IBUF_SIZE, "%s%2.2Xh", arith[d], opaddr); + break; + case 0x07: + snprintf(ibuf, IBUF_SIZE, "RST %2.2Xh", a & 0x38); + break; + } + return addr; +} + +static uint32_t disassemble(uint32_t addr, const char **ptr, char *ibuf) { + uint8_t a = GetBYTE(addr++); + uint8_t d = (a >> 3) & 7; + uint8_t e = a & 7; + + if (a & 0x80) { + if (a & 0x40) + addr = unp_misc2(addr, a, d, e, ptr, ibuf); + else + snprintf(ibuf, IBUF_SIZE, "%s%s", arith[d], reg[e]); + } else { + if (a & 0x40) { + if (d == 6 && e == 6) { + *ptr = "HALT"; + } else { + snprintf(ibuf, IBUF_SIZE, "LD %s,%s", reg[d], reg[e]); + } + } else + addr = unp_misc1(addr, a, d, e, ptr, ibuf); + } + return addr; +} + +uint32_t z80_disassemble(uint32_t addr, char *buf, size_t bufsize) { + uint32_t naddr, oaddr; + const int width=18; + char ibuf[IBUF_SIZE]; + const char *iptr = ibuf; + uint8_t b1, b2, b3, b4; + + naddr = disassemble(addr, &iptr, ibuf); + oaddr = addr; + switch(naddr-addr) { + case 1: + b1 = GetBYTE(oaddr++); + snprintf(buf, bufsize, "%04"PRIX32" %02X %-*s", addr, b1, width, iptr); + break; + case 2: + b1 = GetBYTE(oaddr++); + b2 = GetBYTE(oaddr++); + snprintf(buf, bufsize, "%04"PRIX32" %02X %02X %-*s", addr, b1, b2, width, iptr); + break; + case 3: + b1 = GetBYTE(oaddr++); + b2 = GetBYTE(oaddr++); + b3 = GetBYTE(oaddr++); + snprintf(buf, bufsize, "%04"PRIX32" %02X %02X %02X %-*s", addr, b1, b2, b3, width, iptr); + break; + default: + b1 = GetBYTE(oaddr++); + b2 = GetBYTE(oaddr++); + b3 = GetBYTE(oaddr++); + b4 = GetBYTE(oaddr++); + snprintf(buf, bufsize, "%04"PRIX32" %02X %02X %02X %02X %-*s", addr, b1, b2, b3, b4, width, iptr); + } + return naddr; +} diff --git a/src/yaze/z80dis.h b/src/yaze/z80dis.h new file mode 100644 index 00000000..b4b47cfa --- /dev/null +++ b/src/yaze/z80dis.h @@ -0,0 +1,6 @@ +#ifndef Z80_DIS_INC +#define Z80_DIS_INC + +extern uint32_t z80_disassemble(uint32_t addr, char *buf, size_t bufsize); + +#endif From 54355d3469ea6ada5335ba2deb4fa362939c7c37 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 31 Mar 2017 20:29:22 +0100 Subject: [PATCH 099/149] Use 0x0000 based memory --- src/lib6502.c | 107 ++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 46 deletions(-) diff --git a/src/lib6502.c b/src/lib6502.c index ab415470..93bab27f 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -80,6 +80,13 @@ static int elapsed; #endif /* memory access (indirect if callback installed) -- ARGUMENTS ARE EVALUATED MORE THAN ONCE! */ +#ifdef USE_MEMORY_POINTER +#define MEM(addr) memory[addr] +#else +#define MEM(addr) *(unsigned char *)(( int)addr ) +#endif + + #ifdef INCLUDE_DEBUGGER byte tmpr; @@ -92,12 +99,12 @@ byte tmpr; } \ ( writeCallback[ADDR] \ ? writeCallback[ADDR](mpu, ADDR, BYTE) \ - : (memory[ADDR]= BYTE) ) + : (MEM(ADDR)= BYTE) ) #define getMemory(ADDR) \ tmpr = ( readCallback[ADDR] \ ? readCallback[ADDR](mpu, ADDR, 0) \ - : memory[ADDR] ) ; \ + : MEM(ADDR) ) ; \ if (lib6502_debug_enabled) { \ externalise(); \ debug_memread(&lib6502_cpu_debug, ADDR, tmpr, 1); \ @@ -113,24 +120,26 @@ byte tmpr; #else + #define putMemory(ADDR, BYTE) \ ( writeCallback[ADDR] \ ? writeCallback[ADDR](mpu, ADDR, BYTE) \ - : (memory[ADDR]= BYTE) ) + : (MEM(ADDR)= BYTE) ) #define getMemory(ADDR) \ ( readCallback[ADDR] \ ? readCallback[ADDR](mpu, ADDR, 0) \ - : memory[ADDR] ) + : MEM(ADDR) ) + #define trap(ADDR, n) #endif /* stack access (always direct) */ -#define push(BYTE) (memory[0x0100 + S--]= (BYTE)) -#define pop() (memory[++S + 0x0100]) +#define push(BYTE) (MEM(0x0100 + S--)= (BYTE)) +#define pop() (MEM(++S + 0x0100)) /* addressing modes (memory access direct) */ @@ -143,18 +152,18 @@ byte tmpr; #define abs(ticks) \ tick(ticks); \ - ea= memory[PC] + (memory[PC + 1] << 8); \ + ea= MEM(PC) + (MEM(PC + 1) << 8); \ PC += 2; #define relative(ticks) \ tick(ticks); \ - ea= memory[PC++]; \ + ea= MEM(PC++); \ if (ea & 0x80) ea -= 0x100; \ tickIf((ea >> 8) != (PC >> 8)); #define zpr(ticks) \ tick(ticks); \ - ea= memory[PC++]; \ + ea= MEM(PC++); \ if (ea & 0x80) ea -= 0x100; \ tickIf((ea >> 8) != (PC >> 8)); @@ -162,51 +171,51 @@ byte tmpr; tick(ticks); \ { \ word tmp; \ - tmp= memory[PC] + (memory[PC + 1] << 8); \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ + tmp= MEM(PC) + (MEM(PC + 1) << 8); \ + ea = MEM(tmp) + (MEM(tmp + 1) << 8); \ PC += 2; \ } #define absx(ticks) \ tick(ticks); \ - ea= memory[PC] + (memory[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= memory[PC] + (memory[PC + 1] << 8); \ + ea= MEM(PC) + (MEM(PC + 1) << 8); \ PC += 2; \ tickIf((ticks == 4) && ((ea >> 8) != ((ea + Y) >> 8))); \ ea += Y #define zp(ticks) \ tick(ticks); \ - ea= memory[PC++]; + ea= MEM(PC++); #define zpx(ticks) \ tick(ticks); \ - ea= memory[PC++] + X; \ + ea= MEM(PC++) + X; \ ea &= 0x00ff; #define zpy(ticks) \ tick(ticks); \ - ea= memory[PC++] + Y; \ + ea= MEM(PC++) + Y; \ ea &= 0x00ff; #define indx(ticks) \ tick(ticks); \ { \ - byte tmp= memory[PC++] + X; \ - ea= memory[tmp] + (memory[tmp + 1] << 8); \ + byte tmp= MEM(PC++) + X; \ + ea= MEM(tmp) + (MEM(tmp + 1) << 8); \ } #define indy(ticks) \ tick(ticks); \ { \ - byte tmp= memory[PC++]; \ - ea= memory[tmp] + (memory[tmp + 1] << 8); \ + byte tmp= MEM(PC++); \ + ea= MEM(tmp) + (MEM(tmp + 1) << 8); \ tickIf((ticks == 5) && ((ea >> 8) != ((ea + Y) >> 8))); \ ea += Y; \ } @@ -215,16 +224,16 @@ byte tmpr; tick(ticks); \ { \ word tmp; \ - tmp= memory[PC ] + (memory[PC + 1] << 8) + X; \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ + tmp= MEM(PC ) + (MEM(PC + 1) << 8) + X; \ + ea = MEM(tmp) + (MEM(tmp + 1) << 8); \ } #define indzp(ticks) \ tick(ticks); \ { \ byte tmp; \ - tmp= memory[PC++]; \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ + tmp= MEM(PC++); \ + ea = MEM(tmp) + (MEM(tmp + 1) << 8); \ } /* insns */ @@ -603,23 +612,23 @@ byte tmpr; tick(1); \ next(); -#define bbr0(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<0))) -#define bbr1(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<1))) -#define bbr2(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<2))) -#define bbr3(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<3))) -#define bbr4(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<4))) -#define bbr5(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<5))) -#define bbr6(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<6))) -#define bbr7(ticks, adrmode) branch(ticks, adrmode, !(memory[memory[PC++]] & (1<<7))) - -#define bbs0(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<0))) -#define bbs1(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<1))) -#define bbs2(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<2))) -#define bbs3(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<3))) -#define bbs4(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<4))) -#define bbs5(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<5))) -#define bbs6(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<6))) -#define bbs7(ticks, adrmode) branch(ticks, adrmode, (memory[memory[PC++]] & (1<<7))) +#define bbr0(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<0))) +#define bbr1(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<1))) +#define bbr2(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<2))) +#define bbr3(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<3))) +#define bbr4(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<4))) +#define bbr5(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<5))) +#define bbr6(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<6))) +#define bbr7(ticks, adrmode) branch(ticks, adrmode, !(MEM(MEM(PC++)) & (1<<7))) + +#define bbs0(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<0))) +#define bbs1(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<1))) +#define bbs2(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<2))) +#define bbs3(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<3))) +#define bbs4(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<4))) +#define bbs5(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<5))) +#define bbs6(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<6))) +#define bbs7(ticks, adrmode) branch(ticks, adrmode, (MEM(MEM(PC++)) & (1<<7))) #define jmp(ticks, adrmode) \ adrmode(ticks); \ @@ -712,7 +721,7 @@ byte tmpr; fetch(); \ tick(ticks); \ fflush(stdout); \ - fprintf(stderr, "\nundefined instruction %02X at %04X\n", memory[PC-2], PC-2); \ + fprintf(stderr, "\nundefined instruction %02X at %04X\n", MEM(PC-2), PC-2); \ externalise(); M6502_trace(mpu); \ return; @@ -925,22 +934,23 @@ void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll) # define pollints() if (tube_irq & 7) { externalise(); if (poll(mpu)) return; internalise(); } # define begin() fetch(); next() -# define fetch() pollints(); tpc= itabp[memory[PC++]] +# define fetch() pollints(); tpc= itabp[MEM(PC++)] # define next() nextdebug() goto *tpc # define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) //oops(); next() # define end() #else /* (!__GNUC__) || (__STRICT_ANSI__) */ -# define begin() for (;;) switch (memory[PC++]) { +# define begin() for (;;) switch (MEM(PC++)) { # define fetch() # define next() break # define dispatch(num, name, mode, cycles) case 0x##num: name(cycles, mode); next() # define end() } #endif - +#ifdef USE_MEMORY_POINTER register byte *memory= mpu->memory; +#endif register word PC; word ea; byte A, X, Y, P, S; @@ -1029,10 +1039,15 @@ M6502 *M6502_new(M6502_Registers *registers, M6502_Memory memory, M6502_Callback if (!mpu) outOfMemory(); if (!registers) { registers = (M6502_Registers *)calloc(1, sizeof(M6502_Registers)); mpu->flags |= M6502_RegistersAllocated; } +#ifdef USE_MEMORY_POINTER if (!memory ) { memory = (uint8_t *)calloc(1, sizeof(M6502_Memory )); mpu->flags |= M6502_MemoryAllocated; } + if (!memory) outOfMemory(); +#else + { memory = 0; } +#endif if (!callbacks) { callbacks = (M6502_Callbacks *)calloc(1, sizeof(M6502_Callbacks)); mpu->flags |= M6502_CallbacksAllocated; } - if (!registers || !memory || !callbacks) outOfMemory(); + if (!registers || !callbacks) outOfMemory(); mpu->registers = registers; mpu->memory = memory; From 0aec8b9a83e8f9546bd71fe0b6eceb56c56f2bc3 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 31 Mar 2017 20:43:52 +0100 Subject: [PATCH 100/149] Use new tube_irq pattern --- src/mc6809nc/mc6809.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index 1bab0a4b..24f12678 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -21,6 +21,7 @@ #include "mc6809.h" #include +#include "../tube.h" #ifdef INCLUDE_DEBUGGER #include "mc6809_debug.h" @@ -64,7 +65,7 @@ void mc6809nc_request_irq (unsigned int source) * IRQ immediately. Else, mark it pending and * we'll check it later when the flags change. */ - irqs_pending |= (1 << source); +// irqs_pending |= (1 << source); sync_flag = 0; if (!(EFI & I_FLAG)) irq (); @@ -81,7 +82,7 @@ void mc6809nc_request_firq (unsigned int source) * IRQ immediately. Else, mark it pending and * we'll check it later when the flags change. */ - firqs_pending |= (1 << source); + //firqs_pending |= (1 << source); sync_flag = 0; if (!(EFI & F_FLAG)) firq (); @@ -1572,11 +1573,11 @@ static void bsr (void) } /* Execute 6809 code for a certain number of cycles. */ -int mc6809nc_execute (int cycles) +int mc6809nc_execute (int tube_cycles) { unsigned opcode; - cpu_period = cpu_clk = cycles; + cpu_period = cpu_clk = tube_cycles; if (sync_flag) { return cpu_period; @@ -2944,8 +2945,10 @@ int mc6809nc_execute (int cycles) if (cc_changed) cc_modified (); - } - while (cpu_clk > 0); + + tubeUseCycles(1); + } while (tubeContinueRunning()); + //while (cpu_clk > 0); cpu_period -= cpu_clk; cpu_clk = cpu_period; From 7e81d24a621b626cb512966362263435a16cf149 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 31 Mar 2017 21:16:19 +0100 Subject: [PATCH 101/149] Use new tube_irq pattern --- src/NS32016/32016.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/NS32016/32016.c b/src/NS32016/32016.c index ace0ca73..030ce443 100644 --- a/src/NS32016/32016.c +++ b/src/NS32016/32016.c @@ -15,6 +15,7 @@ #include "Trap.h" #include "Decode.h" #include "../tube-ula.h" +#include "../tube.h" #ifdef PROFILING #include "Profile.h" @@ -1010,10 +1011,9 @@ void n32016_exec() TakeInterrupt(intbase); } - while (tubecycles > 0) - { - tubecycles -= 8; - + + do { + tubeUseCycles(8); CLEAR_TRAP(); WriteSize = szVaries; // The size a result may be written as @@ -3069,5 +3069,5 @@ void n32016_exec() } } #endif - } + }while (tubeContinueRunning()); } From 36172719f7797da56dcaadb1004638ca1abb7ea4 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 31 Mar 2017 22:59:03 +0100 Subject: [PATCH 102/149] Update mc6809.c Fix sync bug introduced in last commit --- src/mc6809nc/mc6809.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index 24f12678..e9c12658 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -1481,6 +1481,7 @@ static void sync (void) { cpu_clk -= 4; sync_flag = 1; + while (tubeContinueRunning()); } static void orcc (void) From 458c8b04f634fc1437bf8493b390a00f3400861c Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 1 Apr 2017 15:48:40 +0100 Subject: [PATCH 103/149] Debugger: Fixed deadlock if a key is pressed while serial tx buffer is full (#50) Change-Id: I626be0f0ac4c0cd9a8081b60687b219c016e3bbd --- src/rpi-aux.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index d30f3a96..f050c201 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -5,6 +5,7 @@ #include "info.h" #ifdef INCLUDE_DEBUGGER +#include "startup.h" #include "debugger/debugger.h" #endif @@ -141,11 +142,20 @@ void RPI_AuxMiniUartWrite(char c) { #ifdef USE_IRQ int tmp_head = (tx_head + 1) & (TX_BUFFER_SIZE - 1); - - /* Wait for space in buffer */ - while (tmp_head == tx_tail) { - } + /* Test if the buffer is full */ + if (tmp_head == tx_tail) { + int cpsr = _get_cpsr(); + if (cpsr & 0x80) { + /* IRQ disabled: drop the character to avoid deadlock */ + return; + } else { + /* IRQ enabled: wait for space in buffer */ + while (tmp_head == tx_tail) { + } + } + } + /* Buffer the character */ tx_buffer[tmp_head] = c; tx_head = tmp_head; From 9fb3997f8926c80ec5d0eb79a9afa4b9c89a91e8 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 1 Apr 2017 16:22:06 +0100 Subject: [PATCH 104/149] Lib6502 Co Pro: Fixed Basic crashes when events enabled (#51) Change-Id: Ibcb75f003bdfe7c15a0e360bad54651ad6272537 --- src/lib6502.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib6502.c b/src/lib6502.c index 93bab27f..5b1b62eb 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -927,15 +927,15 @@ void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll) register void *tpc; #ifdef INCLUDE_DEBUGGER -# define nextdebug() if (lib6502_debug_enabled) { lib6502_last_PC = PC - 1; externalise(); debug_preexec(&lib6502_cpu_debug, lib6502_last_PC); internalise(); } +# define debug() if (lib6502_debug_enabled) { lib6502_last_PC = PC; externalise(); debug_preexec(&lib6502_cpu_debug, PC); internalise(); } #else -# define nextdebug() +# define debug() #endif # define pollints() if (tube_irq & 7) { externalise(); if (poll(mpu)) return; internalise(); } # define begin() fetch(); next() -# define fetch() pollints(); tpc= itabp[MEM(PC++)] -# define next() nextdebug() goto *tpc +# define fetch() +# define next() debug(); pollints(); tpc= itabp[MEM(PC++)]; goto *tpc # define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) //oops(); next() # define end() From ae79fdf4ebfe41aac81016027213303c5e458817 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 17:38:02 +0100 Subject: [PATCH 105/149] Tidy cppcheck 1.78 warnings --- src/debugger/debugger.c | 2 +- src/yaze/simz80.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 8a9f31af..6b084c46 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -459,7 +459,7 @@ static void doCmdRegs(char *params) { const char **reg = cpu->reg_names; char name[100]; char value[100]; - int num_params = sscanf(params, "%100s %100s", name, value); + int num_params = sscanf(params, "%99s %99s", name, value); if (num_params > 0) { int i = 0; while (*reg) { diff --git a/src/yaze/simz80.c b/src/yaze/simz80.c index 1ccb4cc6..4a58578b 100644 --- a/src/yaze/simz80.c +++ b/src/yaze/simz80.c @@ -663,7 +663,7 @@ simz80_execute(int tube_cycles) case 0x29: /* ADD HL,HL */ HL &= 0xffff; sum = HL + HL; - cbits = (HL ^ HL ^ sum) >> 8; + cbits = (/*HL ^ HL ^ */sum) >> 8; HL = sum; AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | (cbits & 0x10) | ((cbits >> 8) & 1); @@ -1325,7 +1325,7 @@ simz80_execute(int tube_cycles) ((sum == 0) << 6) | partab[sum]; break; case 0xA7: /* AND A */ - sum = ((AF & (AF)) >> 8) & 0xff; + sum = ((AF /*& (AF)*/) >> 8) & 0xff; AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | 0x10 | partab[sum]; break; @@ -1358,8 +1358,8 @@ simz80_execute(int tube_cycles) AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum]; break; case 0xAF: /* XOR A */ - sum = ((AF ^ (AF)) >> 8) & 0xff; - AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum]; + sum = 0;//((AF ^ (AF)) >> 8) & 0xff; + AF = (sum << 8) | (sum & 0xa8) | (1 << 6) | partab[sum]; break; case 0xB0: /* OR B */ sum = ((AF | (BC)) >> 8) & 0xff; @@ -1390,7 +1390,7 @@ simz80_execute(int tube_cycles) AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum]; break; case 0xB7: /* OR A */ - sum = ((AF | (AF)) >> 8) & 0xff; + sum = ((AF /*| (AF)*/) >> 8) & 0xff; AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum]; break; case 0xB8: /* CP B */ @@ -1584,8 +1584,8 @@ simz80_execute(int tube_cycles) cbits = acu & 1; cbshflg1: AF = (AF & ~0xff) | (temp & 0xa8) | - (((temp & 0xff) == 0) << 6) | - parity(temp) | !!cbits; + ((temp & 0xff)?0:(1<< 6)) | + parity(temp) | (cbits ?1:0); } break; case 0x40: /* BIT */ @@ -1741,7 +1741,7 @@ simz80_execute(int tube_cycles) case 0x29: /* ADD IX,IX */ IX &= 0xffff; sum = IX + IX; - cbits = (IX ^ IX ^ sum) >> 8; + cbits = (/*IX ^ IX ^ */sum) >> 8; IX = sum; AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | (cbits & 0x10) | ((cbits >> 8) & 1); @@ -2195,8 +2195,8 @@ simz80_execute(int tube_cycles) cbits = acu & 1; cbshflg2: AF = (AF & ~0xff) | (temp & 0xa8) | - (((temp & 0xff) == 0) << 6) | - parity(temp) | !!cbits; + ((temp & 0xff)?0:(1<< 6)) | + parity(temp) | (cbits?1:0); } break; case 0x40: /* BIT */ @@ -2469,8 +2469,8 @@ simz80_execute(int tube_cycles) break; case 0x62: /* SBC HL,HL */ HL &= 0xffff; - sum = HL - HL - TSTFLAG(C); - cbits = (HL ^ HL ^ sum) >> 8; + sum = /*HL - HL*/0 - TSTFLAG(C); + cbits = (/*HL ^ HL ^*/ sum) >> 8; HL = sum; AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & 0xffff) == 0) << 6) | @@ -2503,7 +2503,7 @@ simz80_execute(int tube_cycles) case 0x6A: /* ADC HL,HL */ HL &= 0xffff; sum = HL + HL + TSTFLAG(C); - cbits = (HL ^ HL ^ sum) >> 8; + cbits = (/*HL ^ HL ^ */sum) >> 8; HL = sum; AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & 0xffff) == 0) << 6) | @@ -2587,10 +2587,10 @@ simz80_execute(int tube_cycles) temp = GetBYTE_pp(HL); sum = acu - temp; cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | + AF = (AF & ~0xfe) | (sum & 0x80) | ((sum & 0xff)?0:1<<6) | (((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & 0xffff) != 0) << 2 | 2; + ((--BC & 0xffff)?(1<<2):0 ) | 2; if ((sum & 15) == 8 && (cbits & 16) != 0) AF &= ~8; break; @@ -2626,10 +2626,10 @@ simz80_execute(int tube_cycles) temp = GetBYTE_mm(HL); sum = acu - temp; cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | + AF = (AF & ~0xfe) | (sum & 0x80) | ((sum & 0xff)?0:1<< 6) | (((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & 0xffff) != 0) << 2 | 2; + ((--BC & 0xffff)?(1<<2):0) | 2; if ((sum & 15) == 8 && (cbits & 16) != 0) AF &= ~8; break; @@ -2855,7 +2855,7 @@ simz80_execute(int tube_cycles) case 0x29: /* ADD IY,IY */ IY &= 0xffff; sum = IY + IY; - cbits = (IY ^ IY ^ sum) >> 8; + cbits = (/*IY ^ IY ^ */sum) >> 8; IY = sum; AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | (cbits & 0x10) | ((cbits >> 8) & 1); @@ -3310,8 +3310,8 @@ simz80_execute(int tube_cycles) cbits = acu & 1; cbshflg3: AF = (AF & ~0xff) | (temp & 0xa8) | - (((temp & 0xff) == 0) << 6) | - parity(temp) | !!cbits; + ((temp & 0xff)?0:(1 << 6)) | + parity(temp) | (cbits?1:0) ; } break; case 0x40: /* BIT */ From fbdcd2a155beb6830b289e32df9763ebb6eb99cd Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 17:49:00 +0100 Subject: [PATCH 106/149] Make sync work if B-Em is used --- src/mc6809nc/mc6809.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mc6809nc/mc6809.c b/src/mc6809nc/mc6809.c index e9c12658..b4ef9178 100644 --- a/src/mc6809nc/mc6809.c +++ b/src/mc6809nc/mc6809.c @@ -1479,9 +1479,11 @@ static void cwai (void) static void sync (void) { - cpu_clk -= 4; - sync_flag = 1; - while (tubeContinueRunning()); + sync_flag = 1; + do { + cpu_clk -= 4; + tubeUseCycles(0xFFFF); + } while (tubeContinueRunning()); } static void orcc (void) From 01a1d5f8ed16c21af7a4a73b52d2f9062d432231 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 17:54:19 +0100 Subject: [PATCH 107/149] Make non debugger version build without warings --- src/rpi-aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index f050c201..03907a09 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -3,9 +3,9 @@ #include "rpi-base.h" #include "rpi-gpio.h" #include "info.h" +#include "startup.h" #ifdef INCLUDE_DEBUGGER -#include "startup.h" #include "debugger/debugger.h" #endif From 6a4b3d7e56c4735112eec0a93a9de9be0b1ad71c Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 18:34:40 +0100 Subject: [PATCH 108/149] Add variable memory size to 32016 co pro --- src/NS32016/mem32016.c | 8 +++++++- src/NS32016/mem32016.h | 1 - src/tube-client.c | 21 +++++++++++++++++---- src/tube-ula.c | 15 ++++++++++++--- src/tube.h | 2 ++ 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index c761b86c..d3693d30 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -17,6 +17,8 @@ #include "32016_debug.h" #endif +static uint32_t RAM_SIZE; + #ifdef BEM #include "../tube.h" @@ -49,8 +51,12 @@ static uint8_t * ns32016ram; void init_ram(void) { + if (copro_memory_size >0) + RAM_SIZE = copro_memory_size; + else + RAM_SIZE = MEG1; #ifndef BEM - ns32016ram = copro_mem_reset(MEG16); + ns32016ram = copro_mem_reset(RAM_SIZE); #endif #ifdef TEST_SUITE memcpy(ns32016ram, ROM, sizeof(ROM)); diff --git a/src/NS32016/mem32016.h b/src/NS32016/mem32016.h index 77794039..693df72b 100644 --- a/src/NS32016/mem32016.h +++ b/src/NS32016/mem32016.h @@ -1,7 +1,6 @@ #define IO_BASE 0xFFFFF0 //#define PANDORA_BASE 0xF00000 -#define RAM_SIZE MEG1 //#define TEST_SUITE #ifdef TEST_SUITE diff --git a/src/tube-client.c b/src/tube-client.c index d8757d62..19b36fbc 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -87,6 +87,8 @@ static const func_ptr emulator_functions[] = { volatile unsigned int copro; volatile unsigned int copro_speed; +volatile unsigned int copro_memory_size = 0; + int arm_speed; static func_ptr emulator; @@ -207,6 +209,17 @@ static void get_copro_speed() { copro_speed = (arm_speed/(1000000/256) / copro_speed); } +static void get_copro_memory_size() { + char *copro_prop = get_cmdline_prop("copro13_memory_size"); + copro_memory_size = 0; // default + if (copro_prop) { + copro_memory_size = atoi(copro_prop); + } + if (copro_memory_size > 32*1024 *1024){ + copro_memory_size = 0; + } + LOG_DEBUG("Copro Memory size %u\r\n", copro_memory_size); +} void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) { @@ -218,11 +231,11 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) arm_speed = get_clock_rate(ARM_CLK_ID); copro = get_copro_number(); get_copro_speed(); + get_copro_memory_size(); - - LOG_DEBUG("Staring VC ULA\r\n"); - start_vc_ula(); - LOG_DEBUG("Done\r\n"); + LOG_DEBUG("Staring VC ULA\r\n"); + start_vc_ula(); + LOG_DEBUG("Done\r\n"); enable_MMU_and_IDCaches(); _enable_unaligned_access(); diff --git a/src/tube-ula.c b/src/tube-ula.c index fd0c5d92..7e4baf0e 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -180,9 +180,18 @@ void copro_command_excute(unsigned char copro_command,unsigned char val) copro_speed = 0; else copro_speed = (arm_speed/(1000000/256) / val); - LOG_DEBUG("New speed Copro = %u, %u\n", val, copro_speed); + LOG_DEBUG("New Copro speed= %u, %u\r\n", val, copro_speed); return; - + case 1 : // *fx 151,226,1 followed by *fx 151,228,val + // Select memory size + if (val & 128 ) + copro_memory_size = (val & 127 ) * 8 * 1024 * 1024; + else + copro_memory_size = (val & 127 ) * 64 * 1024 ; + if (copro_memory_size > 16 *1024 * 1024) + copro_memory_size = 0; + LOG_DEBUG("New Copro memory size = %u, %u\r\n", val, copro_memory_size); + return; default : break; } @@ -366,7 +375,7 @@ static void tube_host_write(uint16_t addr, uint8_t val) break; case 6: copro = val; - LOG_DEBUG("New Copro = %u\n", copro); + LOG_DEBUG("New Copro = %u\r\n", copro); return; case 7: /*Register 4*/ // if (!tube_enabled) diff --git a/src/tube.h b/src/tube.h index 917833a0..f7cc51c8 100644 --- a/src/tube.h +++ b/src/tube.h @@ -10,6 +10,8 @@ extern volatile unsigned int copro; extern volatile unsigned int copro_speed; +extern volatile unsigned int copro_memory_size; + extern int arm_speed; extern void arm_fiq_handler_flag1(); From 8b10ff58383af80bd28093f90e16a003966a00c8 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 20:31:10 +0100 Subject: [PATCH 109/149] Tidying , making header files consistant with code --- src/NS32016/32016.h | 2 +- src/cpu80186/cpu80186.h | 2 +- src/darm/thumb2.h | 2 +- src/lib6502.c | 6 +++--- src/lib6502.h | 2 +- src/logging.h | 4 ++-- src/mame/arm.h | 2 +- src/mc6809nc/mc6809.h | 2 +- src/yaze/simz80.h | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/NS32016/32016.h b/src/NS32016/32016.h index 27608e29..da2a92d2 100644 --- a/src/NS32016/32016.h +++ b/src/NS32016/32016.h @@ -336,7 +336,7 @@ enum StringBits }; extern void n32016_init(); -extern void n32016_ShowRegs(int bShowFloat); +extern void n32016_ShowRegs(int Option); extern void n32016_reset(); extern void n32016_reset_addr(uint32_t StartAddress); extern void n32016_exec(); diff --git a/src/cpu80186/cpu80186.h b/src/cpu80186/cpu80186.h index c130a4ed..3ed69287 100644 --- a/src/cpu80186/cpu80186.h +++ b/src/cpu80186/cpu80186.h @@ -78,7 +78,7 @@ union _bytewordregs_ #define segbase(x) ((uint32_t) ((x) << 4)) extern void reset(void); -extern void exec86(uint32_t execloops); +extern void exec86(uint32_t tube_cycles); extern void intcall86(uint8_t intnum); extern uint8_t ifl; diff --git a/src/darm/thumb2.h b/src/darm/thumb2.h index af38c9e9..a35e9436 100644 --- a/src/darm/thumb2.h +++ b/src/darm/thumb2.h @@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef __THUMB2_H__ #define __THUMB2_H__ -uint32_t thumb_expand_imm(uint16_t imm12_r); +uint32_t thumb_expand_imm(uint16_t imm12); void thumb2_decode_immshift(darm_t *d, uint8_t type, uint8_t imm5); darm_instr_t thumb2_decode_instruction(darm_t *d, uint16_t w, uint16_t w2); diff --git a/src/lib6502.c b/src/lib6502.c index 5b1b62eb..b79ce772 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -876,12 +876,12 @@ void M6502_reset(M6502 *mpu) /* the compiler should eliminate all calls to this function */ - +/* static void oops(void) { fprintf(stderr, "\noops -- instruction dispatch missing\n"); } - +*/ static int previousPC; void M6502_trace(M6502 *mpu) @@ -974,7 +974,7 @@ void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll) # undef dispatch # undef end - (void)oops; + // (void)oops; } diff --git a/src/lib6502.h b/src/lib6502.h index fd9e99a5..32185255 100644 --- a/src/lib6502.h +++ b/src/lib6502.h @@ -60,7 +60,7 @@ extern void M6502_nmi(M6502 *mpu); extern void M6502_irq(M6502 *mpu); extern void M6502_run(M6502 *mpu, M6502_PollInterruptsCallback poll); //extern void M6502_run(M6502 *mpu); -extern int M6502_disassemble(M6502 *mpu, uint16_t addr, char buffer[64]); +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); diff --git a/src/logging.h b/src/logging.h index ea45d40a..0dc9ab7f 100644 --- a/src/logging.h +++ b/src/logging.h @@ -4,9 +4,9 @@ #define LOGGING_H #ifdef DEBUG -extern void log_debug(const char *format, ...); +extern void log_debug(const char *fmt, ...); #else -static inline void log_debug(const char *format, ...) {} +static inline void log_debug(const char *fmt, ...) {} #endif extern void log_info(const char *fmt, ...); diff --git a/src/mame/arm.h b/src/mame/arm.h index 75088f77..c65f3689 100644 --- a/src/mame/arm.h +++ b/src/mame/arm.h @@ -53,7 +53,7 @@ enum }; void arm2_device_reset(); -void arm2_execute_run(int n); +void arm2_execute_run(int tube_cycles); void arm2_check_irq_state(); void arm2_execute_set_input(int irqline, int state); UINT32 arm2_getR15(); diff --git a/src/mc6809nc/mc6809.h b/src/mc6809nc/mc6809.h index d8e17d19..20fbc2ae 100644 --- a/src/mc6809nc/mc6809.h +++ b/src/mc6809nc/mc6809.h @@ -77,7 +77,7 @@ extern void copro_mc6809nc_write(uint16_t addr, uint8_t data); #define fetch16() (pc += 2, abs_read16(pc-2)) /* 6809.c */ -extern int mc6809nc_execute (int cycles); +extern int mc6809nc_execute (int tube_cycles); extern void mc6809nc_reset (void); diff --git a/src/yaze/simz80.h b/src/yaze/simz80.h index 18359d2e..3bd2e721 100644 --- a/src/yaze/simz80.h +++ b/src/yaze/simz80.h @@ -93,4 +93,4 @@ extern void simz80_IRQ(); extern int simz80_is_IRQ_enabled(); -extern FASTWORK simz80_execute(int n); +extern FASTWORK simz80_execute(int tube_cycles); From dde534214cb2fccc238ffbfb69e351856bf93083 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 1 Apr 2017 21:33:17 +0100 Subject: [PATCH 110/149] Remove ARMv8 build warning --- src/copro-armnativeasm.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/copro-armnativeasm.S b/src/copro-armnativeasm.S index 90f54740..01d1286d 100644 --- a/src/copro-armnativeasm.S +++ b/src/copro-armnativeasm.S @@ -164,14 +164,15 @@ _user_exec: stmfd sp!, {r0-r3} // Save the _user_exec params bl CleanDataCache ldmfd sp!, {r0-r3} // Restore the _user_exec params + isb #else mov r0, #0 // New code may have just been written to memory, so mcr p15, 0, r0, c7, c10, 0 // Clean entire data cache -#endif + mov r0, #0 mcr p15, 0, r0, c7, c5, 0 // Invalidate entire instruction cache mcr p15, 0, r0, c7, c5, 4 // Flush the prefetch buffer - + #endif mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #CPSR_MODE_USER From 594232a00294f0b64e9961bc2f32dac2f1a47e23 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 2 Apr 2017 09:37:12 +0100 Subject: [PATCH 111/149] Update copro-armnativeasm.S Fix bug in last commit --- src/copro-armnativeasm.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/copro-armnativeasm.S b/src/copro-armnativeasm.S index 01d1286d..6274973f 100644 --- a/src/copro-armnativeasm.S +++ b/src/copro-armnativeasm.S @@ -164,6 +164,9 @@ _user_exec: stmfd sp!, {r0-r3} // Save the _user_exec params bl CleanDataCache ldmfd sp!, {r0-r3} // Restore the _user_exec params + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 // Invalidate entire instruction cache isb #else mov r0, #0 // New code may have just been written to memory, so From 28a6a2bdac509e8fe64e56ac99e8a613fd429e81 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 2 Apr 2017 19:14:48 +0100 Subject: [PATCH 112/149] Improve variable memory for the 32016 core --- src/NS32016/mem32016.c | 2 +- src/tube-client.c | 1 + src/tube-ula.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index d3693d30..443b0190 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -52,7 +52,7 @@ static uint8_t * ns32016ram; void init_ram(void) { if (copro_memory_size >0) - RAM_SIZE = copro_memory_size; + RAM_SIZE = copro_memory_size & ~((128*1024)-1); else RAM_SIZE = MEG1; #ifndef BEM diff --git a/src/tube-client.c b/src/tube-client.c index 19b36fbc..df00aba3 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -129,6 +129,7 @@ void init_emulator() { } #endif + copro &= 127 ; // Clear top bit which is used to signal full reset // Make sure that copro number is valid if (copro >= sizeof(emulator_functions) / sizeof(func_ptr)) { LOG_DEBUG("using default co pro\r\n"); diff --git a/src/tube-ula.c b/src/tube-ula.c index 7e4baf0e..6bd90a06 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -191,6 +191,7 @@ void copro_command_excute(unsigned char copro_command,unsigned char val) if (copro_memory_size > 16 *1024 * 1024) copro_memory_size = 0; LOG_DEBUG("New Copro memory size = %u, %u\r\n", val, copro_memory_size); + copro = copro | 128 ; // Set bit 7 to signal full reset of core return; default : break; From 1f1dd20781fbcb78c34defd07cd53a3014bebd7d Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 3 Apr 2017 19:09:44 +0100 Subject: [PATCH 113/149] Fix lack of NMI ack for slow 6502 copro --- src/copro-65tubeasm.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 432a7531..d8a770e5 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1518,7 +1518,11 @@ handle_irq2: INTR -2, 0 b execute_one_instruction + handle_nmi2: + push {r2,r3,r12} + BL tube_ack_nmi + pop {r2,r3,r12} msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 b execute_one_instruction From 54d258a14c5b1a970ddf17c17e1dbaf548627cc9 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 3 Apr 2017 19:12:55 +0100 Subject: [PATCH 114/149] Ack NMI on Fast 6502 core just to be safe --- src/copro-65tubeasm.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index d8a770e5..7eac0396 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1410,6 +1410,9 @@ handle_irq: FETCH_NEXT_3B_MERGED SUBPC handle_nmi: + push {r2,r3,r12} + BL tube_ack_nmi + pop {r2,r3,r12} msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 FETCH_NEXT_3B_MERGED SUBPC From 59ab7224e66c222c429c2923a2329995d0857bc6 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 3 Apr 2017 22:20:14 +0100 Subject: [PATCH 115/149] Fix V Flag and out of range BCD operations --- src/copro-65tubeasm.S | 99 ++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index 7eac0396..a8c51895 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -618,6 +618,12 @@ .macro SBC_macro reg=r1 tst flags, #8 bic flags, #0x40 +#if defined(USE_MEMORY_POINTER) + orrcc \reg, \reg, #0xff00 + sxthcc \reg, \reg +#else + orrcc \reg, \reg, memry // memry here is a const of 0xFFFFFF00 +#endif FETCH_NEXT_STAGE_0 .if \reg==r0 bne decimal_mode_sbc_r0 @@ -625,12 +631,6 @@ bne decimal_mode_sbc .endif -#if defined(USE_MEMORY_POINTER) - orrcc \reg, \reg, #0xff00 - sxthcc \reg, \reg -#else - orrcc \reg, \reg, memry // memry here is a const of 0xFFFFFF00 -#endif .if \reg==r0 FETCH_NEXT_STAGE_1a_OO sbcs regA, regA, \reg, ror #8 @@ -1411,7 +1411,7 @@ handle_irq: handle_nmi: push {r2,r3,r12} - BL tube_ack_nmi + BL tube_ack_nmi pop {r2,r3,r12} msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 @@ -1536,66 +1536,69 @@ decimal_mode_adc: adc r2, r2, r0, lsr #24 cmp r2, #10 subcs r2, r2, #10 - lsr r1, r1, #4 - lsl r2, r2, #24 - adc regA, r1, regA, lsr #28 - cmp regA, #10 - subcs regA, regA, #10 + and r2, r2, #0x0F + orrcs r1, r1 ,#0x0F + orrcs r1, r1, memry + and regA, regA,#0xF0<<24 + orrcs regA, regA,#0x0F<<24 + adcs regA, regA, r1 , ror #8 + orrvs flags, #0x40 + cmpcc regA, #10<<28 + subcs regA, regA, #10<<28 FETCH_NEXT_STAGE_1 - orr regA, r2, regA, lsl #28 + and regA, regA, #0xF0<<24 + orr regA, regA, r2,lsl #24 teq regA, #0 - orrvs flags, #0x40 FETCH_NEXT_STAGE_2 decimal_mode_sbc: - and r0, regA, #0xf000000 - and r2, r1, #15 - rscs r2, r2, r0, lsr #24 - addcc r2, r2, #10 - lsr r1, r1, #4 - rscs regA, r1, regA, lsr #28 - addcc regA, regA, #10 + bic r0, r1,# 0xf0 + and r2, regA, #0xf000000 + sbc r2, r2, r0, ror #8 FETCH_NEXT_STAGE_1a - orr regA, r2, regA, lsl #4 + sbcs regA, regA, r1, ror #8 FETCH_NEXT_STAGE_1b - lsl regA, regA, #24 - teq regA, #0 orrvs flags, #0x40 + subcc regA, regA,#0x60<<24 + teq r2,#0 + submi regA, regA, #0x6<<24 + teq regA, #0 FETCH_NEXT_STAGE_2 - + decimal_mode_adc_r0: + and r1, regA, #0xf000000 and r2, r0, #15 - lsr r1, r0, #4 - and r0, regA, #0xf000000 - FETCH_NEXT_STAGE_1a_OO - adc r2, r2, r0, lsr #24 + adc r2, r2, r1, lsr #24 cmp r2, #10 subcs r2, r2, #10 - adc regA, r1, regA, lsr #28 - cmp regA, #10 - lsl r2, r2, #24 - subcs regA, regA, #10 - FETCH_NEXT_STAGE_1b_OO - orr regA, r2, regA, lsl #28 - teq regA, #0 + and r2, r2, #0x0F + orrcs r0, r0 ,#0x0F + orrcs r0, r0, memry + and regA, regA,#0xF0<<24 + orrcs regA, regA,#0x0F<<24 + adcs regA, regA, r0 , ror #8 orrvs flags, #0x40 + cmpcc regA, #10<<28 + subcs regA, regA, #10<<28 + FETCH_NEXT_STAGE_1 + and regA, regA, #0xF0<<24 + orr regA, regA, r2,lsl #24 + teq regA, #0 FETCH_NEXT_STAGE_2 decimal_mode_sbc_r0: - and r2, r0, #15 - lsr r1, r0, #4 - and r0, regA, #0xf000000 - FETCH_NEXT_STAGE_1a_OO - rscs r2, r2, r0, lsr #24 - addcc r2, r2, #10 - rscs regA, r1, regA, lsr #28 - addcc regA, regA, #10 - FETCH_NEXT_STAGE_1b_OO - orr regA, r2, regA, lsl #4 + bic r1, r0,# 0xf0 + and r2, regA, #0xf000000 + sbc r2, r2, r1, ror #8 + sbcs regA, regA, r0, ror #8 + FETCH_NEXT_STAGE_1a orrvs flags, #0x40 - lsl regA, regA, #24 + subcc regA, regA,#0x60<<24 + FETCH_NEXT_STAGE_1b + teq r2,#0 + submi regA, regA, #0x6<<24 teq regA, #0 - FETCH_NEXT_STAGE_2 + FETCH_NEXT_STAGE_2 tube_load_handler: push {r0,r2,r3,r5,r12,lr} From 32ef71fb817d59dea70cdcee09cf954f205160a2 Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 4 Apr 2017 19:21:13 +0100 Subject: [PATCH 116/149] Speed Up 6502 NMI acknowledge --- src/copro-65tubeasm.S | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index a8c51895..b9b199e2 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -94,7 +94,8 @@ .equ N_FLAG, 0x80000000 .equ Z_FLAG, 0x40000000 .equ C_FLAG, 0x20000000 - +.equ CPSR_FIQ_INHIBIT, 0x40 +.equ CPSR_IRQ_INHIBIT, 0x80 // Mask used when poping status into flags (RTI, PLP) @@ -102,9 +103,7 @@ // bits 7-0 are 6502 status reg bits // bits 31-8 are emulator control bits .equ R4_MASK, 0xFFFFFF4C - - - + // ********************************************** // Start of macros // ********************************************** @@ -1379,11 +1378,11 @@ exec_65tube_exit: // We get here from the Event handler wh // if USE_MULTICORE is not defined, we have come here via a branch from the second instruction table Event_Handler: - ldr r0, =tube_irq + ldr r1, =tube_irq mrs r2, CPSR // preserve the 6502 flags bic instt, instt, #1024 // ack events - ldrb r0, [r0] + ldrb r0, [r1] sub regPC, regPC, #2 // set the instruction back as we haven't executed it tst r0, #4 // Bit 2 set indicate RST is active @@ -1410,10 +1409,12 @@ handle_irq: FETCH_NEXT_3B_MERGED SUBPC handle_nmi: - push {r2,r3,r12} - BL tube_ack_nmi - pop {r2,r3,r12} - msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts + orr r0,r2, #(CPSR_FIQ_INHIBIT | CPSR_IRQ_INHIBIT) + msr CPSR_c,r0 // Disable interrupts + ldr r0,[r1] // load tube_irq again as it might have changed + BIC r0,r0,#2 // clear NMI flag + str r0,[r1] // Store it back again + msr CPSR_cf, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 FETCH_NEXT_3B_MERGED SUBPC @@ -1451,12 +1452,12 @@ targettime: // we restore the modified table base pointer so we will re-enter this handler Event_Handler_Single_Core_Slow: - ldr r0, =tube_irq + ldr r1, =tube_irq mrs r2, CPSR // preserve the 6502 flags // interrupts are left enabled bic instt, instt, #1024 // ack any events - ldrb r0,[r0] + ldrb r0,[r1] sub regPC, regPC, #2 // set the instruction back as we haven't executed it tst r0,#7 beq noirq2 @@ -1523,10 +1524,12 @@ handle_irq2: handle_nmi2: - push {r2,r3,r12} - BL tube_ack_nmi - pop {r2,r3,r12} - msr CPSR, r2 // Restore the 6502 flags and re-enable ARM interrupts + orr r0,r2, #(CPSR_FIQ_INHIBIT | CPSR_IRQ_INHIBIT) + msr CPSR_c,r0 // Disable interrupts + ldr r0,[r1] // load tube_irq again as it might have changed + BIC r0,r0,#2 // clear NMI flag + str r0,[r1] // Store it back again + msr CPSR_cf, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 b execute_one_instruction From 9069977384bbcdc8e62e2c69435a993c920f84bd Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 4 Apr 2017 20:23:15 +0100 Subject: [PATCH 117/149] Slight improvement to BCD ADC --- src/copro-65tubeasm.S | 63 ++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index b9b199e2..c70f3648 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -586,21 +586,22 @@ FETCH_NEXT_STAGE_2 .endm -.macro ADC_macro reg=r1 +.macro ADC_macro reg=r1 tst flags, #8 bic flags, #0x40 - FETCH_NEXT_STAGE_0 -.if \reg==r0 - bne decimal_mode_adc_r0 -.else - bne decimal_mode_adc -.endif -#if defined(USE_MEMORY_POINTER) +#if defined(USE_MEMORY_POINTER) orrcs \reg, \reg, #0xff00 sxthcs \reg, \reg #else orrcs \reg, \reg, memry // memry has been reused and is 0xFFFFFF00 -#endif +#endif + FETCH_NEXT_STAGE_0 +.if \reg==r0 + bne decimal_mode_adc_r0 +.else + bne decimal_mode_adc +.endif + .if \reg==r0 FETCH_NEXT_STAGE_1a_OO adcs regA, regA, \reg, ror #8 @@ -611,19 +612,19 @@ FETCH_NEXT_STAGE_1b .endif orrvs flags, #0x40 - FETCH_NEXT_STAGE_2 + FETCH_NEXT_STAGE_2 .endm -.macro SBC_macro reg=r1 +.macro SBC_macro reg=r1 tst flags, #8 bic flags, #0x40 -#if defined(USE_MEMORY_POINTER) - orrcc \reg, \reg, #0xff00 +#if defined(USE_MEMORY_POINTER) + orrcc \reg, \reg, #0xff00 sxthcc \reg, \reg #else orrcc \reg, \reg, memry // memry here is a const of 0xFFFFFF00 -#endif - FETCH_NEXT_STAGE_0 +#endif + FETCH_NEXT_STAGE_0 .if \reg==r0 bne decimal_mode_sbc_r0 .else @@ -641,19 +642,19 @@ .endif orrvs flags, #0x40 - FETCH_NEXT_STAGE_2 + FETCH_NEXT_STAGE_2 .endm .macro BRANCH yes no reg=r0 sxtab\yes regPC, regPC, \reg // stall - ldr\yes\()b r5, [regPC] + ldr\yes\()b r5, [regPC] //stall //stall //stall ldr lr, [instt, r5, lsl #2] ldrb r0, [regPC, #1] //hidden in stall - ldrb r5, [regPC, #2]! //hidden in stall + ldrb r5, [regPC, #2]! //hidden in stall FETCH_NEXT_STAGE_2 // 5 cycles // total of 14 if taken. 10 if not taken @@ -1534,23 +1535,24 @@ handle_nmi2: b execute_one_instruction decimal_mode_adc: - and r0, regA, #0xf000000 + // if carry is set the upper 24 bits of R1 are set too + + and r0, regA, #0x0F<<24 and r2, r1, #15 adc r2, r2, r0, lsr #24 cmp r2, #10 subcs r2, r2, #10 and r2, r2, #0x0F orrcs r1, r1 ,#0x0F - orrcs r1, r1, memry - and regA, regA,#0xF0<<24 - orrcs regA, regA,#0x0F<<24 + and regA, regA, #0xF0<<24 + orrcs regA, regA, #0x0F<<24 adcs regA, regA, r1 , ror #8 orrvs flags, #0x40 - cmpcc regA, #10<<28 + cmpcc regA, #10<<28 subcs regA, regA, #10<<28 FETCH_NEXT_STAGE_1 and regA, regA, #0xF0<<24 - orr regA, regA, r2,lsl #24 + orr regA, regA, r2, lsl #24 teq regA, #0 FETCH_NEXT_STAGE_2 @@ -1569,23 +1571,22 @@ decimal_mode_sbc: FETCH_NEXT_STAGE_2 decimal_mode_adc_r0: - and r1, regA, #0xf000000 + and r1, regA, #0x0F<<24 and r2, r0, #15 adc r2, r2, r1, lsr #24 cmp r2, #10 subcs r2, r2, #10 and r2, r2, #0x0F orrcs r0, r0 ,#0x0F - orrcs r0, r0, memry - and regA, regA,#0xF0<<24 - orrcs regA, regA,#0x0F<<24 - adcs regA, regA, r0 , ror #8 + and regA, regA, #0xF0<<24 + orrcs regA, regA, #0x0F<<24 + adcs regA, regA, r0 , ror #8 orrvs flags, #0x40 cmpcc regA, #10<<28 subcs regA, regA, #10<<28 FETCH_NEXT_STAGE_1 and regA, regA, #0xF0<<24 - orr regA, regA, r2,lsl #24 + orr regA, regA, r2, lsl #24 teq regA, #0 FETCH_NEXT_STAGE_2 @@ -1596,7 +1597,7 @@ decimal_mode_sbc_r0: sbcs regA, regA, r0, ror #8 FETCH_NEXT_STAGE_1a orrvs flags, #0x40 - subcc regA, regA,#0x60<<24 + subcc regA, regA, #0x60<<24 FETCH_NEXT_STAGE_1b teq r2,#0 submi regA, regA, #0x6<<24 From ab34499a95a03260d42e702290183742f81dc073 Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 4 Apr 2017 20:56:35 +0100 Subject: [PATCH 118/149] Fix (zp),y lack of wrapping issue --- src/lib6502.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib6502.c b/src/lib6502.c index b79ce772..5c860070 100644 --- a/src/lib6502.c +++ b/src/lib6502.c @@ -208,14 +208,14 @@ byte tmpr; tick(ticks); \ { \ byte tmp= MEM(PC++) + X; \ - ea= MEM(tmp) + (MEM(tmp + 1) << 8); \ + ea= MEM(tmp) + (MEM((tmp + 1)&0xFF) << 8); \ } #define indy(ticks) \ tick(ticks); \ { \ byte tmp= MEM(PC++); \ - ea= MEM(tmp) + (MEM(tmp + 1) << 8); \ + ea= MEM(tmp) + (MEM((tmp + 1)&0xFF) << 8); \ tickIf((ticks == 5) && ((ea >> 8) != ((ea + Y) >> 8))); \ ea += Y; \ } @@ -233,7 +233,7 @@ byte tmpr; { \ byte tmp; \ tmp= MEM(PC++); \ - ea = MEM(tmp) + (MEM(tmp + 1) << 8); \ + ea = MEM(tmp) + (MEM((tmp + 1)&0xFF) << 8); \ } /* insns */ From aa6a4a1358cebf19ad820ba70947242ab64b8816 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 8 Apr 2017 10:01:47 +0100 Subject: [PATCH 119/149] Fix arm native ignoring ULA reset --- src/copro-armnativeasm.S | 5 ++++- src/tube-ula.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/copro-armnativeasm.S b/src/copro-armnativeasm.S index 6274973f..52d8a8b6 100644 --- a/src/copro-armnativeasm.S +++ b/src/copro-armnativeasm.S @@ -121,8 +121,11 @@ copro_armnative_fiq_handler: push {r0} bl tube_io_handler // Update the Tube ULA emulation + and r1, r0, #4 // Get Reset bit which migh have come from + // write to register pop {r0} - + orr r0, r0, r1, LSL #12-2 + bl copro_armnative_tube_interrupt_handler pop {r0-r7, lr} diff --git a/src/tube-ula.c b/src/tube-ula.c index 6bd90a06..8b8df043 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -783,7 +783,7 @@ void tube_init_hardware() } int tube_is_rst_active() { - return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) || ((tube_irq & TUBE_ENABLE_BIT) && (HSTAT1 & HBIT_5)); + return ((RPI_GpioBase->GPLEV0 & NRST_MASK) == 0) ; } #if 0 static void tube_wait_for_rst_active() { From b5166b86bfa24dcf911481c52879a51143a5fbaa Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 10 Apr 2017 19:55:56 +0100 Subject: [PATCH 120/149] Increase speed of variable speed 6502 --- src/copro-65tubeasm.S | 58 +++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/copro-65tubeasm.S b/src/copro-65tubeasm.S index c70f3648..a010cf34 100644 --- a/src/copro-65tubeasm.S +++ b/src/copro-65tubeasm.S @@ -1355,6 +1355,9 @@ exec_65tube: MRC p15, 0, r0, c15, c12, 1 // Read Cycle Counter Register #endif str r0,targettime + ldr lr,=copro_speed + ldr lr,[lr] + str lr,copro_speed6502 handle_rst: orr flags, flags, #4 // Set the I bit @@ -1424,6 +1427,9 @@ lastPC: targettime: .word 0 +copro_speed6502: + .word 0 + // In slowdown we patch the event handler dispatch table to a special event handler (below) // // This implements the following dispatch pattern @@ -1476,27 +1482,27 @@ Event_Handler_Single_Core_Slow: noirq2: ldrb r0, [regPC] // get next instruction - adr r1,timing_table - ldr lr,lastPC - ldrb r0,[r1,r0,LSL#1]! // get instruction time - ldrb r1,[r1,#1] // get instruction length - cmp lr,regPC - ldr lr,=copro_speed - ADDNE r0,r0,#1 + adr r1, timing_table + ldr lr, lastPC + + ldrb r0, [r1,r0,LSL#1]! // get instruction time + ldrb r1, [r1,#1] // get instruction length + cmp lr, regPC + ldr lr, copro_speed6502 // load copro_speed + ADDNE r0, r0, #1 - add r1,r1,regPC - ldr lr,[lr] // load copro_speed - str r1,lastPC + add r1, r1, regPC + str r1, lastPC // get last time - LDR r1,targettime - MUL r0,lr,r0 - + LDR r1, targettime + MUL r0, lr, r0 + ldrb r5, [regPC] // get next instruction // add on new time - ADD lr,r1,r0,LSR #8 // shift by 8 + ADD lr, r1, r0, LSR #8 // shift by 8 // save time new time. - str lr,targettime - + str lr, targettime + // loop until current time(R0) > nexttime(R1) ( nb deal with wrap around) waste_time: #if defined(RPI2)|| defined(RPI3) @@ -1504,17 +1510,15 @@ waste_time: #else MRC p15, 0, lr, c15, c12, 1 // Read Cycle Counter Register #endif - sub lr,lr,r1 // if this goes negative we are running too slow - CMP lr,r0,LSR #8 + sub lr, lr, r1 // if this goes negative we are running too slow + CMP lr, r0, LSR #8 BCC waste_time msr CPSR, r2 // restore the 6502 flags -execute_one_instruction: - ldrb r2, [regPC] // same as FETCH_NEXT_STAGE_012 but set bit in instt to return immediately to event handler + ldr lr, [instt, r5, lsl #2] ldrb r0, [regPC, #1] ldrb r5, [regPC, #2]! - ldr lr, [instt, r2, lsl #2] orr instt, instt, #1024 // Return to event handler after next instruction dispatch bx lr @@ -1526,13 +1530,19 @@ handle_irq2: handle_nmi2: orr r0,r2, #(CPSR_FIQ_INHIBIT | CPSR_IRQ_INHIBIT) - msr CPSR_c,r0 // Disable interrupts + msr CPSR_c,r0 // Disable interrupts ldr r0,[r1] // load tube_irq again as it might have changed BIC r0,r0,#2 // clear NMI flag str r0,[r1] // Store it back again - msr CPSR_cf, r2 // Restore the 6502 flags and re-enable ARM interrupts + msr CPSR_cf, r2 // Restore the 6502 flags and re-enable ARM interrupts INTR -6, 0 - b execute_one_instruction +execute_one_instruction: + ldrb r2, [regPC] // same as FETCH_NEXT_STAGE_012 but set bit in instt to return immediately to event handler + ldrb r0, [regPC, #1] + ldrb r5, [regPC, #2]! + ldr lr, [instt, r2, lsl #2] + orr instt, instt, #1024 // Return to event handler after next instruction dispatch + bx lr decimal_mode_adc: // if carry is set the upper 24 bits of R1 are set too From 5b6972521892c511aa4c905b15114145c3073c38 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 10 Apr 2017 21:31:48 +0100 Subject: [PATCH 121/149] Malloc serial tx buffer --- src/rpi-aux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rpi-aux.c b/src/rpi-aux.c index 03907a09..c05932e9 100644 --- a/src/rpi-aux.c +++ b/src/rpi-aux.c @@ -4,6 +4,7 @@ #include "rpi-gpio.h" #include "info.h" #include "startup.h" +#include "stdlib.h" #ifdef INCLUDE_DEBUGGER #include "debugger/debugger.h" @@ -32,7 +33,7 @@ aux_t* RPI_GetAux(void) // Note, at the point the MiniUART is initialized, low vectors are in use #define IRQ_VECTOR 0x38 -static char tx_buffer[TX_BUFFER_SIZE]; +static char *tx_buffer; static volatile int tx_head; static volatile int tx_tail; @@ -110,6 +111,7 @@ void RPI_AuxMiniUartInit(int baud, int bits) auxillary->MU_BAUD = ( sys_freq / (8 * baud)) - 1; #ifdef USE_IRQ + tx_buffer = malloc(TX_BUFFER_SIZE); tx_head = tx_tail = 0; *((uint32_t *) IRQ_VECTOR) = (uint32_t) RPI_AuxMiniUartIRQHandler; RPI_GetIrqController()->Enable_IRQs_1 = (1 << 29); From bb2b164ca8241cb0db6bd34322ce2c8bd51e6880 Mon Sep 17 00:00:00 2001 From: dp111 Date: Tue, 11 Apr 2017 18:34:33 +0100 Subject: [PATCH 122/149] Remove clearing RPI property buffer as it is about to be overwritten --- src/rpi-mailbox-interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpi-mailbox-interface.c b/src/rpi-mailbox-interface.c index ecad8b6a..05046307 100644 --- a/src/rpi-mailbox-interface.c +++ b/src/rpi-mailbox-interface.c @@ -15,7 +15,7 @@ static int pt_index ; void RPI_PropertyInit( void ) { - memset(pt, 0, sizeof(pt)); + //memset(pt, 0, sizeof(pt)); /* Fill in the size on-the-fly */ pt[PT_OSIZE] = 12; From 9d5c2beff66fc97f0a6c2b07048a3e494da7f5aa Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:19:56 +0100 Subject: [PATCH 123/149] Don't print core spinning debug --- src/armc-start.S | 68 ++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/armc-start.S b/src/armc-start.S index 21fe966b..f1f5dfab 100644 --- a/src/armc-start.S +++ b/src/armc-start.S @@ -29,9 +29,9 @@ #include "tube-defs.h" -.equ STACK_SIZE, 0x00100000 +.equ STACK_SIZE, 0x00100000 -.equ C0_SVR_STACK, 0 +.equ C0_SVR_STACK, 0 .equ C0_IRQ_STACK, (STACK_SIZE*1) .equ C0_FIQ_STACK, STACK_SIZE*2 .equ C0_USER_STACK, STACK_SIZE*4 @@ -68,7 +68,7 @@ .global _clean_invalidate_dcache_mva .global _invalidate_dtlb .global _invalidate_dtlb_mva - + #ifdef HAS_MULTICORE .global _get_core .global _init_core @@ -78,7 +78,7 @@ #if defined(HAS_40PINS) .global _toggle_test_pin #endif - + // From the ARM ARM (Architecture Reference Manual). Make sure you get the // ARMv5 documentation which includes the ARMv6 documentation which is the // correct processor type for the Broadcom BCM2835. The ARMv6-M manuals @@ -114,7 +114,7 @@ _start: ldr pc, _interrupt_vector_h ldr pc, _fast_interrupt_vector_h -_reset_h: .word _reset_ +_reset_h: .word _reset_ _undefined_instruction_vector_h: .word _undefined_instruction_handler_ _software_interrupt_vector_h: .word _swi_handler_ _prefetch_abort_vector_h: .word _prefetch_abort_handler_ @@ -129,7 +129,7 @@ _reset_: #ifdef HAS_MULTICORE #ifdef KERNEL_OLD - + // if kernel_old=1 all cores are running and we need to sleep 1-3 // if kernel_old=0 then just core0 is running, and core 1-3 are waiting // on a mailbox write to be woken up. @@ -141,11 +141,11 @@ _reset_: // Put cores 1-3 into a tight loop _core_loop: wfi - b _core_loop + b _core_loop _core_continue: #else - + // if kernel_old=0 enter in HYP mode and need to force a switch to SVC mode // // for now we assume kernel_old=1 and don't execute this core @@ -170,7 +170,7 @@ _reset_continue: #endif #endif - + // We enter execution in supervisor mode. For more information on // processor modes see ARM Section A2.2 (Processor Modes) @@ -183,7 +183,7 @@ _reset_continue: // Initialise Stack Pointers --------------------------------------------- ldr r4,=_start - + // We're going to use interrupt mode, so setup the interrupt mode // stack pointer which differs to the application stack pointer: mov r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT ) @@ -257,12 +257,12 @@ _reset_continue: _get_stack_pointer: mov r0, sp mov pc, lr - + .section ".text._get_cpsr" _get_cpsr: mrs r0, cpsr mov pc, lr - + .section ".text._enable_interrupts" _enable_interrupts: mrs r0, cpsr @@ -285,7 +285,7 @@ _undefined_instruction_handler_: mov r0, sp bl undefined_instruction_handler -.section ".text._prefetch_abort_handler_" +.section ".text._prefetch_abort_handler_" _prefetch_abort_handler_: stmfd sp!, {r0-r12, lr} mrs r0, spsr // Get spsr. @@ -293,7 +293,7 @@ _prefetch_abort_handler_: mov r0, sp bl prefetch_abort_handler -.section ".text._data_abort_handler_" +.section ".text._data_abort_handler_" _data_abort_handler_: stmfd sp!, {r0-r12, lr} mrs r0, spsr // Get spsr. @@ -301,7 +301,7 @@ _data_abort_handler_: mov r0, sp bl data_abort_handler -.section ".text._swi_handler_" +.section ".text._swi_handler_" _swi_handler_: stmfd sp!, {r0-r12, lr} mrs r0, spsr // Get spsr. @@ -339,40 +339,40 @@ _invalidate_icache: mov r0, #0 mcr p15, 0, r0, c7, c5, 0 mov pc, lr - + .section ".text._invalidate_dcache" _invalidate_dcache: mov r0, #0 mcr p15, 0, r0, c7, c6, 0 mov pc, lr - + .section ".text._clean_invalidate_dcache" _clean_invalidate_dcache: mov r0, #0 mcr p15, 0, r0, c7, c14, 0 mov pc, lr - + .section ".text._invalidate_dcache_mva" _invalidate_dcache_mva: mcr p15, 0, r0, c7, c6, 1 mov pc, lr - + .section ".text._clean_invalidate_dcache_mva" _clean_invalidate_dcache_mva: mcr p15, 0, r0, c7, c14, 1 mov pc, lr - + .section ".text._invalidate_dtlb" _invalidate_dtlb: mov r0, #0 mcr p15, 0, r0, c8, c6, 0 mov pc, lr - + .section ".text._invalidate_dtlb_mva" _invalidate_dtlb_mva: mcr p15, 0, r0, c8, c6, 1 mov pc, lr - + #ifdef USE_MULTICORE _init_core: @@ -443,40 +443,40 @@ _init_continue: #endif #ifdef HAS_MULTICORE - + // If main does return for some reason, just catch it and stay here. _spin_core: -#ifdef DEBUG - mov r0, #'S' +#ifdef DEBUG_Multicore + mov r0, #'S' bl RPI_AuxMiniUartWrite - mov r0, #'P' + mov r0, #'P' bl RPI_AuxMiniUartWrite - mov r0, #'I' + mov r0, #'I' bl RPI_AuxMiniUartWrite - mov r0, #'N' + mov r0, #'N' bl RPI_AuxMiniUartWrite bl _get_core add r0, r0, #'0' bl RPI_AuxMiniUartWrite - mov r0, #'\r' + mov r0, #'\r' bl RPI_AuxMiniUartWrite - mov r0, #'\n' + mov r0, #'\n' bl RPI_AuxMiniUartWrite -#endif +#endif _spin_core1: wfi b _spin_core1 - + _get_core: mrc p15, 0, r0, c0, c0, 5 and r0, #3 mov pc, lr - + #endif #ifdef HAS_40PINS .section ".text._toggle_test_pin" -_toggle_test_pin: +_toggle_test_pin: mov r1, #TEST_MASK _toggle_test_pin_loop: ldr r2, =GPSET0 From 377b03196d2dc3ff7211a2c18afbd70add097473 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:21:15 +0100 Subject: [PATCH 124/149] Don't print so much debug --- src/cache.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cache.c b/src/cache.c index 2b0af620..281bde80 100644 --- a/src/cache.c +++ b/src/cache.c @@ -133,7 +133,7 @@ void enable_MMU_and_IDCaches(void) { LOG_DEBUG("enable_MMU_and_IDCaches\r\n"); - LOG_DEBUG("cpsr = %08x\r\n", _get_cpsr()); + //LOG_DEBUG("cpsr = %08x\r\n", _get_cpsr()); unsigned i; unsigned base; @@ -223,7 +223,7 @@ void enable_MMU_and_IDCaches(void) #if defined(RPI3) unsigned cpuextctrl0, cpuextctrl1; asm volatile ("mrrc p15, 1, %0, %1, c15" : "=r" (cpuextctrl0), "=r" (cpuextctrl1)); - LOG_DEBUG("extctrl = %08x %08x\r\n", cpuextctrl1, cpuextctrl0); + //LOG_DEBUG("extctrl = %08x %08x\r\n", cpuextctrl1, cpuextctrl0); #else // RPI: bit 6 of auxctrl is restrict cache size to 16K (no page coloring) // RPI2: bit 6 of auxctrl is set SMP bit, otherwise all caching disabled @@ -232,7 +232,7 @@ void enable_MMU_and_IDCaches(void) auxctrl |= 1 << 6; asm volatile ("mcr p15, 0, %0, c1, c0, 1" :: "r" (auxctrl)); asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctrl)); - LOG_DEBUG("auxctrl = %08x\r\n", auxctrl); + //LOG_DEBUG("auxctrl = %08x\r\n", auxctrl); #endif // set domain 0 to client @@ -243,7 +243,7 @@ void enable_MMU_and_IDCaches(void) unsigned ttbcr; asm volatile ("mrc p15, 0, %0, c2, c0, 2" : "=r" (ttbcr)); - LOG_DEBUG("ttbcr = %08x\r\n", ttbcr); + //LOG_DEBUG("ttbcr = %08x\r\n", ttbcr); #if defined(RPI2) || defined(RPI3) // set TTBR0 - page table walk memory cacheability/shareable @@ -259,7 +259,7 @@ void enable_MMU_and_IDCaches(void) #endif unsigned ttbr0; asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r" (ttbr0)); - LOG_DEBUG("ttbr0 = %08x\r\n", ttbr0); + //LOG_DEBUG("ttbr0 = %08x\r\n", ttbr0); // Invalidate entire data cache @@ -288,11 +288,11 @@ void enable_MMU_and_IDCaches(void) sctrl |= 0x00001805; asm volatile ("mcr p15,0,%0,c1,c0,0" :: "r" (sctrl) : "memory"); asm volatile ("mrc p15,0,%0,c1,c0,0" : "=r" (sctrl)); - LOG_DEBUG("sctrl = %08x\r\n", sctrl); + //LOG_DEBUG("sctrl = %08x\r\n", sctrl); // For information, show the cache type register // From this you can tell what type of cache is implemented unsigned ctype; asm volatile ("mrc p15,0,%0,c0,c0,1" : "=r" (ctype)); - LOG_DEBUG("ctype = %08x\r\n", ctype); + //LOG_DEBUG("ctype = %08x\r\n", ctype); } From b37e0f337472a3719a472c35267f2e3ea742a536 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:24:34 +0100 Subject: [PATCH 125/149] Tidy up debug output --- src/info.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/info.c b/src/info.c index d9ad1590..51f6d937 100644 --- a/src/info.c +++ b/src/info.c @@ -131,7 +131,7 @@ char *get_cmdline_prop(char *prop) { int proplen = strlen(prop); // continue until the end terminator - while (cmdptr && *cmdptr) { + while (cmdptr && *cmdptr) { // compare the property name if (strncasecmp(cmdptr, prop, proplen) == 0) { // check for an equals in the expected place @@ -225,6 +225,11 @@ void dump_useful_info() { }; int n = sizeof(tags) / sizeof(rpi_mailbox_tag_t); + LOG_INFO("\r\n"); // put some new lines in the serial stream as we don't know what is currently on the terminal + LOG_INFO("\r\n"); + LOG_INFO("********** Raspberry Pi BBC Micro Coprocessor **********\r\n"); + LOG_INFO("\r\n"); + LOG_INFO("\r\n"); RPI_PropertyInit(); for (i = 0; i < n ; i++) { @@ -232,7 +237,7 @@ void dump_useful_info() { } RPI_PropertyProcess(); - + for (i = 0; i < n; i++) { buf = RPI_PropertyGet(tags[i]); print_tag_value(tagnames[i], buf, 1); @@ -255,7 +260,10 @@ void dump_useful_info() { LOG_INFO(" SDRAM_I VOLTAGE : %6.2f V\r\n", get_voltage(COMPONENT_SDRAM_I)); LOG_INFO(" CMD_LINE : %s\r\n", get_cmdline()); - - LOG_INFO(" COPRO : %s\r\n", get_cmdline_prop("copro")); + char *cs ; + cs = get_cmdline_prop("copro"); + if (!cs) + cs = "0 (default)"; + LOG_INFO(" COPRO : %s\r\n", cs); } From 7b7f43f766b8f0da6ebd82a82059576eaf4791bc Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:26:20 +0100 Subject: [PATCH 126/149] Make benchmark default to not be compiled --- src/performance.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/performance.c b/src/performance.c index bee55df8..95a441ca 100644 --- a/src/performance.c +++ b/src/performance.c @@ -205,7 +205,7 @@ void print_performance_counters(perf_counters_t *pct) { printf("%26s = %u\r\n", type_lookup(pct->type[i]), pct->counter[i]); } } - +#ifdef BENCHMARK int benchmark() { int i; int total; @@ -273,3 +273,4 @@ int benchmark() { return total; } +#endif From f438a99dd87a99d040a2d9e6e9a17205c21bca82 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:27:40 +0100 Subject: [PATCH 127/149] Define pt buffer to be in uncached memory --- src/rpi-mailbox-interface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpi-mailbox-interface.c b/src/rpi-mailbox-interface.c index 05046307..99a0ad07 100644 --- a/src/rpi-mailbox-interface.c +++ b/src/rpi-mailbox-interface.c @@ -4,11 +4,12 @@ #include "rpi-mailbox.h" #include "rpi-mailbox-interface.h" +#include "cache.h" /* Make sure the property tag buffer is aligned to a 16-byte boundary because we only have 28-bits available in the property interface protocol to pass the address of the buffer to the VC. */ -static int pt[PROP_BUFFER_SIZE] __attribute__((aligned(16))); +static int *pt = ( int *) UNCACHED_MEM_BASE ;// [PROP_BUFFER_SIZE] __attribute__((aligned(16))); static int pt_index ; //#define PRINT_PROP_DEBUG 1 From c14709a90f8c528c9f7ed3a68a88f944819f9518 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 14 Apr 2017 21:37:12 +0100 Subject: [PATCH 128/149] Move over to GPU setting up of databus driving --- src/tube-ula.c | 42 +++++++++++++++--------------------------- src/tubevc.c | 48 ++++++++++++++++++++++++------------------------ vidcore/tubevc.s | 32 +++++++++++++++----------------- 3 files changed, 54 insertions(+), 68 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index 8b8df043..b80dac32 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -44,7 +44,7 @@ #include "tubevc.h" #include "startup.h" -static volatile uint32_t *tube_regs; +static volatile uint32_t *tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; #define HBIT_7 (1 << 25) #define HBIT_6 (1 << 24) @@ -58,9 +58,6 @@ static volatile uint32_t *tube_regs; #define BYTE_TO_WORD(data) ((((data) & 0x0F) << 8) | (((data) & 0xF0) << 18)) #define WORD_TO_BYTE(data) ((((data) >> 8) & 0x0F) | (((data) << 18) & 0xF0)) - -static volatile uint32_t gpfsel_data_idle[6]; - const static uint32_t magic[3] = {MAGIC_C0, MAGIC_C1, MAGIC_C2 | MAGIC_C3 }; static char copro_command =0; static perf_counters_t pct; @@ -700,8 +697,6 @@ int tube_io_handler(uint32_t mail) void tube_init_hardware() { - - int i; // Write 1 to the LED init nibble in the Function Select GPIO // peripheral register to enable LED pin as an output RPI_GpioBase->LED_GPFSEL |= LED_GPFBIT; @@ -731,8 +726,7 @@ void tube_init_hardware() RPI_SetGpioPinFunction(TEST3_PIN, FS_OUTPUT); #endif - // Initialise the UART to 57600 baud - RPI_AuxMiniUartInit( 115200, 8 ); + // Initialise the info system with cached values (as we break the GPU property interface) init_info(); @@ -741,19 +735,13 @@ void tube_init_hardware() dump_useful_info(); #endif - // Precalculate the values that need to be written to the FSEL registers - // to set the data bus GPIOs as inputs (idle) and output (driving) - for (i = 0; i < 3; i++) { - gpfsel_data_idle[i] = (uint32_t) RPI_GpioBase->GPFSEL[i]; - gpfsel_data_idle[i+3] = gpfsel_data_idle[i] | magic[i]; - LOG_DEBUG("%d %010o %010o\r\n", i, (unsigned int) gpfsel_data_idle[i], (unsigned int) gpfsel_data_idle[i+3]); - } - // Print the GPIO numbers of A0, A1 and A2 +#ifdef DEBUG_GPU LOG_DEBUG("A0 = GPIO%02d = mask %08x\r\n", A0_PIN, A0_MASK); LOG_DEBUG("A1 = GPIO%02d = mask %08x\r\n", A1_PIN, A1_MASK); LOG_DEBUG("A2 = GPIO%02d = mask %08x\r\n", A2_PIN, A2_MASK); - +#endif + // Initialize performance counters #if defined(RPI2) || defined(RPI3) pct.num_counters = 6; @@ -777,9 +765,9 @@ void tube_init_hardware() pct.counter[1] = 0; #endif - tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; - hp1 = hp2 = hp4 = hp3[0]= hp3[1]=0; + + // RPI_GpioBase->GPSET0 = (1 << TEST_PIN); } int tube_is_rst_active() { @@ -862,16 +850,16 @@ void disable_tube() { } // todo : we need to sort out caches memory map etc here void start_vc_ula() -{ int func,r0,r1, r2,r3,r4,r5; - +{ + int func,r0,r1, r2,r3,r4,r5; func = (int) &tubevc_asm[0]; r0 = (int) GPU_TUBE_REG_ADDR; // address of tube register block in IO space - r1 = (int) &gpfsel_data_idle; // gpfsel_data_idle - r2 = 0; + r1 = magic[0]; // data bus drive + r2 = magic[1]; r3 = (A2_PIN << 16) | (A1_PIN << 8) | (A0_PIN); // address bus GPIO mapping - r4 = 0; + r4 = magic[2]; #ifdef HAS_40PINS r5 = TEST_MASK; // test pin #else @@ -884,9 +872,8 @@ void start_vc_ula() if (r0) { r0 |= 0x40000000; } - if (r2) { - r2 |= 0x40000000; - } +#ifdef DEBUG_GPU + LOG_DEBUG("Staring VC ULA\r\n"); LOG_DEBUG("VidCore code = %08x\r\n", func); LOG_DEBUG("VidCore r0 = %08x\r\n", r0); LOG_DEBUG("VidCore r1 = %08x\r\n", r1); @@ -894,6 +881,7 @@ void start_vc_ula() LOG_DEBUG("VidCore r3 = %08x\r\n", r3); LOG_DEBUG("VidCore r4 = %08x\r\n", r4); LOG_DEBUG("VidCore r5 = %08x\r\n", r5); +#endif RPI_PropertyInit(); RPI_PropertyAddTag(TAG_EXECUTE_CODE,func,r0,r1,r2,r3,r4,r5); RPI_PropertyProcessNoCheck(); diff --git a/src/tubevc.c b/src/tubevc.c index d85b4a87..508379b4 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -1,26 +1,26 @@ unsigned char tubevc_asm[] = { - 0x05, 0x00, 0x09, 0xe8, 0x00, 0x0f, 0xc0, 0x03, 0x1a, 0x08, 0x1b, 0x21, - 0x1c, 0x22, 0x1d, 0x23, 0x1e, 0x24, 0x1f, 0x25, 0x50, 0xc3, 0x40, 0x1f, - 0xf0, 0xc0, 0x5f, 0x87, 0x51, 0xc3, 0x48, 0x1f, 0xf1, 0xc0, 0x5f, 0x8f, - 0x52, 0xc3, 0x50, 0x1f, 0xf2, 0xc0, 0x5f, 0x97, 0x01, 0xe8, 0x10, 0x0f, - 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, - 0x12, 0x0f, 0x03, 0xe8, 0x80, 0xb8, 0x00, 0x7e, 0x04, 0x60, 0x06, 0xe8, - 0x00, 0x00, 0x20, 0x7e, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, - 0x54, 0x00, 0x18, 0x6d, 0xfb, 0x18, 0x68, 0x2d, 0x18, 0x6d, 0xf8, 0x18, - 0x28, 0x6d, 0x2c, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, - 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, - 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, - 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, - 0x10, 0x47, 0x05, 0x18, 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, - 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, 0x65, 0x3a, 0x69, 0x3a, 0x6a, 0x09, - 0x6b, 0x31, 0x6c, 0x32, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, - 0xcc, 0x18, 0x27, 0x6d, 0xca, 0x18, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, - 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, 0x47, 0xc3, 0x48, 0x47, - 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, 0xe4, 0xe8, 0xf0, 0x00, - 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, 0x07, 0xc2, 0xc8, 0x38, - 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, 0x88, 0xc1, 0x12, 0x47, - 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, 0xab, 0xff, 0x07, 0xe8, - 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, - 0x7f, 0x9e, 0xa2, 0xff + 0x05, 0x00, 0x09, 0xe8, 0x00, 0x0f, 0xc0, 0x03, 0x59, 0x4d, 0x50, 0xc3, + 0x40, 0x1f, 0xf0, 0xc0, 0x5f, 0x87, 0x51, 0xc3, 0x48, 0x1f, 0xf1, 0xc0, + 0x5f, 0x8f, 0x52, 0xc3, 0x50, 0x1f, 0xf2, 0xc0, 0x5f, 0x97, 0x03, 0xe8, + 0x80, 0xb8, 0x00, 0x7e, 0x06, 0xe8, 0x00, 0x00, 0x20, 0x7e, 0x6a, 0x08, + 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, + 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, + 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x07, 0x40, + 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0xfb, 0x18, + 0x68, 0x2d, 0x18, 0x6d, 0xf8, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, + 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, + 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, + 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, + 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x05, 0x18, 0x07, 0x46, + 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, + 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, 0x67, 0x2d, 0x77, 0x6c, + 0x7e, 0x18, 0x17, 0x6d, 0xcd, 0x18, 0x27, 0x6d, 0xcb, 0x18, 0x67, 0x2d, + 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, + 0x47, 0xc3, 0x48, 0x47, 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, + 0xe4, 0xe8, 0xf0, 0x00, 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, + 0x07, 0xc2, 0xc8, 0x38, 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, + 0x88, 0xc1, 0x12, 0x47, 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, + 0xac, 0xff, 0x07, 0xe8, 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, + 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0xa3, 0xff }; -unsigned int tubevc_asm_len = 268; +unsigned int tubevc_asm_len = 272; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index d31ea004..a1bed803 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -99,13 +99,7 @@ # st r9, (r8) mov r9, (0xF< Date: Fri, 14 Apr 2017 21:40:37 +0100 Subject: [PATCH 129/149] Reorder code so the cache can be enabled sooner. Remove delays to improve boot performance --- src/tube-client.c | 49 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/tube-client.c b/src/tube-client.c index df00aba3..62ffa169 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -10,6 +10,7 @@ #include "cache.h" #include "performance.h" #include "info.h" +#include "rpi-gpio.h" typedef void (*func_ptr)(); @@ -224,53 +225,36 @@ static void get_copro_memory_size() { void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) { -#ifdef HAS_MULTICORE - volatile int i; -#endif - + // Initialise the UART to 57600 baud + RPI_AuxMiniUartInit( 115200, 8 ); + enable_MMU_and_IDCaches(); + _enable_unaligned_access(); tube_init_hardware(); + + arm_speed = get_clock_rate(ARM_CLK_ID); + + + start_vc_ula(); + copro = get_copro_number(); get_copro_speed(); get_copro_memory_size(); - LOG_DEBUG("Staring VC ULA\r\n"); - start_vc_ula(); - LOG_DEBUG("Done\r\n"); - - enable_MMU_and_IDCaches(); - _enable_unaligned_access(); - -#ifdef DEBUG +#ifdef BENCHMARK // Run a short set of CPU and Memory benchmarks benchmark(); #endif - init_emulator(); - - // Lock the Tube Interrupt handler into cache for BCM2835 based Pis - #ifdef HAS_MULTICORE - LOG_DEBUG("main running on core %u\r\n", _get_core()); - for (i = 0; i < 10000000; i++); start_core(1, _spin_core); - for (i = 0; i < 10000000; i++); start_core(2, _spin_core); - for (i = 0; i < 10000000; i++); - -#ifdef USE_MULTICORE - start_core(3, _init_core); - while (1); -#else start_core(3, _spin_core); - for (i = 0; i < 10000000; i++); #endif - -#endif - -#ifndef USE_MULTICORE - + init_emulator(); + +RPI_GpioBase->GPSET0 = (1 << TEST_PIN); do { // Run the emulator emulator(); @@ -279,6 +263,5 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) init_emulator(); } while (1); - -#endif + } From 83e4788b041e47f29228e55e826c193c5d770d87 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 15 Apr 2017 15:12:48 +0100 Subject: [PATCH 130/149] Use GPU L1 cache --- src/tube-ula.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/tube-ula.c b/src/tube-ula.c index b80dac32..bf4b8a3b 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -848,7 +848,7 @@ void disable_tube() { tube_regs[i] = 0xfe; } } -// todo : we need to sort out caches memory map etc here + void start_vc_ula() { int func,r0,r1, r2,r3,r4,r5; @@ -865,13 +865,7 @@ void start_vc_ula() #else r5 = 0; #endif - // re-map to bus addresses - // if the L2 cache is enabled, the VC MMU maps physical memory to 0x40000000 - // if the L2 cache is disabled, the VC MMU maps physical memory to 0xC0000000 - // https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes - if (r0) { - r0 |= 0x40000000; - } + #ifdef DEBUG_GPU LOG_DEBUG("Staring VC ULA\r\n"); LOG_DEBUG("VidCore code = %08x\r\n", func); From 9c7ff844b062aba36b6ce8e6f824cc7c22d739bf Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 15 Apr 2017 15:13:51 +0100 Subject: [PATCH 131/149] Improve Host Read Data setup time by 25ns --- src/tubevc.c | 4 ++-- vidcore/tubevc.s | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index 508379b4..7a8426f0 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -6,8 +6,8 @@ unsigned char tubevc_asm[] = { 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x07, 0x40, - 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0xfb, 0x18, - 0x68, 0x2d, 0x18, 0x6d, 0xf8, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, + 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, + 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index a1bed803..629684ea 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -132,13 +132,13 @@ # poll for nTube being low Poll_loop: mov r7, r0 -Poll_tube_low: ld r8, GPLEV0_offset(r6) +Poll_tube_low: btst r8, nRST beq post_reset btst r8, nTUBE - bne Poll_tube_low ld r8, GPLEV0_offset(r6) # check ntube again to remove glitches + bne Poll_tube_low btst r8, nTUBE bne Poll_tube_low # we now know nTube is low From 614367846b399c3440c0e030c702c5b3091c5512 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 15 Apr 2017 16:10:14 +0100 Subject: [PATCH 132/149] Enable cache as soon as possible to reduce boot time --- src/armc-start.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/armc-start.S b/src/armc-start.S index f1f5dfab..455b54de 100644 --- a/src/armc-start.S +++ b/src/armc-start.S @@ -125,7 +125,7 @@ _fast_interrupt_vector_h: .word arm_fiq_handler .section ".text._reset_" _reset_: - + BL _enable_l1_cache #ifdef HAS_MULTICORE #ifdef KERNEL_OLD @@ -250,6 +250,7 @@ _reset_continue: // initialise the ro data section (most things that have the const // declaration) and initialise the bss section variables to 0 (generally // known as automatics). It'll then call main + b _cstartup From e14fa473f8822a78bdc55de8147c8963acaf0a60 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 15 Apr 2017 16:12:12 +0100 Subject: [PATCH 133/149] Tweak the pipeline --- src/tubevc.c | 4 ++-- vidcore/tubevc.s | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index 7a8426f0..d3002027 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -5,8 +5,8 @@ unsigned char tubevc_asm[] = { 0x80, 0xb8, 0x00, 0x7e, 0x06, 0xe8, 0x00, 0x00, 0x20, 0x7e, 0x6a, 0x08, 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, - 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x07, 0x40, - 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, + 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x68, 0x2d, + 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 629684ea..7d1bcb69 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -131,8 +131,8 @@ # poll for nTube being low Poll_loop: - mov r7, r0 ld r8, GPLEV0_offset(r6) + mov r7, r0 Poll_tube_low: btst r8, nRST beq post_reset From 2d74d46d68e67fbfd2a50cfe722a317d3e1843db Mon Sep 17 00:00:00 2001 From: dp111 Date: Sat, 15 Apr 2017 20:54:02 +0100 Subject: [PATCH 134/149] Speed up booting --- src/scripts/config.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripts/config.txt b/src/scripts/config.txt index cb4cbd82..adef274d 100644 --- a/src/scripts/config.txt +++ b/src/scripts/config.txt @@ -43,8 +43,10 @@ force_turbo=1 # Disable adjusting the refresh rate of RAM every 500 ms disable_pvt=1 - +hdmi_ignore_edid=0xa5000080 +hdmi_ignore_hotplug=1 boot_delay=0 + kernel_address=0x1f00000 gpu_mem=16 start_file=start_cd.elf From 0a09f4a91c69773f0290181ad7b113715dc069c5 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 16 Apr 2017 12:31:33 +0100 Subject: [PATCH 135/149] Fixed a compile error with the non-40-pin builds Change-Id: Iebbec8edd84fa68387231a4df8ffa78d9f80f0cd --- src/tube-client.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tube-client.c b/src/tube-client.c index 62ffa169..03acdc64 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -253,8 +253,11 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) start_core(3, _spin_core); #endif init_emulator(); - -RPI_GpioBase->GPSET0 = (1 << TEST_PIN); + +#ifdef HAS_40PINS + RPI_GpioBase->GPSET0 = (1 << TEST_PIN); +#endif + do { // Run the emulator emulator(); From 31085b256b45aef16c6ba6a102d652302a632332 Mon Sep 17 00:00:00 2001 From: dp111 Date: Sun, 16 Apr 2017 17:56:47 +0100 Subject: [PATCH 136/149] check nTube again incase of glitches --- src/tubevc.c | 29 +++++++++++++++-------------- vidcore/tubevc.s | 38 +++++++------------------------------- 2 files changed, 22 insertions(+), 45 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index d3002027..0757c9c5 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -6,21 +6,22 @@ unsigned char tubevc_asm[] = { 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x68, 0x2d, - 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, - 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, + 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x57, 0x00, 0x18, 0x6d, 0x68, 0x2d, + 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2d, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, - 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x05, 0x18, 0x07, 0x46, - 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, - 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, 0x67, 0x2d, 0x77, 0x6c, - 0x7e, 0x18, 0x17, 0x6d, 0xcd, 0x18, 0x27, 0x6d, 0xcb, 0x18, 0x67, 0x2d, - 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, - 0x47, 0xc3, 0x48, 0x47, 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, - 0xe4, 0xe8, 0xf0, 0x00, 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, - 0x07, 0xc2, 0xc8, 0x38, 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, - 0x88, 0xc1, 0x12, 0x47, 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, - 0xac, 0xff, 0x07, 0xe8, 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, - 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0xa3, 0xff + 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x07, 0x18, 0x18, 0x6d, + 0x85, 0x18, 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x67, 0x2d, + 0x77, 0x6c, 0xfe, 0x18, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, + 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcb, 0x18, 0x27, 0x6d, + 0xc9, 0x18, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, + 0x77, 0x6c, 0xfd, 0x18, 0x18, 0x6d, 0xc0, 0x18, 0x47, 0xc3, 0x48, 0x47, + 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, 0xe4, 0xe8, 0xf0, 0x00, + 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, 0x07, 0xc2, 0xc8, 0x38, + 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, 0x88, 0xc1, 0x12, 0x47, + 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, 0xa8, 0xff, 0x07, 0xe8, + 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, + 0x7f, 0x9e, 0x9f, 0xff }; -unsigned int tubevc_asm_len = 272; +unsigned int tubevc_asm_len = 280; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 7d1bcb69..0c08378c 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -170,6 +170,8 @@ rd_wait_for_clk_high1: # we now have half a cycle to do post mail btst r8, r16 # no need to post mail if A0 = 0 beq rd_wait_for_clk_low + btst r8, nTUBE # double check nTUBE is low + bne rd_wait_for_clk_low sub r7, r0 # just get the address bits lsl r7, 6 # put address bits in correct place bset r7, RW_MAILBOX_BIT # set read bit @@ -213,6 +215,10 @@ wr_wait_for_clk_low: btst r7, CLK bne wr_wait_for_clk_low +# check that ntube is stil low to ensure we have a valid cycle + btst r8, nTUBE + bne Poll_loop + # Post a message to indicate a tube register write # move databus to correct position @@ -242,37 +248,7 @@ post_reset_loop: btst r7, nRST beq post_reset_loop b Poll_loop -.if 0 -# Subroutine to post r8 to the mailbox -# if r2 is zero then the hardware mailbox is used -# if r2 is non zero then a software mailbox at address r2 is used - -do_post_mailbox: -# Send to GPU->ARM mailbox (channel 10) - and r8, r1 - - cmp r2, 0 - beq use_hw_mailbox - -# Use the software mailbox - bset r8, ATTN_MASK - ld r7, (r2) # get mailbox - btst r7, ATTN_MASK - bsetne r8, OVERRUN_MASK - st r8, (r2) - rts - -# Use the hardware mailbox -use_hw_mailbox: -# Add 4-bit seqence number into bits 12-15 (unused GPIO bits), and increment - or r8, r4 - add r4, 0x1000 - and r4, 0xF000 - lsl r8, 4 - or r8, 0x0000000A - st r8, (r3) - rts -.endif + # This code is not currently used .if 0 From 5ce7425b3a34dbd4b9c9fe066c2b3d707ff877d2 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 11:17:55 +0100 Subject: [PATCH 137/149] Revert "check nTube again incase of glitches" This reverts commit 31085b256b45aef16c6ba6a102d652302a632332. Doesn't actually help --- src/tubevc.c | 29 ++++++++++++++--------------- vidcore/tubevc.s | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index 0757c9c5..d3002027 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -6,22 +6,21 @@ unsigned char tubevc_asm[] = { 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x68, 0x2d, - 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x57, 0x00, 0x18, 0x6d, 0x68, 0x2d, - 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2d, 0x18, 0x88, 0xc1, + 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, + 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, - 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x07, 0x18, 0x18, 0x6d, - 0x85, 0x18, 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x67, 0x2d, - 0x77, 0x6c, 0xfe, 0x18, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, - 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcb, 0x18, 0x27, 0x6d, - 0xc9, 0x18, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, - 0x77, 0x6c, 0xfd, 0x18, 0x18, 0x6d, 0xc0, 0x18, 0x47, 0xc3, 0x48, 0x47, - 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, 0xe4, 0xe8, 0xf0, 0x00, - 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, 0x07, 0xc2, 0xc8, 0x38, - 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, 0x88, 0xc1, 0x12, 0x47, - 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, 0xa8, 0xff, 0x07, 0xe8, - 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, - 0x7f, 0x9e, 0x9f, 0xff + 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x05, 0x18, 0x07, 0x46, + 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, + 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, 0x67, 0x2d, 0x77, 0x6c, + 0x7e, 0x18, 0x17, 0x6d, 0xcd, 0x18, 0x27, 0x6d, 0xcb, 0x18, 0x67, 0x2d, + 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, + 0x47, 0xc3, 0x48, 0x47, 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, + 0xe4, 0xe8, 0xf0, 0x00, 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, + 0x07, 0xc2, 0xc8, 0x38, 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, + 0x88, 0xc1, 0x12, 0x47, 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x7f, 0x9e, + 0xac, 0xff, 0x07, 0xe8, 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, 0x67, 0x2d, + 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0xa3, 0xff }; -unsigned int tubevc_asm_len = 280; +unsigned int tubevc_asm_len = 272; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 0c08378c..7d1bcb69 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -170,8 +170,6 @@ rd_wait_for_clk_high1: # we now have half a cycle to do post mail btst r8, r16 # no need to post mail if A0 = 0 beq rd_wait_for_clk_low - btst r8, nTUBE # double check nTUBE is low - bne rd_wait_for_clk_low sub r7, r0 # just get the address bits lsl r7, 6 # put address bits in correct place bset r7, RW_MAILBOX_BIT # set read bit @@ -215,10 +213,6 @@ wr_wait_for_clk_low: btst r7, CLK bne wr_wait_for_clk_low -# check that ntube is stil low to ensure we have a valid cycle - btst r8, nTUBE - bne Poll_loop - # Post a message to indicate a tube register write # move databus to correct position @@ -248,7 +242,37 @@ post_reset_loop: btst r7, nRST beq post_reset_loop b Poll_loop - +.if 0 +# Subroutine to post r8 to the mailbox +# if r2 is zero then the hardware mailbox is used +# if r2 is non zero then a software mailbox at address r2 is used + +do_post_mailbox: +# Send to GPU->ARM mailbox (channel 10) + and r8, r1 + + cmp r2, 0 + beq use_hw_mailbox + +# Use the software mailbox + bset r8, ATTN_MASK + ld r7, (r2) # get mailbox + btst r7, ATTN_MASK + bsetne r8, OVERRUN_MASK + st r8, (r2) + rts + +# Use the hardware mailbox +use_hw_mailbox: +# Add 4-bit seqence number into bits 12-15 (unused GPIO bits), and increment + or r8, r4 + add r4, 0x1000 + and r4, 0xF000 + lsl r8, 4 + or r8, 0x0000000A + st r8, (r3) + rts +.endif # This code is not currently used .if 0 From 4af8eede60d4379fa4b2f5f9c1103718a63f1a9c Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 11:19:53 +0100 Subject: [PATCH 138/149] Revert "Tweak the pipeline" Not needed This reverts commit e14fa473f8822a78bdc55de8147c8963acaf0a60. --- src/tubevc.c | 4 ++-- vidcore/tubevc.s | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index d3002027..7a8426f0 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -5,8 +5,8 @@ unsigned char tubevc_asm[] = { 0x80, 0xb8, 0x00, 0x7e, 0x06, 0xe8, 0x00, 0x00, 0x20, 0x7e, 0x6a, 0x08, 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, - 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x68, 0x2d, - 0x07, 0x40, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, + 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x07, 0x40, + 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 7d1bcb69..629684ea 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -131,8 +131,8 @@ # poll for nTube being low Poll_loop: - ld r8, GPLEV0_offset(r6) mov r7, r0 + ld r8, GPLEV0_offset(r6) Poll_tube_low: btst r8, nRST beq post_reset From 4c08c5735e1a5e99207ee7a97935ff6929c1572e Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 11:20:24 +0100 Subject: [PATCH 139/149] Revert "Improve Host Read Data setup time by 25ns" Improved data setup timing but breaks systems with slow addre bus and rnw signals This reverts commit 9c7ff844b062aba36b6ce8e6f824cc7c22d739bf. --- src/tubevc.c | 4 ++-- vidcore/tubevc.s | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index 7a8426f0..508379b4 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -6,8 +6,8 @@ unsigned char tubevc_asm[] = { 0x6b, 0x21, 0x6c, 0x22, 0xad, 0xc1, 0x01, 0x57, 0xae, 0xc1, 0x02, 0x5f, 0xaf, 0xc1, 0x04, 0x67, 0x01, 0xe8, 0x10, 0x0f, 0xc6, 0x03, 0x01, 0xc2, 0x10, 0x0f, 0x01, 0xc2, 0x11, 0x0f, 0x01, 0xc2, 0x12, 0x0f, 0x07, 0x40, - 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0x68, 0x2d, - 0xfb, 0x18, 0x18, 0x6d, 0xf9, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, + 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x53, 0x00, 0x18, 0x6d, 0xfb, 0x18, + 0x68, 0x2d, 0x18, 0x6d, 0xf8, 0x18, 0x28, 0x6d, 0x2b, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index 629684ea..a1bed803 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -132,13 +132,13 @@ # poll for nTube being low Poll_loop: mov r7, r0 - ld r8, GPLEV0_offset(r6) Poll_tube_low: + ld r8, GPLEV0_offset(r6) btst r8, nRST beq post_reset btst r8, nTUBE + bne Poll_tube_low ld r8, GPLEV0_offset(r6) # check ntube again to remove glitches - bne Poll_tube_low btst r8, nTUBE bne Poll_tube_low # we now know nTube is low From 4921a60c3fd3b6c20c5efffbed1aa4a0fa46e4ad Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 13:13:06 +0100 Subject: [PATCH 140/149] Code now works out if it is a 26pin build or not. Simplify out of the box usage --- src/info.h | 2 ++ src/rpi-gpio.h | 2 ++ src/scripts/config.txt | 28 ++++++---------- src/scripts/release.sh | 2 +- src/tube-client.c | 2 -- src/tube-defs.h | 31 ++++-------------- src/tube-exception.c | 8 ----- src/tube-ula.c | 73 ++++++++++++++++++------------------------ 8 files changed, 53 insertions(+), 95 deletions(-) diff --git a/src/info.h b/src/info.h index 70b39dd6..1dbd7bda 100644 --- a/src/info.h +++ b/src/info.h @@ -22,6 +22,8 @@ extern char *get_info_string(); extern int get_clock_rate(int clk_id); +int get_revision(); + extern float get_temp(); #define COMPONENT_CORE 1 diff --git a/src/rpi-gpio.h b/src/rpi-gpio.h index e53ddbc6..13cef86d 100644 --- a/src/rpi-gpio.h +++ b/src/rpi-gpio.h @@ -34,6 +34,8 @@ /** The base address of the GPIO peripheral (ARM Physical Address) */ #define RPI_GPIO_BASE (PERIPHERAL_BASE + 0x200000UL) +// Raspberry Pi3 has a differentway of controlling the LED + #if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3) #define LED_GPFSEL GPFSEL[4] #define LED_GPFBIT 21 diff --git a/src/scripts/config.txt b/src/scripts/config.txt index adef274d..8fafd78f 100644 --- a/src/scripts/config.txt +++ b/src/scripts/config.txt @@ -1,37 +1,23 @@ # config.txt for PiTubeDirect (https://github.com/hoglet67/PiTubeDirect) # - -# Settings for Pi Zero -[pi0] -arm_freq=1000 -core_freq=400 -kernel=kernelrpizero.img -# Debug kernel (needs a 115200 serial connection) -#kernel=debug/kernelrpizero.img - -# Settings for Pi 1 Model B and B+ -# Use kernelrpi.img for Pi 1 Model B Rev 1.0 -# Use kernelrpibplus.img for all other Pi 1 models (inc B+) -[pi1] -arm_freq=700 +# default options core_freq=350 kernel=kernelrpi.img -#kernel=kernelrpibplus.img # Debug kernel (needs a 115200 serial connection) #kernel=debug/kernelrpi.img -#kernel=debug/kernelrpibplus.img + +# Settings for Pi Zero +[pi0] +core_freq=400 # Settings for Pi 2 [pi2] -arm_freq=900 -core_freq=350 kernel=kernelrpi2.img # Debug kernel (needs a 115200 serial connection) #kernel=debug/kernelrpi2.img # Settings for Pi 3 [pi3] -arm_freq=1200 core_freq=400 kernel=kernelrpi3.img # Debug kernel (needs a 115200 serial connection) @@ -47,6 +33,10 @@ hdmi_ignore_edid=0xa5000080 hdmi_ignore_hotplug=1 boot_delay=0 +# clock frequency override +# all pis bar zero W default to the correct frequency uncomment for pi zero W +#arm_freq=1000 + kernel_address=0x1f00000 gpu_mem=16 start_file=start_cd.elf diff --git a/src/scripts/release.sh b/src/scripts/release.sh index b528b975..114c0c15 100755 --- a/src/scripts/release.sh +++ b/src/scripts/release.sh @@ -8,7 +8,7 @@ NAME=PiTubeDirect_$(date +"%Y%m%d_%H%M")_$USER DIR=releases/${NAME} mkdir -p ${DIR}/debug -for MODEL in rpi3 rpi2 rpi rpibplus rpizero +for MODEL in rpi3 rpi2 rpi do # compile normal kernel ./clobber.sh diff --git a/src/tube-client.c b/src/tube-client.c index 03acdc64..49a66fae 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -254,9 +254,7 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) #endif init_emulator(); -#ifdef HAS_40PINS RPI_GpioBase->GPSET0 = (1 << TEST_PIN); -#endif do { // Run the emulator diff --git a/src/tube-defs.h b/src/tube-defs.h index af73c268..6e3784bd 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -152,29 +152,19 @@ #define MAGIC_C2 ((1 << ((D4_PIN - 20) * 3)) | (1 << ((D5_PIN - 20) * 3))) #define MAGIC_C3 ((1 << ((D6_PIN - 20) * 3)) | (1 << ((D7_PIN - 20) * 3))) -#if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3) - -#define A2_PIN (3) -#define A1_PIN (2) -#define A0_PIN (27) - -#else - -#define A2_PIN (1) -#define A1_PIN (0) -#define A0_PIN (21) +#define A2_PIN_40PIN (3) +#define A1_PIN_40PIN (2) +#define A0_PIN_40PIN (27) -#endif +#define A2_PIN_26PIN (1) +#define A1_PIN_26PIN (0) +#define A0_PIN_26PIN (21) #define PHI2_PIN (7) #define NTUBE_PIN (17) #define NRST_PIN (4) #define RNW_PIN (18) -#define ATTN_PIN (31) -#define OVERRUN_PIN (30) -#define GLITCH_PIN (29) - #define D7_MASK (1 << D7_PIN) #define D6_MASK (1 << D6_PIN) #define D5_MASK (1 << D5_PIN) @@ -183,9 +173,7 @@ #define D2_MASK (1 << D2_PIN) #define D1_MASK (1 << D1_PIN) #define D0_MASK (1 << D0_PIN) -#define A2_MASK (1 << A2_PIN) -#define A1_MASK (1 << A1_PIN) -#define A0_MASK (1 << A0_PIN) + #define PHI2_MASK (1 << PHI2_PIN) #define NTUBE_MASK (1 << NTUBE_PIN) #define NRST_MASK (1 << NRST_PIN) @@ -199,17 +187,12 @@ #define D74_MASK (D7_MASK | D6_MASK | D5_MASK | D4_MASK) #define D_MASK (D74_MASK | D30_MASK) -#define A_MASK (A2_MASK | A1_MASK | A0_MASK) -#define PINS_MASK (A_MASK | D_MASK | RNW_MASK | NRST_MASK | NTUBE_MASK) - -#ifdef HAS_40PINS #define TEST_PIN (21) #define TEST_MASK (1 << TEST_PIN) #define TEST2_PIN (20) #define TEST2_MASK (1 << TEST2_PIN) #define TEST3_PIN (16) #define TEST3_MASK (1 << TEST3_PIN) -#endif #endif diff --git a/src/tube-exception.c b/src/tube-exception.c index 8fa3a3d5..387ae8ef 100644 --- a/src/tube-exception.c +++ b/src/tube-exception.c @@ -67,7 +67,6 @@ void dump_info(unsigned int *context, int offset, char *type) { unsigned int flags; int i, j; int rstlow; - int led; // Make sure we avoid unaligned accesses context = (unsigned int *)(((unsigned int) context) & ~3); @@ -141,7 +140,6 @@ void dump_info(unsigned int *context, int offset, char *type) { dump_string("Halted waiting for reset\r\n"); rstlow = 0; - led = 0; while (1) { for (i = 0; i < 1000000; i++) { @@ -154,12 +152,6 @@ void dump_info(unsigned int *context, int offset, char *type) { reboot_now(); } } - if (led) { - LED_OFF(); - } else { - LED_ON(); - } - led = ~led; } } diff --git a/src/tube-ula.c b/src/tube-ula.c index bf4b8a3b..f23bbe63 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -45,6 +45,7 @@ #include "startup.h" static volatile uint32_t *tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; +static uint32_t host_addr_bus; #define HBIT_7 (1 << 25) #define HBIT_6 (1 << 24) @@ -600,14 +601,7 @@ int tube_io_handler(uint32_t mail) act_seq_num = (mail >> 12) & 15; #endif #endif - // Toggle the LED on each tube access - static int led = 0; - if (led) { - LED_OFF(); - } else { - LED_ON(); - } - led = ~led; + #ifdef USE_GPU if ((mail >> 12) & 1) // Check for Reset @@ -697,11 +691,33 @@ int tube_io_handler(uint32_t mail) void tube_init_hardware() { - // Write 1 to the LED init nibble in the Function Select GPIO - // peripheral register to enable LED pin as an output - RPI_GpioBase->LED_GPFSEL |= LED_GPFBIT; - LED_ON(); + // early 26pin pins have a slightly different pin out + + switch (get_revision()) + { + case 2 : + case 3 : + + host_addr_bus = (A2_PIN_26PIN << 16) | (A1_PIN_26PIN << 8) | (A0_PIN_26PIN); // address bus GPIO mapping + RPI_SetGpioPinFunction(A2_PIN_26PIN, FS_INPUT); + RPI_SetGpioPinFunction(A1_PIN_26PIN, FS_INPUT); + RPI_SetGpioPinFunction(A0_PIN_26PIN, FS_INPUT); + + break; + + + default : + + host_addr_bus = (A2_PIN_40PIN << 16) | (A1_PIN_40PIN << 8) | (A0_PIN_40PIN); // address bus GPIO mapping + RPI_SetGpioPinFunction(A2_PIN_40PIN, FS_INPUT); + RPI_SetGpioPinFunction(A1_PIN_40PIN, FS_INPUT); + RPI_SetGpioPinFunction(A0_PIN_40PIN, FS_INPUT); + RPI_SetGpioPinFunction(TEST_PIN, FS_OUTPUT); + RPI_SetGpioPinFunction(TEST2_PIN, FS_OUTPUT); + RPI_SetGpioPinFunction(TEST3_PIN, FS_OUTPUT); + break; + } // Configure our pins as inputs RPI_SetGpioPinFunction(D7_PIN, FS_INPUT); RPI_SetGpioPinFunction(D6_PIN, FS_INPUT); @@ -712,35 +728,18 @@ void tube_init_hardware() RPI_SetGpioPinFunction(D1_PIN, FS_INPUT); RPI_SetGpioPinFunction(D0_PIN, FS_INPUT); - RPI_SetGpioPinFunction(A2_PIN, FS_INPUT); - RPI_SetGpioPinFunction(A1_PIN, FS_INPUT); - RPI_SetGpioPinFunction(A0_PIN, FS_INPUT); + RPI_SetGpioPinFunction(PHI2_PIN, FS_INPUT); RPI_SetGpioPinFunction(NTUBE_PIN, FS_INPUT); RPI_SetGpioPinFunction(NRST_PIN, FS_INPUT); RPI_SetGpioPinFunction(RNW_PIN, FS_INPUT); -#ifdef HAS_40PINS - RPI_SetGpioPinFunction(TEST_PIN, FS_OUTPUT); - RPI_SetGpioPinFunction(TEST2_PIN, FS_OUTPUT); - RPI_SetGpioPinFunction(TEST3_PIN, FS_OUTPUT); -#endif - - - // Initialise the info system with cached values (as we break the GPU property interface) init_info(); #ifdef DEBUG dump_useful_info(); #endif - - // Print the GPIO numbers of A0, A1 and A2 -#ifdef DEBUG_GPU - LOG_DEBUG("A0 = GPIO%02d = mask %08x\r\n", A0_PIN, A0_MASK); - LOG_DEBUG("A1 = GPIO%02d = mask %08x\r\n", A1_PIN, A1_MASK); - LOG_DEBUG("A2 = GPIO%02d = mask %08x\r\n", A2_PIN, A2_MASK); -#endif // Initialize performance counters #if defined(RPI2) || defined(RPI3) @@ -798,9 +797,7 @@ static void tube_wait_for_rst_active() { void tube_wait_for_rst_release() { volatile int i; -//#ifdef HAS_40PINS -// RPI_SetGpioValue(TEST2_PIN, 1); -//#endif + do { // Wait for reset to be released while (tube_is_rst_active()); @@ -808,9 +805,7 @@ void tube_wait_for_rst_release() { for (i = 0; i < DEBOUNCE_TIME && !tube_is_rst_active(); i++); // Loop back if we exit the debouce loop prematurely because RST has gone active again } while (i < DEBOUNCE_TIME); -//#ifdef HAS_40PINS -// RPI_SetGpioValue(TEST2_PIN, 0); -//#endif + // Reset all the TUBE ULA registers tube_reset(); } @@ -858,13 +853,9 @@ void start_vc_ula() r1 = magic[0]; // data bus drive r2 = magic[1]; - r3 = (A2_PIN << 16) | (A1_PIN << 8) | (A0_PIN); // address bus GPIO mapping + r3 = host_addr_bus; r4 = magic[2]; -#ifdef HAS_40PINS r5 = TEST_MASK; // test pin -#else - r5 = 0; -#endif #ifdef DEBUG_GPU LOG_DEBUG("Staring VC ULA\r\n"); From 2e3e9b1cea63de049f4252a2b6138595774ae66b Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 18:20:14 +0100 Subject: [PATCH 141/149] Turn off HDMI to save power --- src/scripts/config.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripts/config.txt b/src/scripts/config.txt index 8fafd78f..4361331c 100644 --- a/src/scripts/config.txt +++ b/src/scripts/config.txt @@ -29,6 +29,7 @@ force_turbo=1 # Disable adjusting the refresh rate of RAM every 500 ms disable_pvt=1 +hdmi_blanking=2 hdmi_ignore_edid=0xa5000080 hdmi_ignore_hotplug=1 boot_delay=0 From 6a0878149f3854ff4a0eb64713fb722449668765 Mon Sep 17 00:00:00 2001 From: dp111 Date: Mon, 17 Apr 2017 18:30:15 +0100 Subject: [PATCH 142/149] Move LED control to GPU and add RPI 26pin debug pin --- src/tube-client.c | 4 +++- src/tube-defs.h | 9 +++----- src/tube-ula.c | 39 ++++++++++++++++++++++------------ src/tubevc.c | 54 ++++++++++++++++++++++++++--------------------- 4 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/tube-client.c b/src/tube-client.c index 49a66fae..a6a47cc8 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -14,6 +14,8 @@ typedef void (*func_ptr)(); +extern int test_pin; + #include "copro-65tube.h" #ifdef MINIMAL_BUILD @@ -254,7 +256,7 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) #endif init_emulator(); - RPI_GpioBase->GPSET0 = (1 << TEST_PIN); + RPI_GpioBase->GPSET0 = (1 << test_pin); do { // Run the emulator diff --git a/src/tube-defs.h b/src/tube-defs.h index 6e3784bd..db3e7c86 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -57,12 +57,6 @@ #define DEFAULT_COPRO COPRO_65TUBE_0 -// Indicates a Pi with the 40 pin GPIO connector -// so that additional functionality (e.g. test pins) can be enabled -#if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3) -#define HAS_40PINS -#endif - // Pi 2/3 Multicore options #if defined(RPI2) || defined(RPI3) @@ -188,6 +182,9 @@ #define D_MASK (D74_MASK | D30_MASK) +#define TEST_PIN_26PIN (27) +#define TEST_PIN_40PIN (21) + #define TEST_PIN (21) #define TEST_MASK (1 << TEST_PIN) #define TEST2_PIN (20) diff --git a/src/tube-ula.c b/src/tube-ula.c index f23bbe63..74d9d3a4 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -44,6 +44,9 @@ #include "tubevc.h" #include "startup.h" +int test_pin; +static int led_type=0; + static volatile uint32_t *tube_regs = (uint32_t *) ARM_TUBE_REG_ADDR; static uint32_t host_addr_bus; @@ -59,7 +62,6 @@ static uint32_t host_addr_bus; #define BYTE_TO_WORD(data) ((((data) & 0x0F) << 8) | (((data) & 0xF0) << 18)) #define WORD_TO_BYTE(data) ((((data) >> 8) & 0x0F) | (((data) << 18) & 0xF0)) -const static uint32_t magic[3] = {MAGIC_C0, MAGIC_C1, MAGIC_C2 | MAGIC_C3 }; static char copro_command =0; static perf_counters_t pct; @@ -698,12 +700,16 @@ void tube_init_hardware() { case 2 : case 3 : - + // Write 1 to the LED init nibble in the Function Select GPIO + // peripheral register to enable LED pin as an output + RPI_GpioBase-> GPFSEL[1] |= 1<<18; host_addr_bus = (A2_PIN_26PIN << 16) | (A1_PIN_26PIN << 8) | (A0_PIN_26PIN); // address bus GPIO mapping RPI_SetGpioPinFunction(A2_PIN_26PIN, FS_INPUT); RPI_SetGpioPinFunction(A1_PIN_26PIN, FS_INPUT); RPI_SetGpioPinFunction(A0_PIN_26PIN, FS_INPUT); - + RPI_SetGpioPinFunction(TEST_PIN_26PIN, FS_OUTPUT); + test_pin = TEST_PIN_26PIN; + led_type = 0; break; @@ -712,10 +718,19 @@ void tube_init_hardware() host_addr_bus = (A2_PIN_40PIN << 16) | (A1_PIN_40PIN << 8) | (A0_PIN_40PIN); // address bus GPIO mapping RPI_SetGpioPinFunction(A2_PIN_40PIN, FS_INPUT); RPI_SetGpioPinFunction(A1_PIN_40PIN, FS_INPUT); - RPI_SetGpioPinFunction(A0_PIN_40PIN, FS_INPUT); - RPI_SetGpioPinFunction(TEST_PIN, FS_OUTPUT); + RPI_SetGpioPinFunction(A0_PIN_40PIN, FS_INPUT); + RPI_SetGpioPinFunction(TEST_PIN_40PIN, FS_OUTPUT); RPI_SetGpioPinFunction(TEST2_PIN, FS_OUTPUT); RPI_SetGpioPinFunction(TEST3_PIN, FS_OUTPUT); + test_pin = TEST_PIN_40PIN; +#ifdef RPI3 + led_type = 2; +#else + // Write 1 to the LED init nibble in the Function Select GPIO + // peripheral register to enable LED pin as an output + RPI_GpioBase-> GPFSEL[4] |= 1<<21; + led_type = 1; +#endif break; } // Configure our pins as inputs @@ -728,7 +743,6 @@ void tube_init_hardware() RPI_SetGpioPinFunction(D1_PIN, FS_INPUT); RPI_SetGpioPinFunction(D0_PIN, FS_INPUT); - RPI_SetGpioPinFunction(PHI2_PIN, FS_INPUT); RPI_SetGpioPinFunction(NTUBE_PIN, FS_INPUT); RPI_SetGpioPinFunction(NRST_PIN, FS_INPUT); @@ -765,8 +779,7 @@ void tube_init_hardware() #endif hp1 = hp2 = hp4 = hp3[0]= hp3[1]=0; - - // RPI_GpioBase->GPSET0 = (1 << TEST_PIN); + } int tube_is_rst_active() { @@ -797,7 +810,6 @@ static void tube_wait_for_rst_active() { void tube_wait_for_rst_release() { volatile int i; - do { // Wait for reset to be released while (tube_is_rst_active()); @@ -805,7 +817,6 @@ void tube_wait_for_rst_release() { for (i = 0; i < DEBOUNCE_TIME && !tube_is_rst_active(); i++); // Loop back if we exit the debouce loop prematurely because RST has gone active again } while (i < DEBOUNCE_TIME); - // Reset all the TUBE ULA registers tube_reset(); } @@ -850,12 +861,12 @@ void start_vc_ula() func = (int) &tubevc_asm[0]; r0 = (int) GPU_TUBE_REG_ADDR; // address of tube register block in IO space - r1 = magic[0]; // data bus drive - r2 = magic[1]; + r1 = led_type; + r2 = 0; r3 = host_addr_bus; - r4 = magic[2]; - r5 = TEST_MASK; // test pin + r4 = 0; + r5 = 1< Date: Tue, 18 Apr 2017 09:17:01 +0100 Subject: [PATCH 143/149] slight improvement to datasetup time for reads --- src/tubevc.c | 10 +-- vidcore/tubevc.s | 155 ++++++++++++++++++++++++++++++----------------- 2 files changed, 105 insertions(+), 60 deletions(-) diff --git a/src/tubevc.c b/src/tubevc.c index eb77287a..3bf8572c 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -7,10 +7,10 @@ unsigned char tubevc_asm[] = { 0x0d, 0xe8, 0x00, 0x00, 0x00, 0x09, 0x9e, 0x60, 0x0f, 0xe8, 0x40, 0x92, 0x00, 0x00, 0xad, 0x4d, 0xbe, 0x4d, 0xcf, 0x4d, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, 0x00, 0x90, 0x57, 0x00, 0x18, 0x6d, 0xfb, 0x18, 0x68, 0x2d, - 0x18, 0x6d, 0xf8, 0x18, 0x28, 0x6d, 0x2d, 0x18, 0x88, 0xc1, 0x10, 0x47, - 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, - 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, 0xd0, 0x38, 0x78, 0x08, 0x6d, 0x09, - 0x6e, 0x31, 0x6f, 0x32, 0x68, 0x37, 0x65, 0x37, 0x68, 0x2d, 0x78, 0x6c, + 0x18, 0x6d, 0xf8, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, + 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, + 0xa7, 0xc1, 0xd0, 0x38, 0x74, 0x08, 0x28, 0x6d, 0x20, 0x18, 0x6d, 0x09, + 0x6e, 0x31, 0x6f, 0x32, 0x54, 0x4d, 0x64, 0x37, 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x07, 0x18, 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x80, 0x90, 0x3d, 0x00, 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, 0x67, 0x2d, @@ -24,7 +24,7 @@ unsigned char tubevc_asm[] = { 0x00, 0x00, 0x37, 0x09, 0x80, 0x90, 0x07, 0x00, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, 0x9d, 0xff, 0x53, 0xc1, 0x40, 0x9f, 0x05, 0x18, 0x53, 0xc1, 0x41, 0x9f, 0x0e, 0x18, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x00, - 0x01, 0x00, 0x94, 0xc1, 0x40, 0xa7, 0xb4, 0xc0, 0x41, 0xa7, 0x83, 0x18, + 0x01, 0x00, 0x94, 0xc1, 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, 0x67, 0x3a, 0x5a, 0x00, 0x67, 0x37, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x80, 0x00, 0x00, 0x94, 0xc1, 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, 0x67, 0x3b, 0x5a, 0x00, 0x67, 0x38, 0x5a, 0x00 diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index a1bed803..b328fe6b 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -8,40 +8,50 @@ # gpfsel_data_idle setup # r0 - pointer to shared memory ( VC address) of tube registers -# r1 - pointer to shared memory ( VC address) of gpfsel_data_idle -# r2 - pointer to shared memory ( VC address) of tube_mailbox +# r1 - LEDTYPE +# r2 - unused # r3 - GPIO mapping of address lines - 0x00 where A2, A1 and A0 are the numbers of the respective GPIOs # r4 - unused # r5 - debug pin mask (0 = no debug xx= debug pin e.g 1<<21) # Intenal register allocation # r0 - pointer to shared memory ( VC address) of tube registers -# r1 - ( 1<ARM mailbox (channel 10) - and r8, r1 - - cmp r2, 0 - beq use_hw_mailbox - -# Use the software mailbox - bset r8, ATTN_MASK - ld r7, (r2) # get mailbox - btst r7, ATTN_MASK - bsetne r8, OVERRUN_MASK - st r8, (r2) + +#### Toggle LED +toggle_led: + + cmp r19, 0 + beq led_type0 + cmp r19, 1 + beq led_type1 + + # must be led_type3 + # only on raspberry pi 3 + rts -# Use the hardware mailbox -use_hw_mailbox: -# Add 4-bit seqence number into bits 12-15 (unused GPIO bits), and increment - or r8, r4 - add r4, 0x1000 - and r4, 0xF000 - lsl r8, 4 - or r8, 0x0000000A - st r8, (r3) - rts -.endif +# led_type 0 found on 26 pin raspberry pis +led_type0: + mov r7, (1< Date: Thu, 20 Apr 2017 10:41:06 +0100 Subject: [PATCH 144/149] Fix printing 64-bit cycle counter on reset (newlib-nano limitation) Change-Id: I97a11b8967c91f7dc5a601397b1b74a7e851de4d --- src/performance.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/performance.c b/src/performance.c index 95a441ca..785dadc4 100644 --- a/src/performance.c +++ b/src/performance.c @@ -196,11 +196,27 @@ void read_performance_counters(perf_counters_t *pct) { #endif } +static char bfr[20+1]; + +static char* uint64ToDecimal(uint64_t v) { + int first = 1; + char* p = bfr + sizeof(bfr); + *(--p) = '\0'; + while (v || first) { + *(--p) = '0' + v % 10; + v = v / 10; + first = 0; + } + return p; +} + void print_performance_counters(perf_counters_t *pct) { int i; uint64_t cycle_counter = pct->cycle_counter; cycle_counter *= 64; - printf("%26s = %"PRIu64"\r\n", "cycle counter", cycle_counter); + // newlib-nano doesn't appear to support 64-bit printf/scanf on 32-bit systems + // printf("%26s = %"PRIu64"\r\n", "cycle counter", cycle_counter); + printf("%26s = %s\r\n", "cycle counter", uint64ToDecimal(cycle_counter)); for (i = 0; i < pct->num_counters; i++) { printf("%26s = %u\r\n", type_lookup(pct->type[i]), pct->counter[i]); } From 36c9686775e917158d78a1487a0de551b79a086b Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 20 Apr 2017 11:20:45 +0100 Subject: [PATCH 145/149] 32016 Co Pro: fix a crash when memory set to 16MB (conflict with tube regs) Change-Id: I747b952ce491e6dd2def6c28bc04dcd974d301bd --- src/NS32016/mem32016.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/NS32016/mem32016.c b/src/NS32016/mem32016.c index 443b0190..c8b4f40a 100644 --- a/src/NS32016/mem32016.c +++ b/src/NS32016/mem32016.c @@ -51,10 +51,17 @@ static uint8_t * ns32016ram; void init_ram(void) { - if (copro_memory_size >0) - RAM_SIZE = copro_memory_size & ~((128*1024)-1); - else - RAM_SIZE = MEG1; + if (copro_memory_size > 0) + { + // Ensure RAM size is multiple of 128KB, or the Client ROM memory test gets confused + RAM_SIZE = copro_memory_size & ~((128*1024)-1); + // Limit RAM size to 15MB, so there is space for the tube registers above this + if (RAM_SIZE > MEG15) { + RAM_SIZE = MEG15; + } + } else { + RAM_SIZE = MEG1; + } #ifndef BEM ns32016ram = copro_mem_reset(RAM_SIZE); #endif From 06a459d55723eb324a85229cd0b7756839da7683 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 20 Apr 2017 11:41:03 +0100 Subject: [PATCH 146/149] Debugger: Fixed a crash when tube registers accessed Change-Id: I0ced4b49000855996b5d2456d5b5c3eb1d506123 --- src/armc-start.S | 10 ++++++++++ src/startup.h | 2 ++ src/tube-ula.c | 10 +++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/armc-start.S b/src/armc-start.S index 455b54de..d6903a68 100644 --- a/src/armc-start.S +++ b/src/armc-start.S @@ -58,6 +58,7 @@ .global _get_stack_pointer .global _exception_table .global _enable_interrupts +.global _set_interrupts .global _disable_interrupts .global _enable_unaligned_access .global _enable_l1_cache @@ -264,6 +265,15 @@ _get_cpsr: mrs r0, cpsr mov pc, lr +.section ".text._set_interrupts" +_set_interrupts: + and r0, r0, #CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT // extract the IRQ/FIQ bits from the value of cpsr passed in + mrs r1, cpsr + bic r1, r1, #CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT + orr r1, r1, r0 + msr cpsr_c, r1 + mov pc, lr + .section ".text._enable_interrupts" _enable_interrupts: mrs r0, cpsr diff --git a/src/startup.h b/src/startup.h index 5003d2d9..c60dfec2 100644 --- a/src/startup.h +++ b/src/startup.h @@ -11,6 +11,8 @@ extern void _start( void ); extern void _enable_interrupts( void ); +extern void _set_interrupts( int cpsr ); + extern int _disable_interrupts( void ); extern unsigned int _get_cpsr(); diff --git a/src/tube-ula.c b/src/tube-ula.c index 74d9d3a4..4b0a57f0 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -476,9 +476,9 @@ uint8_t tube_parasite_read(uint32_t addr) tube_index &= 0xffff; } #endif - if ((cpsr & 0xc0) != 0xc0) { - _enable_interrupts(); - } + if ((cpsr & 0xc0) != 0xc0) { + _set_interrupts(cpsr); + } return temp; } @@ -578,8 +578,8 @@ void tube_parasite_write(uint32_t addr, uint8_t val) // tube_updateints_IRQ(); // the above can't change IRQ flag break; } - if ((cpsr & 0xc0) != 0xc0) { - _enable_interrupts(); + if ((cpsr & 0xc0) != 0xc0) { + _set_interrupts(cpsr); } } From 5c7a1f334381b37143a1b45141823f29ba100a44 Mon Sep 17 00:00:00 2001 From: dp111 Date: Fri, 21 Apr 2017 20:29:09 +0100 Subject: [PATCH 147/149] Add tube_delay to specify tube sampling point --- src/scripts/cmdline.txt | 2 +- src/tube-client.c | 22 ++++++++++---- src/tube-ula.c | 4 +-- src/tubevc.c | 63 +++++++++++++++++++++++++---------------- vidcore/tubevc.s | 22 ++++++++++---- 5 files changed, 75 insertions(+), 38 deletions(-) diff --git a/src/scripts/cmdline.txt b/src/scripts/cmdline.txt index 03f0d583..6e61f3ba 100644 --- a/src/scripts/cmdline.txt +++ b/src/scripts/cmdline.txt @@ -1,3 +1,3 @@ -copro=0 copro1speed=3 +copro=0 copro1speed=3 tube_delay=0 diff --git a/src/tube-client.c b/src/tube-client.c index a6a47cc8..f1efc23d 100644 --- a/src/tube-client.c +++ b/src/tube-client.c @@ -91,6 +91,7 @@ static const func_ptr emulator_functions[] = { volatile unsigned int copro; volatile unsigned int copro_speed; volatile unsigned int copro_memory_size = 0; +unsigned int tube_delay = 0; int arm_speed; @@ -225,24 +226,35 @@ static void get_copro_memory_size() { LOG_DEBUG("Copro Memory size %u\r\n", copro_memory_size); } +static void get_tube_delay() { + char *copro_prop = get_cmdline_prop("tube_delay"); + tube_delay = 0; // default + if (copro_prop) { + tube_delay = atoi(copro_prop); + } + if (tube_delay > 40){ + tube_delay = 40; + } + LOG_DEBUG("Tube ULA sample delay %u\r\n", tube_delay); +} + void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) { // Initialise the UART to 57600 baud - RPI_AuxMiniUartInit( 115200, 8 ); - enable_MMU_and_IDCaches(); + RPI_AuxMiniUartInit( 115200, 8 ); + enable_MMU_and_IDCaches(); _enable_unaligned_access(); tube_init_hardware(); - arm_speed = get_clock_rate(ARM_CLK_ID); - - + get_tube_delay(); start_vc_ula(); copro = get_copro_number(); get_copro_speed(); get_copro_memory_size(); + #ifdef BENCHMARK // Run a short set of CPU and Memory benchmarks benchmark(); diff --git a/src/tube-ula.c b/src/tube-ula.c index 4b0a57f0..b2698520 100644 --- a/src/tube-ula.c +++ b/src/tube-ula.c @@ -858,11 +858,11 @@ void disable_tube() { void start_vc_ula() { int func,r0,r1, r2,r3,r4,r5; - + extern int tube_delay; func = (int) &tubevc_asm[0]; r0 = (int) GPU_TUBE_REG_ADDR; // address of tube register block in IO space r1 = led_type; - r2 = 0; + r2 = tube_delay; r3 = host_addr_bus; r4 = 0; diff --git a/src/tubevc.c b/src/tubevc.c index 3bf8572c..3674dd3e 100644 --- a/src/tubevc.c +++ b/src/tubevc.c @@ -5,28 +5,43 @@ unsigned char tubevc_asm[] = { 0x50, 0x1f, 0xf2, 0xc0, 0x5f, 0x97, 0x03, 0xe8, 0x80, 0xb8, 0x00, 0x7e, 0x06, 0xe8, 0x00, 0x00, 0x20, 0x7e, 0x6a, 0x08, 0x6b, 0x21, 0x6c, 0x22, 0x0d, 0xe8, 0x00, 0x00, 0x00, 0x09, 0x9e, 0x60, 0x0f, 0xe8, 0x40, 0x92, - 0x00, 0x00, 0xad, 0x4d, 0xbe, 0x4d, 0xcf, 0x4d, 0x07, 0x40, 0x68, 0x2d, - 0x48, 0x6c, 0x00, 0x90, 0x57, 0x00, 0x18, 0x6d, 0xfb, 0x18, 0x68, 0x2d, - 0x18, 0x6d, 0xf8, 0x18, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, - 0x88, 0xc1, 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, - 0xa7, 0xc1, 0xd0, 0x38, 0x74, 0x08, 0x28, 0x6d, 0x20, 0x18, 0x6d, 0x09, - 0x6e, 0x31, 0x6f, 0x32, 0x54, 0x4d, 0x64, 0x37, 0x68, 0x2d, 0x78, 0x6c, - 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x07, 0x18, 0x07, 0x46, 0x67, 0x7c, - 0xb7, 0x70, 0x37, 0x09, 0x80, 0x90, 0x3d, 0x00, 0x67, 0x2d, 0x77, 0x6c, - 0xfe, 0x18, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, 0x69, 0x3a, 0x67, 0x2d, - 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0xcb, 0x18, 0x27, 0x6d, 0xc9, 0x18, - 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, - 0xfd, 0x18, 0x47, 0xc3, 0x48, 0x47, 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, - 0x4f, 0x3f, 0xe4, 0xe8, 0xf0, 0x00, 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, - 0x10, 0x47, 0x07, 0xc2, 0xc8, 0x38, 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, - 0xc9, 0x38, 0x88, 0xc1, 0x12, 0x47, 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, - 0x80, 0x90, 0x0f, 0x00, 0x7f, 0x9e, 0xa8, 0xff, 0x07, 0xe8, 0x00, 0x10, - 0x00, 0x00, 0x37, 0x09, 0x80, 0x90, 0x07, 0x00, 0x67, 0x2d, 0x47, 0x6c, - 0x7e, 0x18, 0x7f, 0x9e, 0x9d, 0xff, 0x53, 0xc1, 0x40, 0x9f, 0x05, 0x18, - 0x53, 0xc1, 0x41, 0x9f, 0x0e, 0x18, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x00, - 0x01, 0x00, 0x94, 0xc1, 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, - 0x67, 0x3a, 0x5a, 0x00, 0x67, 0x37, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x80, - 0x00, 0x00, 0x94, 0xc1, 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, - 0x67, 0x3b, 0x5a, 0x00, 0x67, 0x38, 0x5a, 0x00 + 0x00, 0x00, 0xad, 0x4d, 0xbe, 0x4d, 0xcf, 0x4d, 0x62, 0xe9, 0x28, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x21, 0x40, 0x07, 0x40, 0x68, 0x2d, 0x48, 0x6c, + 0x00, 0x90, 0xaa, 0x00, 0x18, 0x6d, 0xfb, 0x18, 0x11, 0x80, 0x50, 0xe9, + 0x11, 0x80, 0x4e, 0xe9, 0x11, 0x80, 0x4c, 0xe9, 0x11, 0x80, 0x4a, 0xe9, + 0x11, 0x80, 0x48, 0xe9, 0x11, 0x80, 0x46, 0xe9, 0x11, 0x80, 0x44, 0xe9, + 0x11, 0x80, 0x42, 0xe9, 0x11, 0x80, 0x40, 0xe9, 0x11, 0x80, 0x3e, 0xe9, + 0x11, 0x80, 0x3c, 0xe9, 0x11, 0x80, 0x3a, 0xe9, 0x11, 0x80, 0x38, 0xe9, + 0x11, 0x80, 0x36, 0xe9, 0x11, 0x80, 0x34, 0xe9, 0x11, 0x80, 0x32, 0xe9, + 0x11, 0x80, 0x30, 0xe9, 0x11, 0x80, 0x2e, 0xe9, 0x11, 0x80, 0x2c, 0xe9, + 0x11, 0x80, 0x2a, 0xe9, 0x11, 0x80, 0x28, 0xe9, 0x11, 0x80, 0x26, 0xe9, + 0x11, 0x80, 0x24, 0xe9, 0x11, 0x80, 0x22, 0xe9, 0x11, 0x80, 0x20, 0xe9, + 0x11, 0x80, 0x1e, 0xe9, 0x11, 0x80, 0x1c, 0xe9, 0x11, 0x80, 0x1a, 0xe9, + 0x11, 0x80, 0x18, 0xe9, 0x11, 0x80, 0x16, 0xe9, 0x11, 0x80, 0x14, 0xe9, + 0x11, 0x80, 0x12, 0xe9, 0x11, 0x80, 0x10, 0xe9, 0x11, 0x80, 0x0e, 0xe9, + 0x11, 0x80, 0x0c, 0xe9, 0x11, 0x80, 0x0a, 0xe9, 0x11, 0x80, 0x08, 0xe9, + 0x11, 0x80, 0x06, 0xe9, 0x11, 0x80, 0x04, 0xe9, 0x11, 0x80, 0x02, 0xe9, + 0x68, 0x2d, 0x88, 0xc1, 0x10, 0x47, 0xa7, 0xc1, 0xc4, 0x38, 0x88, 0xc1, + 0x11, 0x47, 0xa7, 0xc1, 0xc8, 0x38, 0x88, 0xc1, 0x12, 0x47, 0xa7, 0xc1, + 0xd0, 0x38, 0x74, 0x08, 0x18, 0x6d, 0x7f, 0x91, 0x9b, 0xff, 0x28, 0x6d, + 0x22, 0x18, 0x6d, 0x09, 0x6e, 0x31, 0x6f, 0x32, 0x54, 0x4d, 0x64, 0x37, + 0x68, 0x2d, 0x78, 0x6c, 0x7e, 0x18, 0x88, 0xc1, 0x10, 0x47, 0x07, 0x18, + 0x07, 0x46, 0x67, 0x7c, 0xb7, 0x70, 0x37, 0x09, 0x80, 0x90, 0x3f, 0x00, + 0x67, 0x2d, 0x77, 0x6c, 0xfe, 0x18, 0x6a, 0x09, 0x6b, 0x31, 0x6c, 0x32, + 0x69, 0x3a, 0x67, 0x2d, 0x77, 0x6c, 0x7e, 0x18, 0x17, 0x6d, 0x7f, 0x91, + 0x79, 0xff, 0x27, 0x6d, 0x7f, 0x91, 0x76, 0xff, 0x67, 0x2d, 0x77, 0x6c, + 0x7e, 0x18, 0x78, 0x40, 0x67, 0x2d, 0x77, 0x6c, 0xfd, 0x18, 0x47, 0xc3, + 0x48, 0x47, 0x44, 0xc3, 0x52, 0x47, 0xe7, 0xc0, 0x4f, 0x3f, 0xe4, 0xe8, + 0xf0, 0x00, 0x00, 0x00, 0x47, 0x4d, 0x88, 0xc1, 0x10, 0x47, 0x07, 0xc2, + 0xc8, 0x38, 0x88, 0xc1, 0x11, 0x47, 0x07, 0xc2, 0xc9, 0x38, 0x88, 0xc1, + 0x12, 0x47, 0x07, 0xc2, 0xca, 0x38, 0x37, 0x09, 0x80, 0x90, 0x0f, 0x00, + 0x7f, 0x9e, 0x54, 0xff, 0x07, 0xe8, 0x00, 0x10, 0x00, 0x00, 0x37, 0x09, + 0x80, 0x90, 0x07, 0x00, 0x67, 0x2d, 0x47, 0x6c, 0x7e, 0x18, 0x7f, 0x9e, + 0x49, 0xff, 0x53, 0xc1, 0x40, 0x9f, 0x05, 0x18, 0x53, 0xc1, 0x41, 0x9f, + 0x0e, 0x18, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x94, 0xc1, + 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, 0x67, 0x3a, 0x5a, 0x00, + 0x67, 0x37, 0x5a, 0x00, 0x07, 0xe8, 0x00, 0x80, 0x00, 0x00, 0x94, 0xc1, + 0x40, 0xa7, 0x14, 0xc1, 0x14, 0xa7, 0x83, 0x18, 0x67, 0x3b, 0x5a, 0x00, + 0x67, 0x38, 0x5a, 0x00 }; -unsigned int tubevc_asm_len = 344; +unsigned int tubevc_asm_len = 520; diff --git a/vidcore/tubevc.s b/vidcore/tubevc.s index b328fe6b..71e86cf1 100644 --- a/vidcore/tubevc.s +++ b/vidcore/tubevc.s @@ -9,7 +9,7 @@ # r0 - pointer to shared memory ( VC address) of tube registers # r1 - LEDTYPE -# r2 - unused +# r2 - tube_delay # r3 - GPIO mapping of address lines - 0x00 where A2, A1 and A0 are the numbers of the respective GPIOs # r4 - unused # r5 - debug pin mask (0 = no debug xx= debug pin e.g 1<<21) @@ -133,6 +133,8 @@ lsr r18, r3, 16 # Extract GPIO number of A2 and r18, 31 + + # r1, r3, r4 now free mov r3, GPU_ARM_MBOX @@ -153,10 +155,12 @@ or r15, r12 # enable interrupts -# ei - +# ei + rsb r2, 40 + nop #nop to align loop for speed # poll for nTube being low Poll_loop: + mov r1, r2 mov r7, r0 Poll_tube_low: ld r8, GPLEV0_offset(r6) @@ -164,9 +168,14 @@ Poll_tube_low: beq post_reset btst r8, nTUBE bne Poll_tube_low + +.rept 40 + addcmpbeq r1,1,41,delay_done +.endr + +delay_done: ld r8, GPLEV0_offset(r6) # check ntube again to remove glitches - btst r8, nTUBE - bne Poll_tube_low + # we now know nTube is low # Extra read with might possible help with rnw on slow machines # ld r8, GPLEV0_offset(r6) # read bus again to ensure we have the correct address @@ -183,7 +192,8 @@ Poll_tube_low: orne r7, 16 ld r4, (r7) # Read word from tube register - + btst r8, nTUBE + bne Poll_tube_low btst r8, RnW beq wr_cycle From 9749b59168d70ddef84c985eeb2853afb4ba023a Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 23 Apr 2017 12:43:59 +0100 Subject: [PATCH 148/149] Updated the release name to Cobra-rc0 Change-Id: I4a45bb98cdcc8b5f4dec070f033fb774178fc47a --- src/tube-defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube-defs.h b/src/tube-defs.h index db3e7c86..63c86cd5 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -3,7 +3,7 @@ #ifndef TUBE_DEFS_H #define TUBE_DEFS_H -#define RELEASENAME "Cobra-dev" +#define RELEASENAME "Cobra-rc0" #define NDEBUG From c79645c757f2e4b02b730b1bc886408ca4358a53 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 7 Jun 2017 18:10:31 +0100 Subject: [PATCH 149/149] Updated the release name to Cobra Change-Id: I83c2eeaa50f2aea01176a3f0c8a20a101042780c --- src/tube-defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube-defs.h b/src/tube-defs.h index 63c86cd5..a952715f 100644 --- a/src/tube-defs.h +++ b/src/tube-defs.h @@ -3,7 +3,7 @@ #ifndef TUBE_DEFS_H #define TUBE_DEFS_H -#define RELEASENAME "Cobra-rc0" +#define RELEASENAME "Cobra" #define NDEBUG