From 41230a84fcd99e45551c722211c7084c4ae04406 Mon Sep 17 00:00:00 2001 From: David Haywood Date: Mon, 19 Aug 2019 21:36:20 +0100 Subject: [PATCH] some monon disassembly helpers [anonymous] (#5504) * some monon disassembly helpers [anonymous] * typo (nw) * not used (nw) * split into ax208 and axc51 (nw) --- src/devices/cpu/mcs51/axc51-core.cpp | 45 ++++- src/devices/cpu/mcs51/axc51-core.h | 16 +- src/devices/cpu/mcs51/axc51-core_dasm.cpp | 206 ++++++++++++++++++++++ src/devices/cpu/mcs51/axc51-core_dasm.h | 22 +++ src/devices/cpu/mcs51/mcs51dasm.cpp | 22 ++- src/devices/cpu/mcs51/mcs51dasm.h | 2 + src/mame/drivers/monon_color.cpp | 52 ++++-- src/tools/unidasm.cpp | 1 + 8 files changed, 334 insertions(+), 32 deletions(-) diff --git a/src/devices/cpu/mcs51/axc51-core.cpp b/src/devices/cpu/mcs51/axc51-core.cpp index ddf22f27880..7dc8272d29e 100644 --- a/src/devices/cpu/mcs51/axc51-core.cpp +++ b/src/devices/cpu/mcs51/axc51-core.cpp @@ -8,13 +8,16 @@ AX208 SoC - - Notes: + AXC51CORE: + somes sources indicate that the extended opcode encoding may change + on some CPU models despite all being 'AXC51CORE' however we lack solid + information on this at present. + AX208: - The CPU has a bootloader that sets a few things up + copies data to RAM - from the Flash meomry. This will need to be simulated. + The CPU has 0x2000 bytes of internal ROM mapped at 0x8000-0x9fff providing + bootcode, operating kernel and many standard library functions *****************************************************************************/ @@ -23,14 +26,44 @@ #include "axc51-core.h" #include "axc51-core_dasm.h" +DEFINE_DEVICE_TYPE(AXC51CORE, axc51core_cpu_device, "axc51core", "AppoTech AXC51-CORE") DEFINE_DEVICE_TYPE(AX208, ax208_cpu_device, "ax208", "AppoTech AX208 (AXC51-CORE)") +// AXC51CORE (base device) + +axc51core_cpu_device::axc51core_cpu_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, int program_width, int data_width, uint8_t features) + : mcs51_cpu_device(mconfig, type, tag, owner, clock, program_width, data_width, features) +{ +} + +axc51core_cpu_device::axc51core_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : axc51core_cpu_device(mconfig, AXC51CORE, tag, owner, clock, 0, 7) +{ +} + +std::unique_ptr axc51core_cpu_device::create_disassembler() +{ + return std::make_unique(); +} + +// AX208 (specific CPU) + ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mcs51_cpu_device(mconfig, AX208, tag, owner, clock, 0, 7) + : axc51core_cpu_device(mconfig, AX208, tag, owner, clock, 0, 7) { } std::unique_ptr ax208_cpu_device::create_disassembler() { - return std::make_unique(); + return std::make_unique(); +} + +ROM_START( ax208 ) + ROM_REGION( 0x2000, "rom", 0 ) + ROM_LOAD("ax208.rom", 0x0000, 0x2000, NO_DUMP ) +ROM_END + +const tiny_rom_entry *ax208_cpu_device::device_rom_region() const +{ + return ROM_NAME( ax208 ); } diff --git a/src/devices/cpu/mcs51/axc51-core.h b/src/devices/cpu/mcs51/axc51-core.h index 6d86c682b2e..f225fecd4da 100644 --- a/src/devices/cpu/mcs51/axc51-core.h +++ b/src/devices/cpu/mcs51/axc51-core.h @@ -17,9 +17,22 @@ #include "mcs51.h" +DECLARE_DEVICE_TYPE(AXC51CORE, axc51core_cpu_device) DECLARE_DEVICE_TYPE(AX208, ax208_cpu_device) -class ax208_cpu_device : public mcs51_cpu_device +class axc51core_cpu_device : public mcs51_cpu_device +{ +public: + // construction/destruction + axc51core_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + axc51core_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int program_width, int data_width, uint8_t features = 0); + +protected: + virtual std::unique_ptr create_disassembler() override; +}; + + +class ax208_cpu_device : public axc51core_cpu_device { public: // construction/destruction @@ -27,6 +40,7 @@ public: protected: virtual std::unique_ptr create_disassembler() override; + virtual const tiny_rom_entry *device_rom_region() const override; }; #endif // MAME_CPU_MCS51_AXC51_CORE_H diff --git a/src/devices/cpu/mcs51/axc51-core_dasm.cpp b/src/devices/cpu/mcs51/axc51-core_dasm.cpp index b6d5a6da83c..be500543505 100644 --- a/src/devices/cpu/mcs51/axc51-core_dasm.cpp +++ b/src/devices/cpu/mcs51/axc51-core_dasm.cpp @@ -13,6 +13,7 @@ #include "emu.h" #include "axc51-core_dasm.h" +// SOME of these might be AX208 specific, we do not currently hvae enough information to split it into AXC51 / AX208 however const axc51core_disassembler::mem_info axc51core_disassembler::axc51core_names[] = { // SFR Registers @@ -196,6 +197,151 @@ const axc51core_disassembler::mem_info axc51core_disassembler::axc51core_names[] { -1 } }; + +// based on extracted symbol table, note 0x8000 - 0x8ca3 is likely boot code, interrupt code, kernel etc. +// this should be the same for all ax208 CPUs as they are thought to all use the same internal ROM +const ax208_disassembler::ax208_bios_info ax208_disassembler::bios_call_names[] = { + { 0x8000, "entry point" }, + + { 0x8006, "unknown, used" }, + { 0x8009, "unknown, used" }, + + { 0x8ca4, "_STRCHR" }, + { 0x8dd6, "_STRLEN" }, + { 0x8eb7, "_tolower" }, + { 0x8ec8, "_toupper" }, + { 0x900f, "_isalpha" }, + { 0x902a, "_iscntrl" }, + { 0x9038, "_isdigit" }, + { 0x9047, "_isalnum" }, + { 0x906d, "_isgraph" }, + { 0x907c, "_isprint" }, + { 0x908b, "_ispunct" }, + { 0x90bb, "_islower" }, + { 0x90ca, "_isupper" }, + { 0x90d9, "_isspace" }, + { 0x90ec, "_isxdigit" }, + { 0x91e2, "COPY" }, + { 0x9208, "SCDIV" }, + { 0x922a, "CLDPTR" }, + { 0x9243, "CLDIPTR" }, + { 0x9267, "CLDOPTR" }, + { 0x9294, "CLDIOPTR" }, + { 0x92cb, "CILDPTR" }, + { 0x92ed, "CILDOPTR" }, + { 0x9320, "CSTPTR" }, + { 0x9332, "CSTOPTR" }, + { 0x9354, "UIDIV" }, + { 0x93a9, "SIDIV" }, + { 0x93df, "IILDX" }, + { 0x93f5, "ILDIX" }, + { 0x940b, "ILDPTR" }, + { 0x9436, "ILDIPTR" }, + { 0x946b, "ILDOPTR" }, + { 0x94a3, "ILDIOPTR" }, + { 0x94ef, "IILDPTR" }, + { 0x9527, "IILDOPTR" }, + { 0x9574, "ISTPTR" }, + { 0x9593, "ISTOPTR" }, + { 0x95c0, "LADD" }, + { 0x95cd, "LSUB" }, + { 0x95db, "LMUL" }, + { 0x9666, "ULDIV" }, + { 0x96f8, "LAND" }, + { 0x9705, "LOR" }, + { 0x9712, "LXOR" }, + { 0x971f, "LNOT" }, + { 0x972c, "LNEG" }, + { 0x973a, "SLCMP" }, + { 0x9750, "ULCMP" }, + { 0x9761, "ULSHR" }, + { 0x9774, "SLSHR" }, + { 0x9788, "LSHL" }, + { 0x979b, "LLDPTR" }, + { 0x97bb, "LLDOPTR" }, + { 0x97eb, "LSTPTR" }, + { 0x9805, "LSTOPTR" }, + { 0x9829, "LILDPTR" }, + { 0x9849, "LILDOPTR" }, + { 0x9879, "LLDIPTR" }, + { 0x9899, "LLDIOPTR" }, + { 0x98c9, "LLDIDATA" }, + { 0x98d5, "LLDXDATA" }, + { 0x98e1, "LLDPDATA" }, + { 0x98ed, "LLDCODE" }, + { 0x98fd, "LLDIDATA0" }, + { 0x990a, "LLDXDATA0" }, + { 0x9916, "LLDPDATA0" }, + { 0x9923, "LLDCODE0" }, + { 0x9933, "LLDPTR0" }, + { 0x9953, "LLDOPTR0" }, + { 0x9983, "LLDIIDATA1" }, + { 0x9985, "LLDIIDATA8" }, + { 0x998c, "LLDIIDATA" }, + { 0x99a3, "LLDIXDATA1" }, + { 0x99a5, "LLDIXDATA8" }, + { 0x99ac, "LLDIXDATA" }, + { 0x99d8, "LLDIPDATA1" }, + { 0x99da, "LLDIPDATA8" }, + { 0x99e1, "LLDIPDATA" }, + { 0x99f8, "LILDIDATA1" }, + { 0x99fa, "LILDIDATA8" }, + { 0x9a01, "LILDIDATA" }, + { 0x9a18, "LILDXDATA1" }, + { 0x9a1a, "LILDXDATA8" }, + { 0x9a21, "LILDXDATA" }, + { 0x9a4d, "LILDPDATA1" }, + { 0x9a4f, "LILDPDATA8" }, + { 0x9a56, "LILDPDATA" }, + { 0x9a6d, "LSTIDATA" }, + { 0x9a79, "LSTXDATA" }, + { 0x9a85, "LSTPDATA" }, + { 0x9a91, "LSTKIDATA" }, + { 0x9aaa, "LSTKXDATA" }, + { 0x9adb, "LSTKPDATA" }, + { 0x9af4, "LSTKPTR" }, + { 0x9b0e, "LSTKOPTR" }, + { 0x9b32, "BCAST_L" }, + { 0x9b3b, "OFFX256" }, + { 0x9b4c, "OFFXADD" }, + { 0x9b58, "OFFXADD1" }, + { 0x9b61, "PLDIDATA" }, + { 0x9b6a, "PLDIIDATA" }, + { 0x9b7a, "PILDIDATA" }, + { 0x9b8a, "PSTIDATA" }, + { 0x9b93, "PLDXDATA" }, + { 0x9b9c, "PLDIXDATA" }, + { 0x9bb3, "PILDXDATA" }, + { 0x9bca, "PSTXDATA" }, + { 0x9bd3, "PLDPDATA" }, + { 0x9bdc, "PLDIPDATA" }, + { 0x9bec, "PILDPDATA" }, + { 0x9bfc, "PSTPDATA" }, + { 0x9c05, "PLDCODE" }, + { 0x9c11, "PLDPTR" }, + { 0x9c31, "PLDIPTR" }, + { 0x9c53, "PILDPTR" }, + { 0x9c75, "PSTPTR" }, + { 0x9cc4, "PSTPTRR" }, + { 0x9cf4, "PLDOPTR" }, + { 0x9d24, "PLDIOPTR" }, + { 0x9d56, "PILDOPTR" }, + { 0x9d88, "PSTOPTR" }, + { 0x9de1, "CCASE" }, + { 0x9e07, "ICASE" }, + { 0x9e34, "LCASE" }, + { 0x9e6e, "ICALL" }, + { 0x9e72, "ICALL2" }, + { 0x9e74, "MEMSET" }, + { 0x9ea0, "LROL" }, + { 0x9eb4, "LROR" }, + { 0x9ec8, "SLDIV" }, + { 0x9f47, "SPI_ENCRYPT_ON3" }, + { 0x9f5c, "_lshift9" }, + { 0x9fdc, "SPI_ENCRYPT_CLOSE" }, + { -1, "unknown" } +}; + axc51core_disassembler::axc51core_disassembler() : mcs51_disassembler(axc51core_names) { } @@ -814,6 +960,7 @@ offs_t axc51core_disassembler::disassemble_extended_a5(std::ostream& stream, uns return (PC - pc) | flags | SUPPORTED; } + offs_t axc51core_disassembler::disassemble_op(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params, uint8_t op) { uint32_t flags = 0; @@ -831,3 +978,62 @@ offs_t axc51core_disassembler::disassemble_op(std::ostream& stream, unsigned PC, } +ax208_disassembler::ax208_disassembler() : axc51core_disassembler(axc51core_names) +{ +} + +void ax208_disassembler::disassemble_op_ljmp(std::ostream& stream, unsigned &PC, const data_buffer& params) +{ + uint16_t addr = (params.r8(PC++) << 8) & 0xff00; + addr |= params.r8(PC++); + if ((addr >= 0x8000) && (addr < 0xa000)) + { + int i = 0; + int lookaddr = -1; + const char* lookname; + do + { + lookaddr = bios_call_names[i].addr; + lookname = bios_call_names[i].name; + + if (lookaddr == addr) + break; + + i++; + } while (lookaddr != -1); + + util::stream_format(stream, "ljmp $%04X (%s)", addr, lookname); + } + else + { + util::stream_format(stream, "ljmp $%04X", addr); + } +} + +void ax208_disassembler::disassemble_op_lcall(std::ostream& stream, unsigned &PC, const data_buffer& params) +{ + uint16_t addr = (params.r8(PC++)<<8) & 0xff00; + addr|= params.r8(PC++); + if ((addr >= 0x8000) && (addr < 0xa000)) + { + int i = 0; + int lookaddr = -1; + const char* lookname; + do + { + lookaddr = bios_call_names[i].addr; + lookname = bios_call_names[i].name; + + if (lookaddr == addr) + break; + + i++; + } while (lookaddr != -1); + + util::stream_format(stream, "lcall $%04X (%s)", addr, lookname); + } + else + { + util::stream_format(stream, "lcall $%04X", addr); + } +} diff --git a/src/devices/cpu/mcs51/axc51-core_dasm.h b/src/devices/cpu/mcs51/axc51-core_dasm.h index f3f1b053241..83292e7783b 100644 --- a/src/devices/cpu/mcs51/axc51-core_dasm.h +++ b/src/devices/cpu/mcs51/axc51-core_dasm.h @@ -21,6 +21,9 @@ class axc51core_disassembler : public mcs51_disassembler { public: axc51core_disassembler(); + + axc51core_disassembler(const mem_info* names) : mcs51_disassembler(names) {}; + virtual ~axc51core_disassembler() = default; static const mem_info axc51core_names[]; @@ -37,5 +40,24 @@ private: }; +class ax208_disassembler : public axc51core_disassembler +{ +public: + ax208_disassembler(); + virtual ~ax208_disassembler() = default; + + struct ax208_bios_info { + int addr; + const char *name; + }; + + static const ax208_bios_info bios_call_names[]; + +protected: + virtual void disassemble_op_ljmp(std::ostream& stream, unsigned &PC, const data_buffer& params) override; + virtual void disassemble_op_lcall(std::ostream& stream, unsigned &PC, const data_buffer& params) override; +}; + + #endif // MAME_CPU_MCS51_AXC51_CORE_DASM_H diff --git a/src/devices/cpu/mcs51/mcs51dasm.cpp b/src/devices/cpu/mcs51/mcs51dasm.cpp index 29f6d579638..ebd77aece33 100644 --- a/src/devices/cpu/mcs51/mcs51dasm.cpp +++ b/src/devices/cpu/mcs51/mcs51dasm.cpp @@ -408,6 +408,20 @@ std::string mcs51_disassembler::get_bit_address( uint8_t arg ) const } } +void mcs51_disassembler::disassemble_op_ljmp(std::ostream& stream, unsigned &PC, const data_buffer& params) +{ + uint16_t addr = (params.r8(PC++)<<8) & 0xff00; + addr|= params.r8(PC++); + util::stream_format(stream, "ljmp $%04X", addr); +} + +void mcs51_disassembler::disassemble_op_lcall(std::ostream& stream, unsigned &PC, const data_buffer& params) +{ + uint16_t addr = (params.r8(PC++)<<8) & 0xff00; + addr|= params.r8(PC++); + util::stream_format(stream, "lcall $%04X", addr); +} + offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms, uint8_t op) { uint32_t flags = 0; @@ -439,9 +453,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off //LJMP code addr case 0x02: /* 1: 0000 0010 */ - addr = (params.r8(PC++)<<8) & 0xff00; - addr|= params.r8(PC++); - util::stream_format(stream, "ljmp $%04X", addr); + disassemble_op_ljmp(stream, PC, params); break; //RR A @@ -501,9 +513,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off //LCALL code addr case 0x12: /* 1: 0001 0010 */ - addr = (params.r8(PC++)<<8) & 0xff00; - addr|= params.r8(PC++); - util::stream_format(stream, "lcall $%04X", addr); + disassemble_op_lcall(stream, PC, params); flags = STEP_OVER; break; diff --git a/src/devices/cpu/mcs51/mcs51dasm.h b/src/devices/cpu/mcs51/mcs51dasm.h index 0bb161f3ab8..9ae251af8ea 100644 --- a/src/devices/cpu/mcs51/mcs51dasm.h +++ b/src/devices/cpu/mcs51/mcs51dasm.h @@ -66,6 +66,8 @@ public: virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; protected: + virtual void disassemble_op_ljmp(std::ostream& stream, unsigned& PC, const data_buffer& params); + virtual void disassemble_op_lcall(std::ostream& stream, unsigned& PC, const data_buffer& params); virtual offs_t disassemble_op(std::ostream &stream, unsigned PC, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms, uint8_t op); std::string get_data_address( uint8_t arg ) const; diff --git a/src/mame/drivers/monon_color.cpp b/src/mame/drivers/monon_color.cpp index 6eeb017882d..14952bd45e2 100644 --- a/src/mame/drivers/monon_color.cpp +++ b/src/mame/drivers/monon_color.cpp @@ -30,7 +30,8 @@ public: m_screen(*this, "screen"), m_palette(*this, "palette"), m_mainram(*this, "mainram"), - m_otherram(*this, "otherram") + m_otherram(*this, "otherram"), + m_bootcopy(0) { } void monon_color(machine_config &config); @@ -54,6 +55,7 @@ private: DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); void monon_color_map(address_map &map); + int m_bootcopy; }; void monon_color_state::machine_start() @@ -63,18 +65,37 @@ void monon_color_state::machine_start() memcpy(maincpu, flash+0x200, 0x1e00); // 0x4000-0x5dff fixed code? - // there are a whole bunch of blocks that map at 0x5e00 (boot code jumps straight to 0x5e00) - memcpy(maincpu+0x1e00, flash+0x2000, 0x1000); // BANK0 - clears RAM, sets up stack etc. but then jumps to 0x9xxx where we have nothing (probably the correct initial block tho) -// memcpy(maincpu+0x1e00, flash+0x4200, 0x0a00); // BANK1 - just set register + a jump (to function that writes to UART) -// memcpy(maincpu+0x1e00, flash+0x4c00, 0x0a00); // BANK2 -// memcpy(maincpu+0x1e00, flash+0x5600, 0x0a00); // BANK3 -// memcpy(maincpu+0x1e00, flash+0x6000, 0x0a00); // BANK4 - ends up reting with nothing on the stack -// memcpy(maincpu+0x1e00, flash+0x6a00, 0x0a00); // BANK5 -// memcpy(maincpu+0x1e00, flash+0x7400, 0x0a00); // BANK6 -// memcpy(maincpu+0x1e00, flash+0x7e00, 0x0a00); // BANK7 -// memcpy(maincpu+0x1e00, flash+0x8800, 0x0a00); // BANK8 -// memcpy(maincpu+0x1e00, flash+0x9200, 0x0a00); // BANK9 +} + + + +void monon_color_state::machine_reset() +{ + m_maincpu->set_state_int(MCS51_PC, 0x4000); + + uint8_t* flash = memregion("flash")->base(); + uint8_t* maincpu = &m_mainram[0]; + + memset(maincpu + 0x1e00, 0x00, 0x1000); + + switch (m_bootcopy) + { + // there are a whole bunch of blocks that map at 0x5e00 (boot code jumps straight to 0x5e00) + case 0x0: memcpy(maincpu + 0x1e00, flash + 0x2000, 0x1000); break; // BANK0 - clears RAM, sets up stack etc. but then jumps to 0x9xxx where we have nothing (probably the correct initial block tho) + case 0x1: memcpy(maincpu + 0x1e00, flash + 0x4200, 0x0a00); break; // BANK1 - just set register + a jump (to function that writes to UART) + case 0x2: memcpy(maincpu + 0x1e00, flash + 0x4c00, 0x0a00); break; // BANK2 + case 0x3: memcpy(maincpu + 0x1e00, flash + 0x5600, 0x0a00); break; // BANK3 + case 0x4: memcpy(maincpu + 0x1e00, flash + 0x6000, 0x0a00); break; // BANK4 - ends up reting with nothing on the stack + case 0x5: memcpy(maincpu + 0x1e00, flash + 0x6a00, 0x0a00); break; // BANK5 + case 0x6: memcpy(maincpu + 0x1e00, flash + 0x7400, 0x0a00); break; // BANK6 + case 0x7: memcpy(maincpu + 0x1e00, flash + 0x7e00, 0x0a00); break; // BANK7 + case 0x8: memcpy(maincpu + 0x1e00, flash + 0x8800, 0x0a00); break; // BANK8 + case 0x9: memcpy(maincpu + 0x1e00, flash + 0x9200, 0x0a00); break; // BANK9 + } + + m_bootcopy++; + if (m_bootcopy == 0xa) m_bootcopy = 0x0; /* block starting at e000 in flash is not code? (or encrypted?) no code to map at 0x9000 in address space (possible BIOS?) @@ -92,13 +113,6 @@ void monon_color_state::machine_start() */ } - - -void monon_color_state::machine_reset() -{ - m_maincpu->set_state_int(MCS51_PC, 0x4000); -} - void monon_color_state::video_start() { } diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 74e8faa9d74..73e32e68863 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -329,6 +329,7 @@ static const dasm_table_entry dasm_table[] = { "asap", le, 0, []() -> util::disasm_interface * { return new asap_disassembler; } }, { "avr8", le, 0, []() -> util::disasm_interface * { return new avr8_disassembler; } }, { "axc51core", le, 0, []() -> util::disasm_interface * { return new axc51core_disassembler; } }, + { "axc208", le, 0, []() -> util::disasm_interface * { return new ax208_disassembler; } }, { "capricorn", le, 0, []() -> util::disasm_interface * { return new capricorn_disassembler; } }, { "ccpu", le, 0, []() -> util::disasm_interface * { return new ccpu_disassembler; } }, { "cdp1801", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1801); } },