diff options
Diffstat (limited to 'src/devices/cpu/mcs51')
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core.cpp | 69 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core.h | 46 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core_dasm.cpp | 1039 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core_dasm.h | 63 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51.cpp | 1569 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51.h | 313 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51dasm.cpp | 492 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51dasm.h | 68 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51ops.hxx | 512 |
9 files changed, 1858 insertions, 2313 deletions
diff --git a/src/devices/cpu/mcs51/axc51-core.cpp b/src/devices/cpu/mcs51/axc51-core.cpp deleted file mode 100644 index 104f3bb07bd..00000000000 --- a/src/devices/cpu/mcs51/axc51-core.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/***************************************************************************** - - AXC51-CORE (AppoTech Inc.) - - used in - - 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 0x2000 bytes of internal ROM mapped at 0x8000-0x9fff providing - bootcode, operating kernel and many standard library functions - - *****************************************************************************/ - -#include "emu.h" -#include "debugger.h" -#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<util::disasm_interface> axc51core_cpu_device::create_disassembler() -{ - return std::make_unique<axc51core_disassembler>(); -} - -// AX208 (specific CPU) - -ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : axc51core_cpu_device(mconfig, AX208, tag, owner, clock, 0, 7) -{ -} - -std::unique_ptr<util::disasm_interface> ax208_cpu_device::create_disassembler() -{ - return std::make_unique<ax208_disassembler>(); -} - -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 deleted file mode 100644 index f225fecd4da..00000000000 --- a/src/devices/cpu/mcs51/axc51-core.h +++ /dev/null @@ -1,46 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/***************************************************************************** - - AXC51-CORE (AppoTech Inc.) - - used in - - AX208 SoC - - *****************************************************************************/ - -#ifndef MAME_CPU_MCS51_AXC51_CORE_H -#define MAME_CPU_MCS51_AXC51_CORE_H - -#pragma once - -#include "mcs51.h" - -DECLARE_DEVICE_TYPE(AXC51CORE, axc51core_cpu_device) -DECLARE_DEVICE_TYPE(AX208, ax208_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<util::disasm_interface> create_disassembler() override; -}; - - -class ax208_cpu_device : public axc51core_cpu_device -{ -public: - // construction/destruction - ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual std::unique_ptr<util::disasm_interface> 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 deleted file mode 100644 index be500543505..00000000000 --- a/src/devices/cpu/mcs51/axc51-core_dasm.cpp +++ /dev/null @@ -1,1039 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/***************************************************************************** - - AXC51-CORE (AppoTech Inc.) - - used in - - AX208 SoC - - *****************************************************************************/ - -#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 - { 0x80, "P0" }, - { 0x81, "SP" }, // Stack Pointer - { 0x82, "DPL0" }, - { 0x83, "DPH0" }, - { 0x84, "DPL1" }, - { 0x85, "DPH1" }, - { 0x86, "DPCON" }, // Data Pointer Configure Register - { 0x87, "PCON0" }, // Power Control 0 - { 0x88, "SDCON0" }, - { 0x89, "SDCON1" }, - { 0x8A, "SDCON2" }, - { 0x8B, "JPGCON4" }, - { 0x8C, "JPGCON3" }, - { 0x8D, "JPGCON2" }, - { 0x8E, "JPGCON1" }, - { 0x8F, "TRAP" }, - { 0x90, "P1" }, - { 0x91, "SDBAUD" }, - { 0x92, "SDCPTR" }, - { 0x93, "SDDCNT" }, - { 0x94, "SDDPTR" }, - { 0x95, "IE2" }, // Interrupt Enable 2 - { 0x96, "UARTBAUDH" }, // UART Baud (high) - { 0x97, "PWKEN" }, // Port Wakeup Enable - { 0x98, "PWKPND" }, //Port Wakeup Flag - { 0x99, "PWKEDGE" }, // Port Wakeup Edge - { 0x9A, "PIE0" }, // Port Digital Input Enable Control 0 - { 0x9B, "DBASE" }, // DRAM Base Address Register - { 0x9C, "PCON1" }, // Power Control 1 - { 0x9D, "PIE1" }, // Port Digital Input Enable Control 1 - { 0x9E, "IRTDATA" }, // IRTCC Communication Data - { 0x9F, "IRTCON" }, // IRTCC Control - { 0xA0, "P2" }, - { 0xA1, "GP0" }, // (General Purpose Register 0) - { 0xA2, "GP1" }, // (General Purpose Register 1) - { 0xA3, "GP2" }, // (General Purpose Register 2) - { 0xA4, "GP3" }, // (General Purpose Register 3) - { 0xA5, "DACCON" }, // DAC Control Register - { 0xA6, "DACLCH" }, // DAC Left Channel - { 0xA7, "DACRCH" }, // DAC Right Channel - { 0xA8, "IE0" }, // Interrupt Enable 0 - { 0xA9, "IE1" }, // Interrupt Enable 1 - { 0xAA, "KEY0" }, - { 0xAB, "KEY1" }, - { 0xAC, "TMR3CON" }, // Timer3 Control - { 0xAD, "TMR3CNT" }, // Timer3 Counter - { 0xAE, "TMR3PR" }, // Timer3 Period - { 0xAF, "TMR3PSR" }, // Timer3 Pre-scalar - { 0xB0, "P3" }, - { 0xB1, "GP4" }, // (General Purpose Register 4) - { 0xB2, "GP5" }, // (General Purpose Register 5) - { 0xB3, "GP6" }, // (General Purpose Register 6) - { 0xB4, "P4" }, - { 0xB5, "GP7" }, // (General Purpose Register 7) - { 0xB6, "LCDCON" }, // LCD Control Register (or C6?) - { 0xB7, "PLLCON" }, // PLL Configuration - { 0xB8, "IP0" }, // Interrupt Priority 0 - { 0xB9, "IP1" }, // Interrupt Priority 1 - { 0xBA, "P0DIR" }, - { 0xBB, "P1DIR" }, - { 0xBC, "P2DIR" }, - { 0xBD, "P3DIR" }, - { 0xBE, "P4DIR" }, - { 0xBF, "LVDCON" }, // LVD Control Register - { 0xC0, "JPGCON0" }, - { 0xC1, "TMR2CON" }, // Timer2 Control - { 0xC2, "JPGCON9" }, - { 0xC3, "JPGCON5" }, - { 0xC4, "JPGCON6" }, - { 0xC5, "JPGCON7" }, - { 0xC6, "JPGCON8" }, - { 0xC7, "LCDPR" }, // LCD CS Pulse Width Register - { 0xC8, "LCDTCON" }, // LCD WR Pulse Timing Control Register - { 0xC9, "USBCON0" }, - { 0xCA, "USBCON1" }, - { 0xCB, "USBCON2" }, - { 0xCC, "USBDATA" }, - { 0xCD, "USBADR" }, - { 0xCE, "illegal" }, - { 0xCF, "MICCON" }, // MIC Control - { 0xD0, "PSW" }, // Processor Status Word - { 0xD1, "PGCON" }, // Power Gate Control Register - { 0xD2, "ADCCON" }, // SARADC Control - { 0xD3, "PCON2" }, // Power Control 2 - { 0xD4, "ADCDATAL" }, // SARADC Buffer Low Byte Control - { 0xD5, "ADCDATAH" }, // SARADC Buffer High Byte Control - { 0xD6, "SPIDMAADDR" }, // SPI DMA Start Address - { 0xD7, "SPIDMACNT" }, // SPI DMA counter - { 0xD8, "SPICON" }, // SPI Control - { 0xD9, "SPIBUF" }, // SPI Data Buffer - { 0xDA, "SPIBAUD" }, // SPI Baud Rate - { 0xDB, "CLKCON" }, // Clock Control - { 0xDC, "CLKCON1" }, - { 0xDD, "USBDPDM" }, - { 0xDE, "LFSRPOLY0" }, - { 0xDF, "LFSRPOLY1" }, - { 0xE0, "ACC" }, - { 0xE1, "TMR1CON" }, // Timer1 Control - { 0xE2, "UID0" }, - { 0xE3, "UID1" }, - { 0xE4, "UID2" }, - { 0xE5, "UID3" }, - { 0xE6, "ER00" }, // ER00 \- ER0 (16-bit) Extended Registers (used by 16-bit opcodes) - { 0xE7, "ER01" }, // ER01 / - { 0xE8, "ER10" }, // ER10 \- ER1 (16-bit) - { 0xE9, "ER11" }, // ER11 / - { 0xEA, "ER20" }, // ER20 \- ER2 (16-bit) - { 0xEB, "ER21" }, // ER21 / - { 0xEC, "ER30" }, // ER30 \- ER3 (16-bit) - { 0xED, "ER31" }, // ER31 / - { 0xEE, "ER8" }, // ER8 - { 0xEF, "illegal" }, - { 0xF0, "B" }, - { 0xF1, "HUFFBUF" }, - { 0xF2, "HUFFSFT" }, - { 0xF3, "HUFFDCL" }, - { 0xF4, "HUFFDCH" }, - { 0xF5, "CRC" }, - { 0xF6, "LFSRFIFO" }, - { 0xF7, "WDTCON" }, // Watchdog Control - { 0xF8, "TMR0CON" }, // Timer0 Control - { 0xF9, "TMR0CNT" }, // Timer0 Counter - { 0xFA, "TMR0PR" }, // Timer0 Period - { 0xFB, "TMR0PSR" }, // Timer0 Pre-scalar - { 0xFC, "UARTSTA" }, // UART Status - { 0xFD, "UARTCON" }, // UART Control - { 0xFE, "UARTBAUD" }, // UART Baud (low) - { 0xFF, "UARTDATA" }, // UART Communication Data - - // Upper Registers - - { 0x3010, "PUP0" }, - { 0x3011, "PUP1" }, - { 0x3012, "PUP2" }, - { 0x3013, "PUP3" }, - { 0x3014, "PUP4" }, - { 0x3015, "PDN0" }, - { 0x3016, "PDN1" }, - { 0x3017, "PDN2" }, - { 0x3018, "PDN3" }, - { 0x3019, "PDN4" }, - - { 0x3020, "TMR1CNTL" }, // Timer 1 Counter (low) - { 0x3021, "TMR1CNTH" }, // Timer 1 Counter (high) - { 0x3022, "TMR1PRL" }, // Timer 1 Period (low) - { 0x3023, "TMR1PRH" }, // Timer 1 Period (high) - { 0x3024, "TMR1PWML" }, // Timer 1 Duty (low) - { 0x3025, "TMR1PWMH" }, // Timer 1 Duty (high) - - { 0x3030, "TMR2CNTL" }, // Timer 2 Counter (low) - { 0x3031, "TMR2CNTH" }, // Timer 2 Counter (high) - { 0x3032, "TMR2PRL" }, // Timer 2 Period (low) - { 0x3033, "TMR2PRH" }, // Timer 2 Period (high) - { 0x3034, "TMR2PWML" }, // Timer 2 Duty (low) - { 0x3035, "TMR2PWMH" }, // Timer 2 Duty (high) - - { 0x3040, "ADCBAUD" }, //S ARADC Baud - - { 0x3050, "USBEP0ADL" }, - { 0x3051, "USBEP0ADH" }, - { 0x3052, "USBEP1RXADL" }, - { 0x3053, "USBEP1RXADH" }, - { 0x3054, "USBEP1TXADL" }, - { 0x3055, "USBEP1TXADH" }, - { 0x3056, "USBEP2RXADL" }, - { 0x3057, "USBEP2RXADH" }, - { 0x3058, "USBEP2TXADL" }, - { 0x3059, "USBEP2TXADH" }, - - { 0x3060, "SFSCON" }, - { 0x3061, "SFSPID" }, - { 0x3062, "SFSCNTH" }, - { 0x3063, "SFSCNTL" }, - - { 0x3070, "DACPTR" }, // DAC DMA Pointer - { 0x3071, "DACCNT" }, // DAC DMA Counter - - { -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) -{ -} -/* Extended 16-bit Opcodes - -Opcode/params | Operation | Flags touched ----------------------------------------------------------------------------------------- -INCDPi | | - | DPTRi = DPTRi + 1 | ----------------------------------------------------------------------------------------- -DECDPi | | - | DPTRi = DPTRi - 1 | ----------------------------------------------------------------------------------------- -ADDDPi | | - | DPTRi = DPTRi + {R8, B} | ----------------------------------------------------------------------------------------- -SUBDPi | | - | DPTRi = DPTRi - {R8, B} | ----------------------------------------------------------------------------------------- -INC2DPi | | - | DPTRi = DPTRi + 2 | ----------------------------------------------------------------------------------------- -DEC2DPi | | - | DPTRi = DPTRi - 2 | ----------------------------------------------------------------------------------------- -ROTR8 | | -EACC, ER8 | Rotate Right ACC by R8 &0x3 bits | ----------------------------------------------------------------------------------------- -ROTL8 | | -EACC, ER8 | Rotate Left ACC by R8 &0x3 bits | ----------------------------------------------------------------------------------------- -ADD16 | | -ERp, DPTRi, ERn | ERp = XRAM + ERn + EC | EZ, EC -DPTRi, ERn, ERp | XRAM = ERn + ERp + EC | -ERp, ERn, ERm | ERp = ERn + ERm + EC | ----------------------------------------------------------------------------------------- -SUB16 | | -ERp, DPTRi, ERn | ERp = XRAM - ERn - EC | EZ, EC -DPTRi, ERn, ERp | XRAM = ERn - ERp - EC | -ERp, ERn, ERm | ERp = ERn - ERm - EC | ----------------------------------------------------------------------------------------- -NOT16 | | -ERn | ERn = ~ERn | ----------------------------------------------------------------------------------------- -CLR16 | | -ERn | ERn = 0 | ----------------------------------------------------------------------------------------- -INC16 | | -ERn | ERn = ERn + 1 | EZ ----------------------------------------------------------------------------------------- -DEC16 | | -ERn | ERn = ERn - 1 | EZ ----------------------------------------------------------------------------------------- -ANL16 | | -ERn, DPTRi | ERn = XRAM & ERn | EZ -DPTRi, ERn | XRAM = XRAM & ERn | -ERn, ERm | ERn = ERn & ERm | ----------------------------------------------------------------------------------------- -ORL16 | | -ERn, DPTRi | ERn = XRAM | ERn | EZ -DPTRi, ERn | XRAM = XRAM | ERn | -ERn, ERm | ERn = ERn | ERm | ----------------------------------------------------------------------------------------- -XRL16 | | -ERn, DPTRi | ERn = XRAM ^ ERn | EZ -DPTRi, ERn | XRAM = XRAM ^ ERn | -ERn, ERm | ERn = ERn ^ ERm | ----------------------------------------------------------------------------------------- -MOV16 | | -ERn, DPTRi | ERn = XRAM | EZ -DPTRi, ERn | XRAM = ERn | -ERn, ERm | ERn = ERm | ----------------------------------------------------------------------------------------- -MUL16 (signed) | | -ERn, ERm | {ERn, ERm} = ERn * ERm | ----------------------------------------------------------------------------------------- -MULS16 (sign, satur) | | -ERn, ERm | {ERn, ERm} = ERn * ERm | ----------------------------------------------------------------------------------------- -ROTR16 | | -ERn, ER8 | Rotate Right ERn by ER8 & 0xf bits | ----------------------------------------------------------------------------------------- -ROTL16 | | -ERn, ER8 | Rotate Left ERn by ER8 & 0xf bits | ----------------------------------------------------------------------------------------- -SHIFTL (lsl) | | -ERn, ER8 | ERn = ERn >> (ER8 & 0xf) | ----------------------------------------------------------------------------------------- -SHIFTR (asr) | | -ERn, ER8 | ERn = ERn >> (ER8 & 0xf) | ----------------------------------------------------------------------------------------- -ADD16 (saturate) | | -ERp, DPTRi, ERn | ERp = XRAM + ERn + EC | EZ, EC -DPTRi, ERn, ERp | XRAM = ERn + ERp + EC | -ERp, ERn, ERm | ERp = ERn + ERm + EC | ----------------------------------------------------------------------------------------- -SUB16 (saturate) | | -ERp, DPTRi, ERn | ERp = XRAM - ERn - EC | EZ, EC -DPTRi, ERn, ERp | XRAM = ERn - ERp - EC | -ERp, ERn, ERm | ERp = ERn - ERm - EC | ----------------------------------------------------------------------------------------- -SWAP16 | | -ERn | Swap upper and lower 8-bits of ERn | ----------------------------------------------------------------------------------------- - -access to 16-bit registers is mapped in SFR space, from 0xE6 (note, changing SFR bank does NOT update the actual registers) - -ERn - 16-bit register ER0-ER3 (as data?) -ERm - 16-bit register ER0-ER3 (as data?) -ERp - 16-bit register ER0-ER3 (as pointer?) -EACC = 8-bit accumulator (same as regular opcodes?) -EZ = Zero flag (same as regular opcodes?) -EC = Carry flag (same as regular opcodes?) - -*/ - -offs_t axc51core_disassembler::disassemble_extended_a5_0e(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params) -{ - uint32_t flags = 0; - uint8_t prm2 = params.r8(PC++); - - switch (prm2) - { - - case 0x00: case 0x01: case 0x04: case 0x05: case 0x08: case 0x09: case 0x0c: case 0x0d: - case 0x10: case 0x11: case 0x14: case 0x15: case 0x18: case 0x19: case 0x1c: case 0x1d: - case 0x20: case 0x21: case 0x24: case 0x25: case 0x28: case 0x29: case 0x2c: case 0x2d: - case 0x30: case 0x31: case 0x34: case 0x35: case 0x38: case 0x39: case 0x3c: case 0x3d: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "ADD16 ER%01x, EDP%01x, ER%01x", p, i, n); - break; - } - - case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0b: case 0x0e: case 0x0f: - case 0x12: case 0x13: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1e: case 0x1f: - case 0x22: case 0x23: case 0x26: case 0x27: case 0x2a: case 0x2b: case 0x2e: case 0x2f: - case 0x32: case 0x33: case 0x36: case 0x37: case 0x3a: case 0x3b: case 0x3e: case 0x3f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "ADD16 EDP%01x, ER%01x, ER%01x", i, n, p); - break; - } - - 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 0x4e: 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 0x5e: 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 0x6e: 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 0x7e: case 0x7f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t m = (prm2 & 0x03) >> 0; - util::stream_format(stream, "ADD16 ER%01x, ER%01x, ER%01x", p, n, m); - break; - } - - default: - util::stream_format(stream, "illegal ax208 a5 0e $%02X", prm2); - break; - } - - return (PC - pc) | flags | SUPPORTED; -} - -offs_t axc51core_disassembler::disassemble_extended_a5_0f(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params) -{ - uint32_t flags = 0; - uint8_t prm2 = params.r8(PC++); - - switch (prm2) - { - - case 0x00: case 0x01: case 0x04: case 0x05: case 0x08: case 0x09: case 0x0c: case 0x0d: - case 0x10: case 0x11: case 0x14: case 0x15: case 0x18: case 0x19: case 0x1c: case 0x1d: - case 0x20: case 0x21: case 0x24: case 0x25: case 0x28: case 0x29: case 0x2c: case 0x2d: - case 0x30: case 0x31: case 0x34: case 0x35: case 0x38: case 0x39: case 0x3c: case 0x3d: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "SUB16 ER%01x, EDP%01x, ER%01x", p, i, n); - break; - } - - case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0b: case 0x0e: case 0x0f: - case 0x12: case 0x13: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1e: case 0x1f: - case 0x22: case 0x23: case 0x26: case 0x27: case 0x2a: case 0x2b: case 0x2e: case 0x2f: - case 0x32: case 0x33: case 0x36: case 0x37: case 0x3a: case 0x3b: case 0x3e: case 0x3f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "SUB16 EDP%01x, ER%01x, ER%01x", i, n, p); - break; - } - - 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 0x4e: 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 0x5e: 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 0x6e: 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 0x7e: case 0x7f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t m = (prm2 & 0x03) >> 0; - util::stream_format(stream, "SUB16 ER%01x, ER%01x, ER%01x", p, n, m); - break; - } - - - default: - util::stream_format(stream, "illegal ax208 a5 0f $%02X", prm2); - break; - } - - return (PC - pc) | flags | SUPPORTED; -} - -offs_t axc51core_disassembler::disassemble_extended_a5_d0(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params) -{ - uint32_t flags = 0; - uint8_t prm2 = params.r8(PC++); - - switch (prm2) - { - - case 0x00: case 0x01: case 0x04: case 0x05: case 0x08: case 0x09: case 0x0c: case 0x0d: - case 0x10: case 0x11: case 0x14: case 0x15: case 0x18: case 0x19: case 0x1c: case 0x1d: - case 0x20: case 0x21: case 0x24: case 0x25: case 0x28: case 0x29: case 0x2c: case 0x2d: - case 0x30: case 0x31: case 0x34: case 0x35: case 0x38: case 0x39: case 0x3c: case 0x3d: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "ADDS16 ER%01x, EDP%01x, ER%01x", p, i, n); - break; - } - - case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0b: case 0x0e: case 0x0f: - case 0x12: case 0x13: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1e: case 0x1f: - case 0x22: case 0x23: case 0x26: case 0x27: case 0x2a: case 0x2b: case 0x2e: case 0x2f: - case 0x32: case 0x33: case 0x36: case 0x37: case 0x3a: case 0x3b: case 0x3e: case 0x3f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "ADDS16 EDP%01x, ER%01x, ER%01x", i, n, p); - break; - } - - 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 0x4e: 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 0x5e: 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 0x6e: 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 0x7e: case 0x7f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t m = (prm2 & 0x03) >> 0; - util::stream_format(stream, "ADDS16 ER%01x, ER%01x, ER%01x", p, n, m); - break; - } - - default: - util::stream_format(stream, "illegal ax208 a5 d0 $%02X", prm2); - break; - } - - return (PC - pc) | flags | SUPPORTED; -} - -offs_t axc51core_disassembler::disassemble_extended_a5_d1(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params) -{ - uint32_t flags = 0; - uint8_t prm2 = params.r8(PC++); - - switch (prm2) - { - - case 0x00: case 0x01: case 0x04: case 0x05: case 0x08: case 0x09: case 0x0c: case 0x0d: - case 0x10: case 0x11: case 0x14: case 0x15: case 0x18: case 0x19: case 0x1c: case 0x1d: - case 0x20: case 0x21: case 0x24: case 0x25: case 0x28: case 0x29: case 0x2c: case 0x2d: - case 0x30: case 0x31: case 0x34: case 0x35: case 0x38: case 0x39: case 0x3c: case 0x3d: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "SUBS16 ER%01x, EDP%01x, ER%01x", p, i, n); - break; - } - - case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0b: case 0x0e: case 0x0f: - case 0x12: case 0x13: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1e: case 0x1f: - case 0x22: case 0x23: case 0x26: case 0x27: case 0x2a: case 0x2b: case 0x2e: case 0x2f: - case 0x32: case 0x33: case 0x36: case 0x37: case 0x3a: case 0x3b: case 0x3e: case 0x3f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t i = (prm2 & 0x01) >> 0; - - util::stream_format(stream, "SUBS16 EDP%01x, ER%01x, ER%01x", i, n, p); - break; - } - - 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 0x4e: 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 0x5e: 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 0x6e: 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 0x7e: case 0x7f: - { - uint8_t p = (prm2 & 0x30) >> 4; - uint8_t n = (prm2 & 0x0c) >> 2; - uint8_t m = (prm2 & 0x03) >> 0; - util::stream_format(stream, "SUBS16 ER%01x, ER%01x, ER%01x", p, n, m); - break; - } - - default: - util::stream_format(stream, "illegal ax208 a5 d1 $%02X", prm2); - break; - } - - return (PC - pc) | flags | SUPPORTED; -} - - -offs_t axc51core_disassembler::disassemble_extended_a5(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params) -{ - uint32_t flags = 0; - uint8_t prm = params.r8(PC++); - - switch (prm) - { - case 0x00: - util::stream_format(stream, "INCDP0"); - break; - - case 0x01: - util::stream_format(stream, "INCDP1"); - break; - - case 0x02: - util::stream_format(stream, "DECDP0"); - break; - - case 0x03: - util::stream_format(stream, "DECDP1"); - break; - - case 0x04: - util::stream_format(stream, "ADDDP0"); - break; - - case 0x05: - util::stream_format(stream, "ADDDP1"); - break; - - case 0x06: - util::stream_format(stream, "SUBDP0"); - break; - - case 0x07: - util::stream_format(stream, "SUBDP1"); - break; - - case 0x08: - util::stream_format(stream, "INC2DP0"); - break; - - case 0x09: - util::stream_format(stream, "INC2DP1"); - break; - - case 0x0a: - util::stream_format(stream, "DEC2DP0"); - break; - - case 0x0b: - util::stream_format(stream, "DEC2DP1"); - break; - - case 0x0c: - util::stream_format(stream, "ROTR8 EACC, ER8"); - break; - - case 0x0d: - util::stream_format(stream, "ROTL8 EACC, ER8"); - break; - - case 0x0e: // ADD16 - return disassemble_extended_a5_0e(stream, PC, pc, opcodes, params); - - case 0x0f: // SUB16 - return disassemble_extended_a5_0f(stream, PC, pc, opcodes, params); - - case 0x10: case 0x14: case 0x18: case 0x1c: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "NOT16 ER%01x", n); - break; - } - - case 0x11: case 0x15: case 0x19: case 0x1d: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "CLR16 ER%01x", n); - break; - } - - case 0x12: case 0x16: case 0x1a: case 0x1e: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "INC16 ER%01x", n); - break; - } - - case 0x13: case 0x17: case 0x1b: case 0x1f: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "DEC16 ER%01x", n); - break; - } - - case 0x20: case 0x21: case 0x24: case 0x25: case 0x28: case 0x29: case 0x2c: case 0x2d: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "ANL16 ER%01x, EDP%01x", n, i); - break; - } - - case 0x22: case 0x23: case 0x26: case 0x27: case 0x2a: case 0x2b: case 0x2e: case 0x2f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "ANL16 EDP%01x, ER%01x", i, n); - break; - } - - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "ANL16 ER%01x, ER%01x", n, m); - break; - } - - case 0x40: case 0x41: case 0x44: case 0x45: case 0x48: case 0x49: case 0x4c: case 0x4d: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "ORL16 ER%01x, EDP%01x", n, i); - break; - } - - case 0x42: case 0x43: case 0x46: case 0x47: case 0x4a: case 0x4b: case 0x4e: case 0x4f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "ORL16 EDP%01x, ER%01x", i, n); - break; - } - - 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 0x5e: case 0x5f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "ORL16 ER%01x, ER%01x", n, m); - break; - } - - case 0x60: case 0x61: case 0x64: case 0x65: case 0x68: case 0x69: case 0x6c: case 0x6d: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "XRL16 ER%01x, EDP%01x", n, i); - break; - } - - case 0x62: case 0x63: case 0x66: case 0x67: case 0x6a: case 0x6b: case 0x6e: case 0x6f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "XRL16 EDP%01x, ER%01x", i, n); - break; - } - - 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 0x7e: case 0x7f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "XRL16 ER%01x, ER%01x", n, m); - break; - } - - case 0x80: case 0x81: case 0x84: case 0x85: case 0x88: case 0x89: case 0x8c: case 0x8d: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "MOV16 ER%01x, EDP%01x", n, i); - break; - } - - case 0x82: case 0x83: case 0x86: case 0x87: case 0x8a: case 0x8b: case 0x8e: case 0x8f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t i = (prm & 0x01) >> 0; - - util::stream_format(stream, "MOV16 EDP%01x, ER%01x", i, n); - break; - } - - case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "MOV16 ER%01x, ER%01x", n, m); - break; - } - - case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "MUL16 ER%01x, ER%01x", n, m); - break; - } - - case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: - { - uint8_t n = (prm & 0x0c) >> 2; - uint8_t m = (prm & 0x03) >> 0; - - util::stream_format(stream, "MULS16 ER%01x, ER%01x", n, m); - break; - } - - case 0xc0: case 0xc4: case 0xc8: case 0xcc: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "ROTR16 ER%01x, ER8", n); - break; - } - - case 0xc1: case 0xc5: case 0xc9: case 0xcd: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "ROTL16 ER%01x, ER8", n); - break; - } - - case 0xc2: case 0xc6: case 0xca: case 0xce: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "SHIFTL ER%01x, ER8", n); - break; - } - - case 0xc3: case 0xc7: case 0xcb: case 0xcf: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "SHIFTA ER%01x, ER8", n); - break; - } - - case 0xd0: // ADDS16 - return disassemble_extended_a5_d0(stream, PC, pc, opcodes, params); - - case 0xd1: // SUBS16 - return disassemble_extended_a5_d1(stream, PC, pc, opcodes, params); - - case 0xd2: case 0xd6: case 0xda: case 0xde: - { - uint8_t n = (prm & 0x0c) >> 2; - util::stream_format(stream, "SWAP16 ER%01x", n); - break; - } - - case 0xd3: case 0xd4: case 0xd5: case 0xd7: case 0xd8: case 0xd9: case 0xdb: case 0xdc: case 0xdd: case 0xdf: - util::stream_format(stream, "invalid ax208 a5 $%02X", prm); - break; - - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: - util::stream_format(stream, "invalid ax208 a5 $%02X", prm); - break; - - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: - util::stream_format(stream, "invalid ax208 a5 $%02X", prm); - break; - - default: - util::stream_format(stream, "unknown ax208 a5 $%02X", prm); - break; - } - - 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; - - switch (op) - { - case 0xa5: - return disassemble_extended_a5(stream, PC, pc, opcodes, params); - - default: - return mcs51_disassembler::disassemble_op(stream, PC, pc, opcodes, params, op); - } - - return (PC - pc) | flags | SUPPORTED; -} - - -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 deleted file mode 100644 index 0e9bd5c3ed2..00000000000 --- a/src/devices/cpu/mcs51/axc51-core_dasm.h +++ /dev/null @@ -1,63 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/***************************************************************************** - - AXC51-CORE (AppoTech Inc.) - - used in - - AX208 SoC - - *****************************************************************************/ - -#ifndef MAME_CPU_MCS51_AXC51_CORE_DASM_H -#define MAME_CPU_MCS51_AXC51_CORE_DASM_H - -#pragma once - -#include "mcs51dasm.h" - -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[]; - -protected: - virtual offs_t disassemble_op(std::ostream &stream, unsigned PC, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms, uint8_t op) override; - -private: - offs_t disassemble_extended_a5(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params); - offs_t disassemble_extended_a5_0e(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params); - offs_t disassemble_extended_a5_0f(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params); - offs_t disassemble_extended_a5_d0(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params); - offs_t disassemble_extended_a5_d1(std::ostream& stream, unsigned PC, offs_t pc, const data_buffer& opcodes, const data_buffer& params); - -}; - -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/mcs51.cpp b/src/devices/cpu/mcs51/mcs51.cpp index 21f64953a45..5c0e9034f6d 100644 --- a/src/devices/cpu/mcs51/mcs51.cpp +++ b/src/devices/cpu/mcs51/mcs51.cpp @@ -2,139 +2,100 @@ // copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud /***************************************************************************** * - * i8051.c - * Portable MCS-51 Family Emulator + * Portable MCS-51 Family Emulator + * Copyright Steve Ellenoff * - * Chips in the family: - * 8051 Product Line (8031,8051,8751) - * 8052 Product Line (8032,8052,8752) - * 8054 Product Line (8054) - * 8058 Product Line (8058) + * Chips in the family: + * 8051 Product Line (8031,8051,8751) + * 8052 Product Line (8032,8052,8752) + * 8054 Product Line (8054) + * 8058 Product Line (8058) + * 80552 Product Line (80552, 83552, 87552) + * 80562 Product Line (80562, 83562, 87562) * - * Copyright Steve Ellenoff, all rights reserved. - * - * This work is based on: - * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and - * #2) 8051 simulator by Travis Marlatte - * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE) + * This work is based on: + * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and + * #2) 8051 simulator by Travis Marlatte + * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE) * *****************************************************************************/ /***************************************************************************** - * DS5002FP emulator by Manuel Abadia - * - * October 2008, couriersud: Merged back in mcs51 * - * What has been added? - * - Extra SFRs - * - Bytewide Bus Support - * - Memory Partition and Memory Range - * - Bootstrap Configuration - * - Power Fail Interrupt - * - Timed Access - * - Stop Mode - * - Idle Mode + * DS5002FP emulator by Manuel Abadia * - * What is not implemented? - * - Peripherals and Reprogrammable Peripheral Controller - * - CRC-16 - * - Watchdog timer + * The main features of the DS5002FP are: + * - 100% code-compatible with 8051 + * - Directly addresses 64kB program/64kB data memory + * - Nonvolatile memory control circuitry + * - 10-year data retention in the absence of power + * - In-system reprogramming via serial port + * - Dedicated memory bus, preserving four 8-bit ports for general purpose I/O + * - Power-fail reset + * - Early warning power-fail interrupt + * - Watchdog timer + * - Accesses up to 128kB on the bytewide bus + * - Decodes memory for 32kB x 8 or 128kB x 8 SRAMs + * - Four additional decoded peripheral-chip enables + * - CRC hardware for checking memory validity + * - Optionally emulates an 8042-style slave interface + * - Memory encryption using an 80-bit encryption key + * - Automatic random generation of encryption keys + * - Self-destruct input for tamper protection + * - Optional top-coating prevents microprobe * - * The main features of the DS5002FP are: - * - 100% code-compatible with 8051 - * - Directly addresses 64kB program/64kB data memory - * - Nonvolatile memory control circuitry - * - 10-year data retention in the absence of power - * - In-system reprogramming via serial port - * - Dedicated memory bus, preserving four 8-bit ports for general purpose I/O - * - Power-fail reset - * - Early warning power-fail interrupt - * - Watchdog timer - * - Accesses up to 128kB on the bytewide bus - * - Decodes memory for 32kB x 8 or 128kB x 8 SRAMs - * - Four additional decoded peripheral-chip enables - * - CRC hardware for checking memory validity - * - Optionally emulates an 8042-style slave interface - * - Memory encryption using an 80-bit encryption key - * - Automatic random generation of encryption keys - * - Self-destruct input for tamper protection - * - Optional top-coating prevents microprobe + * TODO: + * - Peripherals and Reprogrammable Peripheral Controller + * - CRC-16 + * - Watchdog timer * *****************************************************************************/ /****************************************************************************** - * Notes: - * - * The term cycles is used here to really refer to clock oscilations, because 1 machine cycle - * actually takes 12 oscilations. * - * Read/Write/Modify Instruction - - * Data is read from the Port Latch (not the Port Pin!), possibly modified, and - * written back to (the pin? and) the latch! + * Notes: * - * The following all perform this on a port address.. - * (anl, orl, xrl, jbc, cpl, inc, dec, djnz, mov px.y,c, clr px.y, setb px.y) + * The term cycles is used here to really refer to clock oscilations, because 1 machine cycle + * actually takes 12 oscilations. * - * Serial UART emulation is not really accurate, but faked enough to work as far as i can tell + * Read/Write/Modify Instruction - + * Data is read from the Port Latch (not the Port Pin!), possibly modified, and + * written back to (the pin? and) the latch! * - * August 27,2003: Currently support for only 8031/8051/8751 chips (ie 128 RAM) - * October 14,2003: Added initial support for the 8752 (ie 256 RAM) - * October 22,2003: Full support for the 8752 (ie 256 RAM) - * July 28,2004: Fixed MOVX command and added External Ram Paging Support - * July 31,2004: Added Serial Mode 0 Support & Fixed Interrupt Flags for Serial Port - * - * October, 2008, Couriersud - Major rewrite + * The following all perform this on a port address.. + * (anl, orl, xrl, jbc, cpl, inc, dec, djnz, mov px.y,c, clr px.y, setb px.y) * *****************************************************************************/ -/* TODO: Varios - * - EA pin - defined by architecture, must implement: - * 1 means external access, bypassing internal ROM - * - T0 output clock ? +/* TODO: Various + * - EA pin - defined by architecture, must implement: + * 1 means external access, bypassing internal ROM + * - T0 output clock ? * * - Implement 80C52 extended serial capabilities - * - Fix serial communication - This is a big hack (but working) right now. * - Implement 83C751 in sslam.c * - Fix cardline.c * most likely due to different behaviour of I/O pins. The boards * actually use 80CXX, i.e. CMOS versions. * "Normal" 805X will return a 0 if reading from a output port which has * a 0 written to it's latch. At least cardline expects a 1 here. + * - ADC support for 80552/80562 (controls analog inputs for Arctic Thunder) * - * Done: (Couriersud) - * - Merged DS5002FP - * - Disassembler now uses type specific memory names - * - Merged DS5002FP disasm - * - added 83C751 memory names to disassembler - * - Pointer-ified - * - Implemented cmos features - * - Implemented 80C52 interrupt handling - * - Fix segas18.c (segaic16.c) memory handling. - * - Fix sslam.c - * - Fix limenko.c videopkr.c : Issue with core allocation of ram (duplicate savestate) - * - Handle internal ram better (debugger visible) - * - Fixed port reading - * - Rewrote Macros for better readability - * - Fixed and rewrote Interrupt handling - * - Now returns INTERNAL_DIVIDER, adjusted cycle counts - * - Remove unnecessary and duplicated code - * - Remove unnecessary functions - * - Rewrite to have sfr-registers stored in int_ram. - * - Debugger may now watch sfr-registers as well. - * - implemented interrupt callbacks (HOLD_LINE now supported) - * - Runtime switch for processor type - remove ifdefs - * - internal memory maps for internal rom versions (internal ram now displayed in debugger) - * - more timer cleanups from manual */ #include "emu.h" -#include "debugger.h" #include "mcs51.h" #include "mcs51dasm.h" -#define VERBOSE 0 +#include <tuple> + +#define LOG_RX (1U << 1) +#define LOG_TX (1U << 2) + +#define VERBOSE (0) + +#include "logmacro.h" -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) /*************************************************************************** CONSTANTS @@ -142,11 +103,11 @@ enum { - FEATURE_NONE = 0x00, - FEATURE_I8052 = 0x01, - FEATURE_CMOS = 0x02, - FEATURE_I80C52 = 0x04, - FEATURE_DS5002FP = 0x08 + FEATURE_NONE = 0x00, + FEATURE_I8052 = 0x01, + FEATURE_CMOS = 0x02, + FEATURE_I80C52 = 0x04, + FEATURE_DS5002FP = 0x08 }; /* Internal address in SFR of registers */ @@ -200,7 +161,6 @@ enum ADDR_RNR = 0xcf, ADDR_RPCTL = 0xd8, ADDR_RPS = 0xda - }; /* PC vectors */ @@ -221,6 +181,22 @@ enum V_PFI = 0x02b /* Power Failure Interrupt */ }; +enum serial_state : u8 +{ + SIO_IDLE, + SIO_START_LE, + SIO_START, + SIO_DATA0, + SIO_DATA1, + SIO_DATA2, + SIO_DATA3, + SIO_DATA4, + SIO_DATA5, + SIO_DATA6, + SIO_DATA7, + SIO_DATA8, + SIO_STOP, +}; DEFINE_DEVICE_TYPE(I8031, i8031_device, "i8031", "Intel 8031") DEFINE_DEVICE_TYPE(I8032, i8032_device, "i8032", "Intel 8032") @@ -235,10 +211,18 @@ DEFINE_DEVICE_TYPE(I87C51, i87c51_device, "i87c51", "Intel 87C51") DEFINE_DEVICE_TYPE(I80C32, i80c32_device, "i80c32", "Intel 80C32") DEFINE_DEVICE_TYPE(I80C52, i80c52_device, "i80c52", "Intel 80C52") DEFINE_DEVICE_TYPE(I87C52, i87c52_device, "i87c52", "Intel 87C52") +DEFINE_DEVICE_TYPE(I87C51FA, i87c51fa_device, "i87c51fa", "Intel 87C51FA") DEFINE_DEVICE_TYPE(I80C51GB, i80c51gb_device, "i80c51gb", "Intel 80C51GB") DEFINE_DEVICE_TYPE(AT89C52, at89c52_device, "at89c52", "Atmel AT89C52") DEFINE_DEVICE_TYPE(AT89S52, at89s52_device, "at89s52", "Atmel AT89S52") DEFINE_DEVICE_TYPE(AT89C4051, at89c4051_device, "at89c4051", "Atmel AT89C4051") +DEFINE_DEVICE_TYPE(DS80C320, ds80c320_device, "ds80c320", "Dallas DS80C320 HSM") +DEFINE_DEVICE_TYPE(SAB80C535, sab80c535_device, "sab80c535", "Siemens SAB80C535") +DEFINE_DEVICE_TYPE(I8344, i8344_device, "i8344", "Intel 8344AH RUPI-44") +DEFINE_DEVICE_TYPE(I8744, i8744_device, "i8744", "Intel 8744H RUPI-44") +DEFINE_DEVICE_TYPE(P80C552, p80c552_device, "p80c552", "Philips P80C552") +DEFINE_DEVICE_TYPE(P87C552, p87c552_device, "p87c552", "Philips P87C552") +DEFINE_DEVICE_TYPE(P80C562, p80c562_device, "p80c562", "Philips P80C562") DEFINE_DEVICE_TYPE(DS5002FP, ds5002fp_device, "ds5002fp", "Dallas DS5002FP") @@ -260,22 +244,21 @@ void mcs51_cpu_device::data_internal(address_map &map) -mcs51_cpu_device::mcs51_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::mcs51_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map, address_map_constructor data_map, int program_width, int data_width, uint8_t features) : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(mcs51_cpu_device::program_internal), this)) - , m_data_config("data", ENDIANNESS_LITTLE, 8, 9, 0, address_map_constructor(FUNC(mcs51_cpu_device::data_internal), this)) - , m_io_config("io", ENDIANNESS_LITTLE, 8, (features & FEATURE_DS5002FP) ? 17 : 16, 0) + , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, program_map) + , m_data_config("data", ENDIANNESS_LITTLE, 8, 9, 0, data_map) + , m_io_config("io", ENDIANNESS_LITTLE, 8, (features & FEATURE_DS5002FP) ? 18 : 16, 0) , m_pc(0) , m_features(features) + , m_inst_cycles(0) , m_rom_size(program_width > 0 ? 1 << program_width : 0) - , m_ram_mask( (data_width == 8) ? 0xFF : 0x7F ) + , m_ram_mask((data_width == 8) ? 0xff : 0x7f) , m_num_interrupts(5) , m_sfr_ram(*this, "sfr_ram") , m_scratchpad(*this, "scratchpad") - , m_port_in_cb{{*this}, {*this}, {*this}, {*this}} - , m_port_out_cb{{*this}, {*this}, {*this}, {*this}} - , m_serial_tx_cb(*this) - , m_serial_rx_cb(*this) + , m_port_in_cb(*this, 0xff) + , m_port_out_cb(*this) , m_rtemp(0) { m_ds5002fp.mcon = 0; @@ -283,12 +266,17 @@ mcs51_cpu_device::mcs51_cpu_device(const machine_config &mconfig, device_type ty m_ds5002fp.crc = 0; /* default to standard cmos interfacing */ - for (auto & elem : m_forced_inputs) elem = 0; } +mcs51_cpu_device::mcs51_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, address_map_constructor(FUNC(mcs51_cpu_device::program_internal), this), address_map_constructor(FUNC(mcs51_cpu_device::data_internal), this), program_width, data_width, features) +{ +} + + i8031_device::i8031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mcs51_cpu_device(mconfig, I8031, tag, owner, clock, 0, 7) { @@ -372,8 +360,18 @@ i87c52_device::i87c52_device(const machine_config &mconfig, const char *tag, dev { } +i87c51fa_device::i87c51fa_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) + : i80c52_device(mconfig, type, tag, owner, clock, program_width, data_width, features) +{ +} + +i87c51fa_device::i87c51fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : i87c51fa_device(mconfig, I87C51FA, tag, owner, clock, 13, 8) +{ +} + i80c51gb_device::i80c51gb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : i80c52_device(mconfig, I80C51GB, tag, owner, clock, 0, 8) + : i87c51fa_device(mconfig, I80C51GB, tag, owner, clock, 0, 8) { } @@ -392,6 +390,46 @@ at89c4051_device::at89c4051_device(const machine_config &mconfig, const char *ta { } +ds80c320_device::ds80c320_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : i80c52_device(mconfig, DS80C320, tag, owner, clock, 0, 8) +{ +} + +sab80c535_device::sab80c535_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : i80c51_device(mconfig, SAB80C535, tag, owner, clock, 0, 8) +{ +} + +i8344_device::i8344_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mcs51_cpu_device(mconfig, I8344, tag, owner, clock, 0, 8) +{ +} + +i8744_device::i8744_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mcs51_cpu_device(mconfig, I8744, tag, owner, clock, 12, 8) +{ +} + +p80c562_device::p80c562_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) + : i80c51_device(mconfig, type, tag, owner, clock, program_width, data_width, features) +{ +} + +p80c562_device::p80c562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : p80c562_device(mconfig, P80C562, tag, owner, clock, 0, 8) +{ +} + +p80c552_device::p80c552_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : p80c562_device(mconfig, P80C552, tag, owner, clock, 0, 8) +{ +} + +p87c552_device::p87c552_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : p80c562_device(mconfig, P87C552, tag, owner, clock, 12, 8) +{ +} + /* program width field is set to 0 because technically the SRAM isn't internal */ ds5002fp_device::ds5002fp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mcs51_cpu_device(mconfig, DS5002FP, tag, owner, clock, 0, 7, FEATURE_DS5002FP | FEATURE_CMOS) @@ -415,15 +453,15 @@ device_memory_interface::space_config_vector mcs51_cpu_device::memory_space_conf ***************************************************************************/ /* Read Opcode/Opcode Arguments from Program Code */ -#define ROP(pc) m_cache->read_byte(pc) -#define ROP_ARG(pc) m_cache->read_byte(pc) +#define ROP(pc) m_program.read_byte(pc) +#define ROP_ARG(pc) m_program.read_byte(pc) /* Read a byte from External Code Memory (Usually Program Rom(s) Space) */ -#define CODEMEM_R(a) (uint8_t)m_program->read_byte(a) +#define CODEMEM_R(a) (uint8_t)m_program.read_byte(a) /* Read/Write a byte from/to External Data Memory (Usually RAM or other I/O) */ -#define DATAMEM_R(a) (uint8_t)m_io->read_byte(a) -#define DATAMEM_W(a,v) m_io->write_byte(a, v) +#define DATAMEM_R(a) (uint8_t)m_io.read_byte(a) +#define DATAMEM_W(a,v) m_io.write_byte(a, v) /* Read/Write a byte from/to the Internal RAM */ @@ -432,8 +470,8 @@ device_memory_interface::space_config_vector mcs51_cpu_device::memory_space_conf /* Read/Write a byte from/to the Internal RAM indirectly */ /* (called from indirect addressing) */ -uint8_t mcs51_cpu_device::iram_iread(offs_t a) { return (a <= m_ram_mask) ? m_data->read_byte(a) : 0xff; } -void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m_data->write_byte(a, d); } +uint8_t mcs51_cpu_device::iram_iread(offs_t a) { return (a <= m_ram_mask) ? m_data.read_byte(a) : 0xff; } +void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m_data.write_byte(a, d); } #define IRAM_IR(a) iram_iread(a) #define IRAM_IW(a, d) iram_iwrite(a, d) @@ -551,55 +589,55 @@ void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m /* Macros for Setting Flags */ #define SET_X(R, v) do { R = (v);} while (0) -#define SET_CY(n) SET_PSW((PSW & 0x7f) | (n<<7)) //Carry Flag -#define SET_AC(n) SET_PSW((PSW & 0xbf) | (n<<6)) //Aux.Carry Flag -#define SET_FO(n) SET_PSW((PSW & 0xdf) | (n<<5)) //User Flag -#define SET_RS(n) SET_PSW((PSW & 0xe7) | (n<<3)) //R Bank Select -#define SET_OV(n) SET_PSW((PSW & 0xfb) | (n<<2)) //Overflow Flag -#define SET_P(n) SET_PSW((PSW & 0xfe) | (n<<0)) //Parity Flag - -#define SET_BIT(R, n, v) do { R = (R & ~(1<<(n))) | ((v) << (n));} while (0) -#define GET_BIT(R, n) (((R)>>(n)) & 0x01) - -#define SET_EA(n) SET_BIT(IE, 7, n) //Global Interrupt Enable/Disable -#define SET_ES(n) SET_BIT(IE, 4, v) //Serial Interrupt Enable/Disable -#define SET_ET1(n) SET_BIT(IE, 3, n) //Timer 1 Interrupt Enable/Disable -#define SET_EX1(n) SET_BIT(IE, 2, n) //External Int 1 Interrupt Enable/Disable -#define SET_ET0(n) SET_BIT(IE, 1, n) //Timer 0 Interrupt Enable/Disable -#define SET_EX0(n) SET_BIT(IE, 0, n) //External Int 0 Interrupt Enable/Disable +#define SET_CY(n) SET_PSW((PSW & 0x7f) | ((n) << 7)) //Carry Flag +#define SET_AC(n) SET_PSW((PSW & 0xbf) | ((n) << 6)) //Aux.Carry Flag +#define SET_FO(n) SET_PSW((PSW & 0xdf) | ((n) << 5)) //User Flag +#define SET_RS(n) SET_PSW((PSW & 0xe7) | ((n) << 3)) //R Bank Select +#define SET_OV(n) SET_PSW((PSW & 0xfb) | ((n) << 2)) //Overflow Flag +#define SET_P(n) SET_PSW((PSW & 0xfe) | ((n) << 0)) //Parity Flag + +#define SET_BIT(R, n, v) do { R = (R & ~(1 << (n))) | ((v) << (n)); } while (0) +#define GET_BIT(R, n) (((R) >> (n)) & 0x01) + +#define SET_EA(n) SET_BIT(IE, 7, n) //Global Interrupt Enable/Disable +#define SET_ES(n) SET_BIT(IE, 4, v) //Serial Interrupt Enable/Disable +#define SET_ET1(n) SET_BIT(IE, 3, n) //Timer 1 Interrupt Enable/Disable +#define SET_EX1(n) SET_BIT(IE, 2, n) //External Int 1 Interrupt Enable/Disable +#define SET_ET0(n) SET_BIT(IE, 1, n) //Timer 0 Interrupt Enable/Disable +#define SET_EX0(n) SET_BIT(IE, 0, n) //External Int 0 Interrupt Enable/Disable /* 8052 Only flags */ -#define SET_ET2(n) SET_BIT(IE, 5, n) //Timer 2 Interrupt Enable/Disable +#define SET_ET2(n) SET_BIT(IE, 5, n) //Timer 2 Interrupt Enable/Disable /* 8052 Only flags */ -#define SET_PT2(n) SET_BIT(IP, 5, n); //Set Timer 2 Priority Level +#define SET_PT2(n) SET_BIT(IP, 5, n) //Set Timer 2 Priority Level -#define SET_PS0(n) SET_BIT(IP, 4, n) //Set Serial Priority Level -#define SET_PT1(n) SET_BIT(IP, 3, n) //Set Timer 1 Priority Level -#define SET_PX1(n) SET_BIT(IP, 2, n) //Set External Int 1 Priority Level -#define SET_PT0(n) SET_BIT(IP, 1, n) //Set Timer 0 Priority Level -#define SET_PX0(n) SET_BIT(IP, 0, n) //Set External Int 0 Priority Level +#define SET_PS0(n) SET_BIT(IP, 4, n) //Set Serial Priority Level +#define SET_PT1(n) SET_BIT(IP, 3, n) //Set Timer 1 Priority Level +#define SET_PX1(n) SET_BIT(IP, 2, n) //Set External Int 1 Priority Level +#define SET_PT0(n) SET_BIT(IP, 1, n) //Set Timer 0 Priority Level +#define SET_PX0(n) SET_BIT(IP, 0, n) //Set External Int 0 Priority Level -#define SET_TF1(n) SET_BIT(TCON, 7, n) //Indicated Timer 1 Overflow Int Triggered +#define SET_TF1(n) SET_BIT(TCON, 7, n) //Indicated Timer 1 Overflow Int Triggered #define SET_TR1(n) SET_BIT(TCON, 6, n) //IndicateS Timer 1 is running -#define SET_TF0(n) SET_BIT(TCON, 5, n) //Indicated Timer 0 Overflow Int Triggered +#define SET_TF0(n) SET_BIT(TCON, 5, n) //Indicated Timer 0 Overflow Int Triggered #define SET_TR0(n) SET_BIT(TCON, 4, n) //IndicateS Timer 0 is running #define SET_IE1(n) SET_BIT(TCON, 3, n) //Indicated External Int 1 Triggered #define SET_IT1(n) SET_BIT(TCON, 2, n) //Indicates how External Int 1 is Triggered #define SET_IE0(n) SET_BIT(TCON, 1, n) //Indicated External Int 0 Triggered #define SET_IT0(n) SET_BIT(TCON, 0, n) //Indicates how External Int 0 is Triggered -#define SET_SM0(n) SET_BIT(SCON, 7, n) //Sets Serial Port Mode +#define SET_SM0(n) SET_BIT(SCON, 7, n) //Sets Serial Port Mode #define SET_SM1(n) SET_BIT(SCON, 6, n) //Sets Serial Port Mode -#define SET_SM2(n) SET_BIT(SCON, 5, n) //Sets Serial Port Mode (Multiprocesser mode) +#define SET_SM2(n) SET_BIT(SCON, 5, n) //Sets Serial Port Mode (Multiprocesser mode) #define SET_REN(n) SET_BIT(SCON, 4, n) //Sets Serial Port Receive Enable #define SET_TB8(n) SET_BIT(SCON, 3, n) //Transmit 8th Bit #define SET_RB8(n) SET_BIT(SCON, 2, n) //Receive 8th Bit #define SET_TI(n) SET_BIT(SCON, 1, n) //Indicates Transmit Interrupt Occurred #define SET_RI(n) SET_BIT(SCON, 0, n) //Indicates Receive Interrupt Occurred -#define SET_GATE1(n) SET_BIT(TMOD, 7, n) //Timer 1 Gate Mode +#define SET_GATE1(n) SET_BIT(TMOD, 7, n) //Timer 1 Gate Mode #define SET_CT1(n) SET_BIT(TMOD, 6, n) //Timer 1 Counter Mode -#define SET_M1_1(n) SET_BIT(TMOD, 5, n) //Timer 1 Timer Mode Bit 1 +#define SET_M1_1(n) SET_BIT(TMOD, 5, n) //Timer 1 Timer Mode Bit 1 #define SET_M1_0(n) SET_BIT(TMOD, 4, n) //Timer 1 Timer Mode Bit 0 #define SET_GATE0(n) SET_BIT(TMOD, 3, n) //Timer 0 Gate Mode #define SET_CT0(n) SET_BIT(TMOD, 2, n) //Timer 0 Counter Mode @@ -609,14 +647,14 @@ void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m /* 8052 Only flags - T2CON Flags */ -#define SET_TF2(n) SET_BIT(T2CON, 7, n) //Indicated Timer 2 Overflow Int Triggered -#define SET_EXF2(n) SET_BIT(T2CON, 6, n) //Indicates Timer 2 External Flag -#define SET_RCLK(n) SET_BIT(T2CON, 5, n) //Receive Clock -#define SET_TCLK(n) SET_BIT(T2CON, 4, n) //Transmit Clock -#define SET_EXEN2(n) SET_BIT(T2CON, 3, n) //Timer 2 External Interrupt Enable -#define SET_TR2(n) SET_BIT(T2CON, 2, n) //Indicates Timer 2 is running -#define SET_CT2(n) SET_BIT(T2CON, 1, n) //Sets Timer 2 Counter/Timer Mode -#define SET_CP(n) SET_BIT(T2CON, 0, n) //Sets Timer 2 Capture/Reload Mode +#define SET_TF2(n) SET_BIT(T2CON, 7, n) //Indicated Timer 2 Overflow Int Triggered +#define SET_EXF2(n) SET_BIT(T2CON, 6, n) //Indicates Timer 2 External Flag +#define SET_RCLK(n) SET_BIT(T2CON, 5, n) //Receive Clock +#define SET_TCLK(n) SET_BIT(T2CON, 4, n) //Transmit Clock +#define SET_EXEN2(n) SET_BIT(T2CON, 3, n) //Timer 2 External Interrupt Enable +#define SET_TR2(n) SET_BIT(T2CON, 2, n) //Indicates Timer 2 is running +#define SET_CT2(n) SET_BIT(T2CON, 1, n) //Sets Timer 2 Counter/Timer Mode +#define SET_CP(n) SET_BIT(T2CON, 0, n) //Sets Timer 2 Capture/Reload Mode #define SET_GF1(n) SET_BIT(PCON, 3, n) #define SET_GF0(n) SET_BIT(PCON, 2, n) @@ -683,7 +721,7 @@ void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m #define GET_GF1 GET_BIT(PCON, 3) #define GET_GF0 GET_BIT(PCON, 2) #define GET_PD GET_BIT(PCON, 1) -#define GET_IDL (GET_BIT(PCON, 0) & ~(GET_PD)) /* PD takes precedence! */ +#define GET_IDL (GET_BIT(PCON, 0) & ~(GET_PD)) // PD takes precedence! /* 8052 Only flags */ #define GET_TF2 GET_BIT(T2CON, 7) @@ -716,7 +754,7 @@ void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m #define GET_SL GET_BIT(MCON, 0) /* RPCTL Flags - DS5002FP */ -#define GET_RNR GET_BIT(RPCTL, 7) /* Bit 6 ?? */ +#define GET_RNR GET_BIT(RPCTL, 7) // Bit 6 ?? #define GET_EXBS GET_BIT(RPCTL, 5) #define GET_AE GET_BIT(RPCTL, 4) #define GET_IBI GET_BIT(RPCTL, 3) @@ -729,7 +767,7 @@ void mcs51_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m #define DO_ADD_FLAGS(a,d,c) do_add_flags(a, d, c) #define DO_SUB_FLAGS(a,d,c) do_sub_flags(a, d, c) -#define SET_PARITY() do {m_recalc_parity |= 1;} while (0) +#define SET_PARITY() do { m_recalc_parity |= 1; } while (0) #define PUSH_PC() push_pc() #define POP_PC() pop_pc() @@ -755,7 +793,7 @@ void mcs51_cpu_device::clear_current_irq() m_cur_irq_prio = 0; else m_cur_irq_prio = -1; - LOG(("New: %d %02x\n", m_cur_irq_prio, m_irq_active)); + LOG("New: %d %02x\n", m_cur_irq_prio, m_irq_active); } uint8_t mcs51_cpu_device::r_acc() { return SFR_A(ADDR_ACC); } @@ -776,7 +814,7 @@ uint8_t mcs51_cpu_device::r_psw() { return SFR_A(ADDR_PSW); } assume that most hardware will use port 2 for 8bit access as well. On configurations where 8 bit access in conjunction with other ports is used, - it is up to the driver to use AM_MIRROR to mask out the high level address and + it is up to the driver to use mirror() to mask out the high level address and provide it's own mapping. */ @@ -786,12 +824,18 @@ uint8_t mcs51_cpu_device::r_psw() { return SFR_A(ADDR_PSW); } In order to simplify memory mapping to the data address bus, the following address map is assumed for partitioned mode: + PES = 0: 0x00000-0x0ffff -> data memory on the expanded bus 0x10000-0x1ffff -> data memory on the byte-wide bus + PES = 1: + 0x20000-0x2ffff -> memory-mapped peripherals on the byte-wide bus For non-partitioned mode the following memory map is assumed: - 0x0000-0xffff -> data memory (the bus used to access it does not matter) + PES = 0: + 0x00000-0x0ffff -> data memory (the bus used to access it does not matter) + PES = 1: + 0x20000-0x2ffff -> memory-mapped peripherals on the byte-wide bus */ offs_t mcs51_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) @@ -799,18 +843,23 @@ offs_t mcs51_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) /* Memory Range (RG1 and RG0 @ MCON and RPCTL registers) */ static const uint16_t ds5002fp_ranges[4] = { 0x1fff, 0x3fff, 0x7fff, 0xffff }; /* Memory Partition Table (RG1 & RG0 @ MCON & RPCTL registers) */ - static const uint32_t ds5002fp_partitions[16] = { + static const uint32_t ds5002fp_partitions[16] = + { 0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, - 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0x10000 }; + 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0x10000 + }; /* if partition mode is set, adjust offset based on the bus */ if (m_features & FEATURE_DS5002FP) { - if (!GET_PM) { - if (!GET_EXBS) { - if ((offset >= ds5002fp_partitions[GET_PA]) && (offset <= ds5002fp_ranges[m_ds5002fp.range])) { + if (GET_PES) + offset += 0x20000; + else if (!GET_PM) + { + if (!GET_EXBS) + { + if ((offset >= ds5002fp_partitions[GET_PA]) && (offset <= ds5002fp_ranges[m_ds5002fp.range])) offset += 0x10000; - } } } } @@ -826,13 +875,13 @@ offs_t mcs51_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) uint8_t mcs51_cpu_device::iram_read(size_t offset) { - return (((offset) < 0x80) ? m_data->read_byte(offset) : sfr_read(offset)); + return ((offset < 0x80) ? m_data.read_byte(offset) : sfr_read(offset)); } void mcs51_cpu_device::iram_write(size_t offset, uint8_t data) { - if ((offset) < 0x80) - m_data->write_byte(offset, data); + if (offset < 0x80) + m_data.write_byte(offset, data); else sfr_write(offset, data); } @@ -840,19 +889,19 @@ void mcs51_cpu_device::iram_write(size_t offset, uint8_t data) /*Push the current PC to the stack*/ void mcs51_cpu_device::push_pc() { - uint8_t tmpSP = SP+1; //Grab and Increment Stack Pointer - IRAM_IW(tmpSP, (PC & 0xff)); //Store low byte of PC to Internal Ram (Use IRAM_IW to store stack above 128 bytes) - tmpSP++; // "" + uint8_t tmpSP = SP + 1; //Grab and Increment Stack Pointer + IRAM_IW(tmpSP, (PC & 0xff)); //Store low byte of PC to Internal Ram (Use IRAM_IW to store stack above 128 bytes) + tmpSP++; // "" SP = tmpSP; // "" - IRAM_IW(tmpSP, ( (PC & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use IRAM_IW to store stack above 128 bytes) + IRAM_IW(tmpSP, ((PC & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use IRAM_IW to store stack above 128 bytes) } /*Pop the current PC off the stack and into the pc*/ void mcs51_cpu_device::pop_pc() { - uint8_t tmpSP = SP; //Grab Stack Pointer - PC = (IRAM_IR(tmpSP--) & 0xff) << 8; //Store hi byte to PC (must use IRAM_IR to access stack pointing above 128 bytes) - PC = PC | IRAM_IR(tmpSP--); //Store lo byte to PC (must use IRAM_IR to access stack pointing above 128 bytes) + uint8_t tmpSP = SP; //Grab Stack Pointer + PC = (IRAM_IR(tmpSP--) & 0xff) << 8; //Store hi byte to PC (must use IRAM_IR to access stack pointing above 128 bytes) + PC = PC | IRAM_IR(tmpSP--); //Store lo byte to PC (must use IRAM_IR to access stack pointing above 128 bytes) SP = tmpSP; //Decrement Stack Pointer } @@ -861,10 +910,10 @@ void mcs51_cpu_device::set_parity() { //This flag will be set when the accumulator contains an odd # of bits set.. uint8_t p = 0; - int i; uint8_t a = ACC; - for (i=0; i<8; i++) { //Test for each of the 8 bits in the ACC! + for (int i = 0; i < 8; i++) //Test for each of the 8 bits in the ACC! + { p ^= (a & 1); a = (a >> 1); } @@ -874,8 +923,8 @@ void mcs51_cpu_device::set_parity() uint8_t mcs51_cpu_device::bit_address_r(uint8_t offset) { - uint8_t word; - uint8_t mask; + uint8_t word; + uint8_t mask; int bit_pos; int distance; /* distance between bit addressable words */ /* 1 for normal bits, 8 for sfr bit addresses */ @@ -883,17 +932,19 @@ uint8_t mcs51_cpu_device::bit_address_r(uint8_t offset) m_last_bit = offset; //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f) - if (offset < 0x80) { + if (offset < 0x80) + { distance = 1; - word = ( (offset & 0x78) >> 3) * distance + 0x20; + word = ((offset & 0x78) >> 3) * distance + 0x20; bit_pos = offset & 0x7; mask = (0x1 << bit_pos); return((IRAM_R(word) & mask) >> bit_pos); } //SFR bit addressable registers - else { + else + { distance = 8; - word = ( (offset & 0x78) >> 3) * distance + 0x80; + word = ((offset & 0x78) >> 3) * distance + 0x80; bit_pos = offset & 0x7; mask = (0x1 << bit_pos); return ((IRAM_R(word) & mask) >> bit_pos); @@ -904,13 +955,14 @@ uint8_t mcs51_cpu_device::bit_address_r(uint8_t offset) void mcs51_cpu_device::bit_address_w(uint8_t offset, uint8_t bit) { int word; - uint8_t mask; + uint8_t mask; int bit_pos; - uint8_t result; + uint8_t result; int distance; /* User defined bit addresses 0x20-0x2f (values are 0x0-0x7f) */ - if (offset < 0x80) { + if (offset < 0x80) + { distance = 1; word = ((offset & 0x78) >> 3) * distance + 0x20; bit_pos = offset & 0x7; @@ -921,7 +973,8 @@ void mcs51_cpu_device::bit_address_w(uint8_t offset, uint8_t bit) IRAM_W(word, result); } /* SFR bit addressable registers */ - else { + else + { distance = 8; word = ((offset & 0x78) >> 3) * distance + 0x80; bit_pos = offset & 0x7; @@ -935,39 +988,90 @@ void mcs51_cpu_device::bit_address_w(uint8_t offset, uint8_t bit) void mcs51_cpu_device::do_add_flags(uint8_t a, uint8_t data, uint8_t c) { - uint16_t result = a+data+c; - int16_t result1 = (int8_t)a+(int8_t)data+c; + uint16_t result = a + data + c; + int16_t result1 = (int8_t)a + (int8_t)data + c; SET_CY((result & 0x100) >> 8); - result = (a&0x0f)+(data&0x0f)+c; + result = (a & 0x0f) + (data & 0x0f) + c; SET_AC((result & 0x10) >> 4); SET_OV(result1 < -128 || result1 > 127); } void mcs51_cpu_device::do_sub_flags(uint8_t a, uint8_t data, uint8_t c) { - uint16_t result = a-(data+c); - int16_t result1 = (int8_t)a-(int8_t)(data+c); + uint16_t result = a - (data + c); + int16_t result1 = (int8_t)a - (int8_t)(data + c); SET_CY((result & 0x100) >> 8); - result = (a&0x0f)-((data&0x0f)+c); + result = (a & 0x0f) - ((data & 0x0f) + c); SET_AC((result & 0x10) >> 4); SET_OV((result1 < -128 || result1 > 127)); } +void mcs51_cpu_device::transmit(int state) +{ + if (m_uart.txd != state) + { + m_uart.txd = state; + + // P3.1 = SFR(P3) & TxD + if (BIT(SFR_A(ADDR_P3), 1)) + { + if (state) + m_port_out_cb[3](SFR_A(ADDR_P3)); + else + m_port_out_cb[3](SFR_A(ADDR_P3) & ~0x02); + } + } +} + void mcs51_cpu_device::transmit_receive(int source) { - int mode = (GET_SM0<<1) | GET_SM1; + int mode = (GET_SM0 << 1) | GET_SM1; if (source == 1) /* timer1 */ - m_uart.smod_div = (m_uart.smod_div + 1) & (2-GET_SMOD); + m_uart.smod_div = (m_uart.smod_div + 1) & (1-GET_SMOD); - switch(mode) { - //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12 + switch (mode) + { + // 8 bit shifter - rate set by clock freq / 12 case 0: - m_uart.rx_clk += (source == 0) ? 16 : 0; /* clock / 12 */ - m_uart.tx_clk += (source == 0) ? 16 : 0; /* clock / 12 */ - break; + if (source == 0) + { + // TODO: mode 0 serial input is unemulated + // FIXME: output timing is highly simplified and incorrect + switch (m_uart.txbit) + { + case SIO_IDLE: + break; + case SIO_START: + SFR_A(ADDR_P3) |= 0x03; + m_port_out_cb[3](SFR_A(ADDR_P3)); + m_uart.txbit = SIO_DATA0; + break; + case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3: + case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7: + SFR_A(ADDR_P3) &= ~0x03; + if (BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0)) + SFR_A(ADDR_P3) |= 1U << 0; + m_port_out_cb[3](SFR_A(ADDR_P3)); + + if (m_uart.txbit == SIO_DATA7) + { + SET_TI(1); + m_uart.txbit = SIO_STOP; + } + else + m_uart.txbit++; + break; + case SIO_STOP: + SFR_A(ADDR_P3) |= 0x03; + m_port_out_cb[3](SFR_A(ADDR_P3)); + m_uart.txbit = SIO_IDLE; + break; + } + } + return; //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2 case 1: case 3: @@ -988,39 +1092,139 @@ void mcs51_cpu_device::transmit_receive(int source) m_uart.tx_clk += (source == 0) ? (GET_SMOD ? 6 : 3) : 0; /* clock / 12 */ break; } - /* transmit ? */ + + // transmit if (m_uart.tx_clk >= 16) { m_uart.tx_clk &= 0x0f; - if(m_uart.bits_to_send) + + switch (m_uart.txbit) { - m_uart.bits_to_send--; - if(m_uart.bits_to_send == 0) { - //Call the callback function - m_serial_tx_cb(*m_io, 0, m_uart.data_out, 0xff); - //Set Interrupt Flag - SET_TI(1); - } + case SIO_IDLE: + transmit(1); + break; + case SIO_START: + LOGMASKED(LOG_TX, "tx start bit (%s)\n", machine().time().to_string()); + transmit(0); + m_uart.txbit = SIO_DATA0; + break; + case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3: + case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7: + LOGMASKED(LOG_TX, "tx bit %d data %d (%s)\n", m_uart.txbit - SIO_DATA0, BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0), machine().time().to_string()); + transmit(BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0)); + + // mode 1 has no data8/parity bit + if (mode == 1 && m_uart.txbit == SIO_DATA7) + m_uart.txbit = SIO_STOP; + else + m_uart.txbit++; + break; + case SIO_DATA8: // data8/parity bit + LOGMASKED(LOG_TX, "tx bit %d data %d (%s)\n", m_uart.txbit - SIO_DATA0, GET_TB8, machine().time().to_string()); + transmit(GET_TB8); + m_uart.txbit = SIO_STOP; + break; + case SIO_STOP: + LOGMASKED(LOG_TX, "tx stop bit (%s)\n", machine().time().to_string()); + transmit(1); + SET_TI(1); + m_uart.txbit = SIO_IDLE; + break; } - } - /* receive */ - if (m_uart.rx_clk >= 16) + + // receive + if (m_uart.rx_clk >= 16 || m_uart.rxbit < SIO_START) { m_uart.rx_clk &= 0x0f; - if (m_uart.delay_cycles>0) + + if (GET_REN) { - m_uart.delay_cycles--; - if (m_uart.delay_cycles == 0) + // directly read RXD input + int const data = BIT(m_port_in_cb[3](), 0); + + switch (m_uart.rxbit) { - int data = 0; - //Call our callball function to retrieve the data - data = m_serial_rx_cb(*m_io, 0, 0xff); - LOG(("RX Deliver %d\n", data)); - SET_SBUF(data); - //Flag the IRQ - SET_RI(1); - SET_RB8(1); // HACK force 2nd stop bit + case SIO_IDLE: + if (data) + m_uart.rxbit = SIO_START_LE; + break; + case SIO_START_LE: // start bit leading edge + if (!data) + { + LOGMASKED(LOG_RX, "rx start leading edge (%s)\n", machine().time().to_string()); + m_uart.rxbit = SIO_START; + m_uart.rx_clk = 8; + } + break; + case SIO_START: + if (!data) + { + LOGMASKED(LOG_RX, "rx start bit (%s)\n", machine().time().to_string()); + + m_uart.data_in = 0; + m_uart.rxbit = SIO_DATA0; + } + else + // false start bit + m_uart.rxbit = SIO_START_LE; + break; + case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3: + case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7: + LOGMASKED(LOG_RX, "rx bit %d data %d (%s)\n", m_uart.rxbit - SIO_DATA0, data, machine().time().to_string()); + if (data) + m_uart.data_in |= 1U << (m_uart.rxbit - SIO_DATA0); + + // mode 1 has no data8/parity bit + if (mode == 1 && m_uart.rxbit == SIO_DATA7) + m_uart.rxbit = SIO_STOP; + else + m_uart.rxbit++; + break; + case SIO_DATA8: // data8/parity bit + LOGMASKED(LOG_RX, "rx bit %d data %d (%s)\n", m_uart.rxbit - SIO_DATA0, data, machine().time().to_string()); + m_uart.rxb8 = data; + m_uart.rxbit = SIO_STOP; + break; + case SIO_STOP: + if (!GET_RI) + { + switch (mode) + { + case 1: + LOGMASKED(LOG_RX, "rx byte 0x%02x stop %d (%s)\n", m_uart.data_in, data, machine().time().to_string()); + SET_SBUF(m_uart.data_in); + if (!GET_SM2) + { + // RB8 contains stop bit + SET_RB8(data); + SET_RI(1); + } + else if (data) + // RI if valid stop bit + SET_RI(1); + break; + case 2: + case 3: + LOGMASKED(LOG_RX, "rx byte 0x%02x RB8 %d stop %d (%s)\n", m_uart.data_in, m_uart.rxb8, data, machine().time().to_string()); + SET_SBUF(m_uart.data_in); + SET_RB8(m_uart.rxb8); + + // no RI if SM2 && !RB8 + if (!GET_SM2 || GET_RB8) + SET_RI(1); + break; + } + } + else + LOGMASKED(LOG_RX, "rx overrun discarding data 0x%02x\n", m_uart.data_in); + + // next state depends on stop bit validity + if (data) + m_uart.rxbit = SIO_START_LE; + else + m_uart.rxbit = SIO_IDLE; + break; } } } @@ -1029,7 +1233,7 @@ void mcs51_cpu_device::transmit_receive(int source) void mcs51_cpu_device::update_timer_t0(int cycles) { - int mode = (GET_M0_1<<1) | GET_M0_0; + int mode = (GET_M0_1 << 1) | GET_M0_0; uint32_t count; if (GET_TR0) @@ -1046,52 +1250,53 @@ void mcs51_cpu_device::update_timer_t0(int cycles) if (GET_GATE0 && !GET_IE0) delta = 0; - switch(mode) { - case 0: /* 13 Bit Timer Mode */ - count = ((TH0<<5) | ( TL0 & 0x1f ) ); + switch (mode) + { + case 0: /* 13 Bit Timer Mode */ + count = ((TH0 << 5) | (TL0 & 0x1f)); count += delta; - if ( count & 0xffffe000 ) /* Check for overflow */ + if (count & 0xffffe000) /* Check for overflow */ SET_TF0(1); - TH0 = (count>>5) & 0xff; - TL0 = count & 0x1f ; + TH0 = (count >> 5) & 0xff; + TL0 = count & 0x1f; break; - case 1: /* 16 Bit Timer Mode */ - count = ((TH0<<8) | TL0); + case 1: /* 16 Bit Timer Mode */ + count = ((TH0 << 8) | TL0); count += delta; - if ( count & 0xffff0000 ) /* Check for overflow */ + if (count & 0xffff0000) /* Check for overflow */ SET_TF0(1); - TH0 = (count>>8) & 0xff; + TH0 = (count >> 8) & 0xff; TL0 = count & 0xff; break; - case 2: /* 8 Bit Autoreload */ - count = ((uint32_t) TL0) + delta; - if ( count & 0xffffff00 ) /* Check for overflow */ + case 2: /* 8 Bit Autoreload */ + count = ((uint32_t)TL0) + delta; + if (count & 0xffffff00) /* Check for overflow */ { SET_TF0(1); - count += TH0; /* Reload timer */ + count += TH0; /* Reload timer */ } /* Update new values of the counter */ TL0 = count & 0xff; break; case 3: /* Split Timer 1 */ - count = ((uint32_t) TL0) + delta; - if ( count & 0xffffff00 ) /* Check for overflow */ + count = ((uint32_t)TL0) + delta; + if (count & 0xffffff00) /* Check for overflow */ SET_TF0(1); - TL0 = count & 0xff; /* Update new values of the counter */ + TL0 = count & 0xff; /* Update new values of the counter */ break; } } if (GET_TR1) { - switch(mode) + switch (mode) { case 3: /* Split Timer 2 */ - count = ((uint32_t) TH0) + cycles; /* No gate control or counting !*/ - if ( count & 0xffffff00 ) /* Check for overflow */ + count = ((uint32_t)TH0) + cycles; /* No gate control or counting !*/ + if (count & 0xffffff00) /* Check for overflow */ SET_TF1(1); - TH0 = count & 0xff; /* Update new values of the counter */ + TH0 = count & 0xff; /* Update new values of the counter */ break; } } @@ -1115,8 +1320,8 @@ switching it into or out of Mode 3 or it can be assigned as a baud rate generato void mcs51_cpu_device::update_timer_t1(int cycles) { - uint8_t mode = (GET_M1_1<<1) | GET_M1_0; - uint8_t mode_0 = (GET_M0_1<<1) | GET_M0_0; + uint8_t mode = (GET_M1_1 << 1) | GET_M1_0; + uint8_t mode_0 = (GET_M0_1 << 1) | GET_M0_0; uint32_t count; if (mode_0 != 3) @@ -1136,28 +1341,27 @@ void mcs51_cpu_device::update_timer_t1(int cycles) if (GET_GATE1 && !GET_IE1) delta = 0; - switch(mode) { - case 0: /* 13 Bit Timer Mode */ - count = ((TH1<<5) | ( TL1 & 0x1f ) ); + switch (mode) + { + case 0: /* 13 Bit Timer Mode */ + count = ((TH1 << 5) | (TL1 & 0x1f)); count += delta; overflow = count & 0xffffe000; /* Check for overflow */ - TH1 = (count>>5) & 0xff; - TL1 = count & 0x1f ; + TH1 = (count >> 5) & 0xff; + TL1 = count & 0x1f; break; - case 1: /* 16 Bit Timer Mode */ - count = ((TH1<<8) | TL1); + case 1: /* 16 Bit Timer Mode */ + count = ((TH1 << 8) | TL1); count += delta; overflow = count & 0xffff0000; /* Check for overflow */ - TH1 = (count>>8) & 0xff; + TH1 = (count >> 8) & 0xff; TL1 = count & 0xff; break; - case 2: /* 8 Bit Autoreload */ - count = ((uint32_t) TL1) + delta; + case 2: /* 8 Bit Autoreload */ + count = ((uint32_t)TL1) + delta; overflow = count & 0xffffff00; /* Check for overflow */ - if ( overflow ) - { - count += TH1; /* Reload timer */ - } + if (overflow) + count += TH1; /* Reload timer */ /* Update new values of the counter */ TL1 = count & 0xff; break; @@ -1180,30 +1384,29 @@ void mcs51_cpu_device::update_timer_t1(int cycles) delta = cycles; /* taken, reset */ m_t1_cnt = 0; - switch(mode) { - case 0: /* 13 Bit Timer Mode */ - count = ((TH1<<5) | ( TL1 & 0x1f ) ); + switch (mode) + { + case 0: /* 13 Bit Timer Mode */ + count = ((TH1 << 5) | (TL1 & 0x1f)); count += delta; overflow = count & 0xffffe000; /* Check for overflow */ - TH1 = (count>>5) & 0xff; - TL1 = count & 0x1f ; + TH1 = (count >> 5) & 0xff; + TL1 = count & 0x1f; break; - case 1: /* 16 Bit Timer Mode */ - count = ((TH1<<8) | TL1); + case 1: /* 16 Bit Timer Mode */ + count = ((TH1 << 8) | TL1); count += delta; overflow = count & 0xffff0000; /* Check for overflow */ - TH1 = (count>>8) & 0xff; + TH1 = (count >> 8) & 0xff; TL1 = count & 0xff; break; - case 2: /* 8 Bit Autoreload */ - count = ((uint32_t) TL1) + delta; + case 2: /* 8 Bit Autoreload */ + count = ((uint32_t)TL1) + delta; overflow = count & 0xffffff00; /* Check for overflow */ - if ( overflow ) - { - count += TH1; /* Reload timer */ - } + if (overflow) + count += TH1; /* Reload timer */ /* Update new values of the counter */ - TL1 = count & 0xff; + TL1 = count & 0xff; break; case 3: /* do nothing */ @@ -1219,36 +1422,37 @@ void mcs51_cpu_device::update_timer_t1(int cycles) void mcs51_cpu_device::update_timer_t2(int cycles) { /* Update Timer 2 */ - if(GET_TR2) { + if (GET_TR2) + { int mode = ((GET_TCLK | GET_RCLK) << 1) | GET_CP; int delta = GET_CT2 ? m_t2_cnt : (mode & 2) ? cycles * (12/2) : cycles; - uint32_t count = ((TH2<<8) | TL2) + delta; + uint32_t count = ((TH2 << 8) | TL2) + delta; m_t2_cnt = 0; switch (mode) { case 0: /* 16 Bit Auto Reload */ - if ( count & 0xffff0000 ) + if (count & 0xffff0000) { SET_TF2(1); - count += ((RCAP2H<<8) | RCAP2L); + count += ((RCAP2H << 8) | RCAP2L); } - else if (GET_EXEN2 && m_t2ex_cnt>0) + else if (GET_EXEN2 && m_t2ex_cnt > 0) { - count += ((RCAP2H<<8) | RCAP2L); + count += ((RCAP2H << 8) | RCAP2L); m_t2ex_cnt = 0; } - TH2 = (count>>8) & 0xff; - TL2 = count & 0xff; + TH2 = (count >> 8) & 0xff; + TL2 = count & 0xff; break; case 1: /* 16 Bit Capture */ - if ( count & 0xffff0000 ) + if (count & 0xffff0000) SET_TF2(1); - TH2 = (count>>8) & 0xff; - TL2 = count & 0xff; + TH2 = (count >> 8) & 0xff; + TL2 = count & 0xff; - if (GET_EXEN2 && m_t2ex_cnt>0) + if (GET_EXEN2 && m_t2ex_cnt > 0) { RCAP2H = TH2; RCAP2L = TL2; @@ -1257,95 +1461,23 @@ void mcs51_cpu_device::update_timer_t2(int cycles) break; case 2: case 3: /* Baud rate */ - if ( count & 0xffff0000 ) + if (count & 0xffff0000) { - count += ((RCAP2H<<8) | RCAP2L); + count += ((RCAP2H << 8) | RCAP2L); transmit_receive(2); } - TH2 = (count>>8) & 0xff; - TL2 = count & 0xff; - break; - } - } -} - -void mcs51_cpu_device::update_timers(int cycles) -{ - while (cycles--) - { - update_timer_t0(1); - update_timer_t1(1); - - if (m_features & FEATURE_I8052) - { - update_timer_t2(1); - } - } -} - -//Set up to transmit data out of serial port -//NOTE: Enable Serial Port Interrupt bit is NOT required to send/receive data! - -void mcs51_cpu_device::serial_transmit(uint8_t data) -{ - int mode = (GET_SM0<<1) | GET_SM1; - - //Flag that we're sending data - m_uart.data_out = data; - LOG(("serial_transmit: %x %x\n", mode, data)); - switch(mode) { - //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12 - case 0: - m_uart.bits_to_send = 8+2; - break; - //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2 - case 1: - m_uart.bits_to_send = 8+2; - break; - //9 bit uart - case 2: - case 3: - m_uart.bits_to_send = 8+3; - break; - } -} - -void mcs51_cpu_device::serial_receive() -{ - int mode = (GET_SM0<<1) | GET_SM1; - - if (GET_REN) { - switch(mode) { - //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12 - case 0: - m_uart.delay_cycles = 8+2; - break; - //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2 - case 1: - m_uart.delay_cycles = 8+2; - break; - //9 bit uart - case 2: - case 3: - m_uart.delay_cycles = 8+3; + TH2 = (count >> 8) & 0xff; + TL2 = count & 0xff; break; } } } /* Check and update status of serial port */ -void mcs51_cpu_device::update_serial(int cycles) -{ - while (--cycles>=0) - transmit_receive(0); -} - -/* Check and update status of serial port */ void mcs51_cpu_device::update_irq_prio(uint8_t ipl, uint8_t iph) { - int i; - for (i=0; i<8; i++) - m_irq_prio[i] = ((ipl >> i) & 1) | (((iph >>i ) & 1) << 1); + for (int i = 0; i < 8; i++) + m_irq_prio[i] = ((ipl >> i) & 1) | (((iph >> i) & 1) << 1); } @@ -1368,17 +1500,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) m_last_op = op; - switch( op ) + switch (op) { - case 0x00: nop(op); break; //NOP - case 0x01: ajmp(op); break; //AJMP code addr - case 0x02: ljmp(op); break; //LJMP code addr - case 0x03: rr_a(op); break; //RR A - case 0x04: inc_a(op); break; //INC A - case 0x05: RWM=1; inc_mem(op); RWM=0; break; //INC data addr + case 0x00: nop(op); break; //NOP + case 0x01: ajmp(op); break; //AJMP code addr + case 0x02: ljmp(op); break; //LJMP code addr + case 0x03: rr_a(op); break; //RR A + case 0x04: inc_a(op); break; //INC A + case 0x05: RWM = 1; inc_mem(op); RWM = 0; break; //INC data addr case 0x06: - case 0x07: inc_ir(op&1); break; //INC @R0/@R1 + case 0x07: inc_ir(op & 1); break; //INC @R0/@R1 case 0x08: case 0x09: @@ -1387,17 +1519,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x0c: case 0x0d: case 0x0e: - case 0x0f: inc_r(op&7); break; //INC R0 to R7 + case 0x0f: inc_r(op & 7); break; //INC R0 to R7 - case 0x10: RWM=1; jbc(op); RWM=0; break; //JBC bit addr, code addr - case 0x11: acall(op); break; //ACALL code addr - case 0x12: lcall(op); break; //LCALL code addr - case 0x13: rrc_a(op); break; //RRC A - case 0x14: dec_a(op); break; //DEC A - case 0x15: RWM=1; dec_mem(op); RWM=0; break; //DEC data addr + case 0x10: RWM = 1; jbc(op); RWM = 0; break; //JBC bit addr, code addr + case 0x11: acall(op); break; //ACALL code addr + case 0x12: lcall(op); break; //LCALL code addr + case 0x13: rrc_a(op); break; //RRC A + case 0x14: dec_a(op); break; //DEC A + case 0x15: RWM = 1; dec_mem(op); RWM = 0; break; //DEC data addr case 0x16: - case 0x17: dec_ir(op&1); break; //DEC @R0/@R1 + case 0x17: dec_ir(op & 1); break; //DEC @R0/@R1 case 0x18: case 0x19: @@ -1406,17 +1538,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x1c: case 0x1d: case 0x1e: - case 0x1f: dec_r(op&7); break; //DEC R0 to R7 + case 0x1f: dec_r(op & 7); break; //DEC R0 to R7 - case 0x20: jb(op); break; //JB bit addr, code addr - case 0x21: ajmp(op); break; //AJMP code addr - case 0x22: ret(op); break; //RET - case 0x23: rl_a(op); break; //RL A - case 0x24: add_a_byte(op); break; //ADD A, #data - case 0x25: add_a_mem(op); break; //ADD A, data addr + case 0x20: jb(op); break; //JB bit addr, code addr + case 0x21: ajmp(op); break; //AJMP code addr + case 0x22: ret(op); break; //RET + case 0x23: rl_a(op); break; //RL A + case 0x24: add_a_byte(op); break; //ADD A, #data + case 0x25: add_a_mem(op); break; //ADD A, data addr case 0x26: - case 0x27: add_a_ir(op&1); break; //ADD A, @R0/@R1 + case 0x27: add_a_ir(op & 1); break; //ADD A, @R0/@R1 case 0x28: case 0x29: @@ -1425,17 +1557,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x2c: case 0x2d: case 0x2e: - case 0x2f: add_a_r(op&7); break; //ADD A, R0 to R7 + case 0x2f: add_a_r(op & 7); break; //ADD A, R0 to R7 - case 0x30: jnb(op); break; //JNB bit addr, code addr - case 0x31: acall(op); break; //ACALL code addr - case 0x32: reti(op); break; //RETI - case 0x33: rlc_a(op); break; //RLC A - case 0x34: addc_a_byte(op); break; //ADDC A, #data - case 0x35: addc_a_mem(op); break; //ADDC A, data addr + case 0x30: jnb(op); break; //JNB bit addr, code addr + case 0x31: acall(op); break; //ACALL code addr + case 0x32: reti(op); break; //RETI + case 0x33: rlc_a(op); break; //RLC A + case 0x34: addc_a_byte(op); break; //ADDC A, #data + case 0x35: addc_a_mem(op); break; //ADDC A, data addr case 0x36: - case 0x37: addc_a_ir(op&1); break; //ADDC A, @R0/@R1 + case 0x37: addc_a_ir(op & 1); break; //ADDC A, @R0/@R1 case 0x38: case 0x39: @@ -1444,17 +1576,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x3c: case 0x3d: case 0x3e: - case 0x3f: addc_a_r(op&7); break; //ADDC A, R0 to R7 + case 0x3f: addc_a_r(op & 7); break; //ADDC A, R0 to R7 - case 0x40: jc(op); break; //JC code addr - case 0x41: ajmp(op); break; //AJMP code addr - case 0x42: RWM=1; orl_mem_a(op); RWM=0; break; //ORL data addr, A - case 0x43: RWM=1; orl_mem_byte(op); RWM=0; break; //ORL data addr, #data - case 0x44: orl_a_byte(op); break; - case 0x45: orl_a_mem(op); break; //ORL A, data addr + case 0x40: jc(op); break; //JC code addr + case 0x41: ajmp(op); break; //AJMP code addr + case 0x42: RWM = 1; orl_mem_a(op); RWM = 0; break; //ORL data addr, A + case 0x43: RWM = 1; orl_mem_byte(op); RWM = 0; break; //ORL data addr, #data + case 0x44: orl_a_byte(op); break; + case 0x45: orl_a_mem(op); break; //ORL A, data addr case 0x46: - case 0x47: orl_a_ir(op&1); break; //ORL A, @RO/@R1 + case 0x47: orl_a_ir(op & 1); break; //ORL A, @RO/@R1 case 0x48: case 0x49: @@ -1463,17 +1595,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x4c: case 0x4d: case 0x4e: - case 0x4f: orl_a_r(op&7); break; //ORL A, RO to R7 + case 0x4f: orl_a_r(op & 7); break; //ORL A, RO to R7 - case 0x50: jnc(op); break; //JNC code addr - case 0x51: acall(op); break; //ACALL code addr - case 0x52: RWM=1; anl_mem_a(op); RWM=0; break; //ANL data addr, A - case 0x53: RWM=1; anl_mem_byte(op); RWM=0; break; //ANL data addr, #data - case 0x54: anl_a_byte(op); break; //ANL A, #data - case 0x55: anl_a_mem(op); break; //ANL A, data addr + case 0x50: jnc(op); break; //JNC code addr + case 0x51: acall(op); break; //ACALL code addr + case 0x52: RWM = 1; anl_mem_a(op); RWM = 0; break; //ANL data addr, A + case 0x53: RWM = 1; anl_mem_byte(op); RWM = 0; break; //ANL data addr, #data + case 0x54: anl_a_byte(op); break; //ANL A, #data + case 0x55: anl_a_mem(op); break; //ANL A, data addr case 0x56: - case 0x57: anl_a_ir(op&1); break; //ANL A, @RO/@R1 + case 0x57: anl_a_ir(op & 1); break; //ANL A, @RO/@R1 case 0x58: case 0x59: @@ -1482,17 +1614,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x5c: case 0x5d: case 0x5e: - case 0x5f: anl_a_r(op&7); break; //ANL A, RO to R7 + case 0x5f: anl_a_r(op & 7); break; //ANL A, RO to R7 - case 0x60: jz(op); break; //JZ code addr - case 0x61: ajmp(op); break; //AJMP code addr - case 0x62: RWM=1; xrl_mem_a(op); RWM=0; break; //XRL data addr, A - case 0x63: RWM=1; xrl_mem_byte(op); RWM=0; break; //XRL data addr, #data - case 0x64: xrl_a_byte(op); break; //XRL A, #data - case 0x65: xrl_a_mem(op); break; //XRL A, data addr + case 0x60: jz(op); break; //JZ code addr + case 0x61: ajmp(op); break; //AJMP code addr + case 0x62: RWM = 1; xrl_mem_a(op); RWM = 0; break; //XRL data addr, A + case 0x63: RWM = 1; xrl_mem_byte(op); RWM = 0; break; //XRL data addr, #data + case 0x64: xrl_a_byte(op); break; //XRL A, #data + case 0x65: xrl_a_mem(op); break; //XRL A, data addr case 0x66: - case 0x67: xrl_a_ir(op&1); break; //XRL A, @R0/@R1 + case 0x67: xrl_a_ir(op & 1); break; //XRL A, @R0/@R1 case 0x68: case 0x69: @@ -1501,17 +1633,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x6c: case 0x6d: case 0x6e: - case 0x6f: xrl_a_r(op&7); break; //XRL A, R0 to R7 + case 0x6f: xrl_a_r(op & 7); break; //XRL A, R0 to R7 - case 0x70: jnz(op); break; //JNZ code addr - case 0x71: acall(op); break; //ACALL code addr - case 0x72: orl_c_bitaddr(op); break; //ORL C, bit addr - case 0x73: jmp_iadptr(op); break; //JMP @A+DPTR - case 0x74: mov_a_byte(op); break; //MOV A, #data - case 0x75: mov_mem_byte(op); break; //MOV data addr, #data + case 0x70: jnz(op); break; //JNZ code addr + case 0x71: acall(op); break; //ACALL code addr + case 0x72: orl_c_bitaddr(op); break; //ORL C, bit addr + case 0x73: jmp_iadptr(op); break; //JMP @A+DPTR + case 0x74: mov_a_byte(op); break; //MOV A, #data + case 0x75: mov_mem_byte(op); break; //MOV data addr, #data case 0x76: - case 0x77: mov_ir_byte(op&1); break; //MOV @R0/@R1, #data + case 0x77: mov_ir_byte(op & 1); break; //MOV @R0/@R1, #data case 0x78: case 0x79: @@ -1520,17 +1652,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x7c: case 0x7d: case 0x7e: - case 0x7f: mov_r_byte(op&7); break; //MOV R0 to R7, #data + case 0x7f: mov_r_byte(op & 7); break; //MOV R0 to R7, #data - case 0x80: sjmp(op); break; //SJMP code addr - case 0x81: ajmp(op); break; //AJMP code addr - case 0x82: anl_c_bitaddr(op); break; //ANL C, bit addr - case 0x83: movc_a_iapc(op); break; //MOVC A, @A + PC - case 0x84: div_ab(op); break; //DIV AB - case 0x85: mov_mem_mem(op); break; //MOV data addr, data addr + case 0x80: sjmp(op); break; //SJMP code addr + case 0x81: ajmp(op); break; //AJMP code addr + case 0x82: anl_c_bitaddr(op); break; //ANL C, bit addr + case 0x83: movc_a_iapc(op); break; //MOVC A, @A + PC + case 0x84: div_ab(op); break; //DIV AB + case 0x85: mov_mem_mem(op); break; //MOV data addr, data addr case 0x86: - case 0x87: mov_mem_ir(op&1); break; //MOV data addr, @R0/@R1 + case 0x87: mov_mem_ir(op & 1); break; //MOV data addr, @R0/@R1 case 0x88: case 0x89: @@ -1539,17 +1671,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x8c: case 0x8d: case 0x8e: - case 0x8f: mov_mem_r(op&7); break; //MOV data addr,R0 to R7 + case 0x8f: mov_mem_r(op & 7); break; //MOV data addr,R0 to R7 - case 0x90: mov_dptr_byte(op); break; //MOV DPTR, #data - case 0x91: acall(op); break; //ACALL code addr - case 0x92: RWM = 1; mov_bitaddr_c(op); RWM = 0; break; //MOV bit addr, C - case 0x93: movc_a_iadptr(op); break; //MOVC A, @A + DPTR - case 0x94: subb_a_byte(op); break; //SUBB A, #data - case 0x95: subb_a_mem(op); break; //SUBB A, data addr + case 0x90: mov_dptr_byte(op); break; //MOV DPTR, #data + case 0x91: acall(op); break; //ACALL code addr + case 0x92: RWM = 1; mov_bitaddr_c(op); RWM = 0; break; //MOV bit addr, C + case 0x93: movc_a_iadptr(op); break; //MOVC A, @A + DPTR + case 0x94: subb_a_byte(op); break; //SUBB A, #data + case 0x95: subb_a_mem(op); break; //SUBB A, data addr case 0x96: - case 0x97: subb_a_ir(op&1); break; //SUBB A, @R0/@R1 + case 0x97: subb_a_ir(op & 1); break; //SUBB A, @R0/@R1 case 0x98: case 0x99: @@ -1558,17 +1690,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0x9c: case 0x9d: case 0x9e: - case 0x9f: subb_a_r(op&7); break; //SUBB A, R0 to R7 + case 0x9f: subb_a_r(op & 7); break; //SUBB A, R0 to R7 - case 0xa0: orl_c_nbitaddr(op); break; //ORL C, /bit addr - case 0xa1: ajmp(op); break; //AJMP code addr - case 0xa2: mov_c_bitaddr(op); break; //MOV C, bit addr - case 0xa3: inc_dptr(op); break; //INC DPTR - case 0xa4: mul_ab(op); break; //MUL AB - case 0xa5: illegal(op); break; //reserved + case 0xa0: orl_c_nbitaddr(op); break; //ORL C, /bit addr + case 0xa1: ajmp(op); break; //AJMP code addr + case 0xa2: mov_c_bitaddr(op); break; //MOV C, bit addr + case 0xa3: inc_dptr(op); break; //INC DPTR + case 0xa4: mul_ab(op); break; //MUL AB + case 0xa5: illegal(op); break; //reserved case 0xa6: - case 0xa7: mov_ir_mem(op&1); break; //MOV @R0/@R1, data addr + case 0xa7: mov_ir_mem(op & 1); break; //MOV @R0/@R1, data addr case 0xa8: case 0xa9: @@ -1577,17 +1709,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xac: case 0xad: case 0xae: - case 0xaf: mov_r_mem(op&7); break; //MOV R0 to R7, data addr + case 0xaf: mov_r_mem(op & 7); break; //MOV R0 to R7, data addr - case 0xb0: anl_c_nbitaddr(op); break; //ANL C,/bit addr - case 0xb1: acall(op); break; //ACALL code addr - case 0xb2: RWM=1; cpl_bitaddr(op); RWM=0; break; //CPL bit addr - case 0xb3: cpl_c(op); break; //CPL C - case 0xb4: cjne_a_byte(op); break; //CJNE A, #data, code addr - case 0xb5: cjne_a_mem(op); break; //CJNE A, data addr, code addr + case 0xb0: anl_c_nbitaddr(op); break; //ANL C,/bit addr + case 0xb1: acall(op); break; //ACALL code addr + case 0xb2: RWM = 1; cpl_bitaddr(op); RWM = 0; break; //CPL bit addr + case 0xb3: cpl_c(op); break; //CPL C + case 0xb4: cjne_a_byte(op); break; //CJNE A, #data, code addr + case 0xb5: cjne_a_mem(op); break; //CJNE A, data addr, code addr case 0xb6: - case 0xb7: cjne_ir_byte(op&1); break; //CJNE @R0/@R1, #data, code addr + case 0xb7: cjne_ir_byte(op & 1); break; //CJNE @R0/@R1, #data, code addr case 0xb8: case 0xb9: @@ -1596,17 +1728,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xbc: case 0xbd: case 0xbe: - case 0xbf: cjne_r_byte(op&7); break; //CJNE R0 to R7, #data, code addr + case 0xbf: cjne_r_byte(op & 7); break; //CJNE R0 to R7, #data, code addr - case 0xc0: push(op); break; //PUSH data addr - case 0xc1: ajmp(op); break; //AJMP code addr - case 0xc2: RWM=1; clr_bitaddr(op); RWM=0; break; //CLR bit addr - case 0xc3: clr_c(op); break; //CLR C - case 0xc4: swap_a(op); break; //SWAP A - case 0xc5: xch_a_mem(op); break; //XCH A, data addr + case 0xc0: push(op); break; //PUSH data addr + case 0xc1: ajmp(op); break; //AJMP code addr + case 0xc2: RWM = 1; clr_bitaddr(op); RWM = 0; break; //CLR bit addr + case 0xc3: clr_c(op); break; //CLR C + case 0xc4: swap_a(op); break; //SWAP A + case 0xc5: xch_a_mem(op); break; //XCH A, data addr case 0xc6: - case 0xc7: xch_a_ir(op&1); break; //XCH A, @RO/@R1 + case 0xc7: xch_a_ir(op & 1); break; //XCH A, @RO/@R1 case 0xc8: case 0xc9: @@ -1615,17 +1747,17 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xcc: case 0xcd: case 0xce: - case 0xcf: xch_a_r(op&7); break; //XCH A, RO to R7 + case 0xcf: xch_a_r(op & 7); break; //XCH A, RO to R7 - case 0xd0: pop(op); break; //POP data addr - case 0xd1: acall(op); break; //ACALL code addr - case 0xd2: RWM=1; setb_bitaddr(op); RWM=0; break; //SETB bit addr - case 0xd3: setb_c(op); break; //SETB C - case 0xd4: da_a(op); break; //DA A - case 0xd5: RWM=1; djnz_mem(op); RWM=0; break; //DJNZ data addr, code addr + case 0xd0: pop(op); break; //POP data addr + case 0xd1: acall(op); break; //ACALL code addr + case 0xd2: RWM = 1; setb_bitaddr(op); RWM = 0; break; //SETB bit addr + case 0xd3: setb_c(op); break; //SETB C + case 0xd4: da_a(op); break; //DA A + case 0xd5: RWM = 1; djnz_mem(op); RWM = 0; break; //DJNZ data addr, code addr case 0xd6: - case 0xd7: xchd_a_ir(op&1); break; //XCHD A, @R0/@R1 + case 0xd7: xchd_a_ir(op & 1); break; //XCHD A, @R0/@R1 case 0xd8: case 0xd9: @@ -1634,18 +1766,18 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xdc: case 0xdd: case 0xde: - case 0xdf: djnz_r(op&7); break; //DJNZ R0 to R7,code addr + case 0xdf: djnz_r(op & 7); break; //DJNZ R0 to R7,code addr - case 0xe0: movx_a_idptr(op); break; //MOVX A,@DPTR - case 0xe1: ajmp(op); break; //AJMP code addr + case 0xe0: movx_a_idptr(op); break; //MOVX A,@DPTR + case 0xe1: ajmp(op); break; //AJMP code addr case 0xe2: - case 0xe3: movx_a_ir(op&1); break; //MOVX A, @R0/@R1 + case 0xe3: movx_a_ir(op & 1); break; //MOVX A, @R0/@R1 - case 0xe4: clr_a(op); break; //CLR A - case 0xe5: mov_a_mem(op); break; //MOV A, data addr + case 0xe4: clr_a(op); break; //CLR A + case 0xe5: mov_a_mem(op); break; //MOV A, data addr case 0xe6: - case 0xe7: mov_a_ir(op&1); break; //MOV A,@RO/@R1 + case 0xe7: mov_a_ir(op & 1); break; //MOV A,@RO/@R1 case 0xe8: case 0xe9: @@ -1654,19 +1786,19 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xec: case 0xed: case 0xee: - case 0xef: mov_a_r(op&7); break; //MOV A,R0 to R7 + case 0xef: mov_a_r(op & 7); break; //MOV A,R0 to R7 - case 0xf0: movx_idptr_a(op); break; //MOVX @DPTR,A - case 0xf1: acall(op); break; //ACALL code addr + case 0xf0: movx_idptr_a(op); break; //MOVX @DPTR,A + case 0xf1: acall(op); break; //ACALL code addr case 0xf2: - case 0xf3: movx_ir_a(op&1); break; //MOVX @R0/@R1,A + case 0xf3: movx_ir_a(op & 1); break; //MOVX @R0/@R1,A - case 0xf4: cpl_a(op); break; //CPL A - case 0xf5: mov_mem_a(op); break; //MOV data addr, A + case 0xf4: cpl_a(op); break; //CPL A + case 0xf5: mov_mem_a(op); break; //MOV data addr, A case 0xf6: - case 0xf7: mov_ir_a(op&1); break; //MOV @R0/@R1, A + case 0xf7: mov_ir_a(op & 1); break; //MOV @R0/@R1, A case 0xf8: case 0xf9: @@ -1675,7 +1807,7 @@ void mcs51_cpu_device::execute_op(uint8_t op) case 0xfc: case 0xfd: case 0xfe: - case 0xff: mov_r_a(op&7); break; //MOV R0 to R7, A + case 0xff: mov_r_a(op & 7); break; //MOV R0 to R7, A default: illegal(op); } @@ -1686,7 +1818,8 @@ void mcs51_cpu_device::execute_op(uint8_t op) ***************************************************************************/ /* # of oscilations each opcode requires*/ -const uint8_t mcs51_cpu_device::mcs51_cycles[256] = { +const uint8_t mcs51_cpu_device::mcs51_cycles[256] = +{ 1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -1724,25 +1857,23 @@ const uint8_t mcs51_cpu_device::mcs51_cycles[256] = { **********************************************************************************/ void mcs51_cpu_device::check_irqs() { - uint8_t ints = (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3) - | ((GET_RI|GET_TI)<<4)); + uint8_t ints = (GET_IE0 | (GET_TF0 << 1) | (GET_IE1 << 2) | (GET_TF1 << 3) | ((GET_RI | GET_TI) << 4)); uint8_t int_vec = 0; uint8_t int_mask; int priority_request = -1; - int i; - //If All Inerrupts Disabled or no pending abort.. + //If All Interrupts Disabled or no pending abort.. int_mask = (GET_EA ? IE : 0x00); if (m_features & FEATURE_I8052) - ints |= ((GET_TF2|GET_EXF2)<<5); + ints |= ((GET_TF2 | GET_EXF2) << 5); if (m_features & FEATURE_DS5002FP) { - ints |= ((GET_PFW)<<5); - m_irq_prio[6] = 3; /* force highest priority */ + ints |= ((GET_PFW) << 5); + m_irq_prio[6] = 3; /* force highest priority */ /* mask out interrupts not enabled */ - ints &= ((int_mask & 0x1f) | ((GET_EPFW)<<5)); + ints &= ((int_mask & 0x1f) | ((GET_EPFW) << 5)); } else { @@ -1750,28 +1881,34 @@ void mcs51_cpu_device::check_irqs() ints &= int_mask; } - if (!ints) return; + if (!ints) + return; - /* CLear IDL - got enabled interrupt */ + /* Clear IDL - got enabled interrupt */ if (m_features & FEATURE_CMOS) { /* any interrupt terminates idle mode */ SET_IDL(0); /* external interrupt wakes up */ if (ints & (GET_IE0 | GET_IE1)) + { /* but not the DS5002FP */ if (!(m_features & FEATURE_DS5002FP)) SET_PD(0); + } } - for (i=0; i<m_num_interrupts; i++) + if ((m_features & FEATURE_CMOS) && GET_PD) + return; + + for (int i = 0; i < m_num_interrupts; i++) { - if (ints & (1<<i)) + if (ints & (1 << i)) { if (m_irq_prio[i] > priority_request) { priority_request = m_irq_prio[i]; - int_vec = (i<<3) | 3; + int_vec = (i << 3) | 3; } } } @@ -1779,17 +1916,28 @@ void mcs51_cpu_device::check_irqs() /* Skip the interrupt request if currently processing interrupt * and the new request does not have a higher priority */ - - LOG(("Request: %d\n", priority_request)); + LOG("Request: %d\n", priority_request); if (m_irq_active && (priority_request <= m_cur_irq_prio)) { - LOG(("higher or equal priority irq (%u) in progress already, skipping ...\n", m_cur_irq_prio)); + LOG("higher or equal priority irq (%u) in progress already, skipping ...\n", m_cur_irq_prio); return; } - // Hack to work around polling latency issue with JB INT0/INT1 - if (m_last_op == 0x20 && ((int_vec == V_IE0 && m_last_bit == 0xb2) || (int_vec == V_IE1 && m_last_bit == 0xb3))) - PC = PPC + 3; + // indicate we took the external IRQ + if (int_vec == V_IE0) + { + // Hack to work around polling latency issue with JB INT0 + if (m_last_op == 0x20 && m_last_bit == 0xb2) + PC = PPC + 3; + standard_irq_callback(0, PC); + } + else if (int_vec == V_IE1) + { + // Hack to work around polling latency issue with JB INT1 + if (m_last_op == 0x20 && m_last_bit == 0xb3) + PC = PPC + 3; + standard_irq_callback(1, PC); + } //Save current pc to stack, set pc to new interrupt vector push_pc(); @@ -1802,18 +1950,15 @@ void mcs51_cpu_device::check_irqs() m_cur_irq_prio = priority_request; m_irq_active |= (1 << priority_request); - LOG(("Take: %d %02x\n", m_cur_irq_prio, m_irq_active)); + LOG("Take: %d %02x\n", m_cur_irq_prio, m_irq_active); //Clear any interrupt flags that should be cleared since we're servicing the irq! - switch(int_vec) { + switch (int_vec) + { case V_IE0: //External Int Flag only cleared when configured as Edge Triggered.. - if(GET_IT0) /* for some reason having this, breaks alving dmd games */ + if (GET_IT0) /* for some reason having this, breaks alving dmd games */ SET_IE0(0); - - /* indicate we took the external IRQ */ - standard_irq_callback(0); - break; case V_TF0: //Timer 0 - Always clear Flag @@ -1821,11 +1966,8 @@ void mcs51_cpu_device::check_irqs() break; case V_IE1: //External Int Flag only cleared when configured as Edge Triggered.. - if(GET_IT1) /* for some reason having this, breaks alving dmd games */ + if (GET_IT1) /* for some reason having this, breaks alving dmd games */ SET_IE1(0); - /* indicate we took the external IRQ */ - standard_irq_callback(1); - break; case V_TF1: //Timer 1 - Always clear Flag @@ -1843,20 +1985,25 @@ void mcs51_cpu_device::check_irqs() * no flags are cleared, PFW is reset by software * This has the same vector as V_TF2. */ - } } void mcs51_cpu_device::burn_cycles(int cycles) { - /* Update Timer (if any timers are running) */ - update_timers(cycles); + while (cycles--) + { + m_icount--; - /* Update Serial (only for mode 0) */ - update_serial(cycles); + // update timers + update_timer_t0(1); + update_timer_t1(1); - /* check_irqs */ - check_irqs(); + if (m_features & FEATURE_I8052) + update_timer_t2(1); + + // check and update status of serial port + transmit_receive(0); + } } void mcs51_cpu_device::execute_set_input(int irqline, int state) @@ -1875,20 +2022,22 @@ void mcs51_cpu_device::execute_set_input(int irqline, int state) /* detect 0->1 transitions */ uint32_t tr_state = (~m_last_line_state) & new_state; - switch( irqline ) + switch (irqline) { //External Interrupt 0 case MCS51_INT0_LINE: //Line Asserted? - if (state != CLEAR_LINE) { + if (state != CLEAR_LINE) + { //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT0 active lo! - if (GET_IT0) { + if (GET_IT0) + { if (GET_BIT(tr_state, MCS51_INT0_LINE)) SET_IE0(1); } else { - SET_IE0(1); //Nope, just set it.. + SET_IE0(1); //Nope, just set it.. } } else @@ -1902,14 +2051,16 @@ void mcs51_cpu_device::execute_set_input(int irqline, int state) //External Interrupt 1 case MCS51_INT1_LINE: //Line Asserted? - if (state != CLEAR_LINE) { + if (state != CLEAR_LINE) + { //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo! - if(GET_IT1){ + if (GET_IT1) + { if (GET_BIT(tr_state, MCS51_INT1_LINE)) SET_IE1(1); } else - SET_IE1(1); //Nope, just set it.. + SET_IE1(1); //Nope, just set it.. } else { @@ -1951,14 +2102,6 @@ void mcs51_cpu_device::execute_set_input(int irqline, int state) fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n"); break; - case MCS51_RX_LINE: /* Serial Port Receive */ - /* Is the enable flags for this interrupt set? */ - if (state != CLEAR_LINE) - { - serial_receive(); - } - break; - /* Power Fail Interrupt */ case DS5002FP_PFI_LINE: if (m_features & FEATURE_DS5002FP) @@ -1974,65 +2117,50 @@ void mcs51_cpu_device::execute_set_input(int irqline, int state) m_last_line_state = new_state; } -/* Execute cycles - returns number of cycles actually run */ +/* Execute cycles */ void mcs51_cpu_device::execute_run() { - uint8_t op; - - /* external interrupts may have been set since we last checked */ - m_inst_cycles = 0; - check_irqs(); - - /* if in powerdown, just return */ - if ((m_features & FEATURE_CMOS) && GET_PD) - { - m_icount = 0; - return; - } - - m_icount -= m_inst_cycles; - burn_cycles(m_inst_cycles); - - if ((m_features & FEATURE_CMOS) && GET_IDL) - { - do - { - /* burn the cycles */ - m_icount--; - burn_cycles(1); - } while( m_icount > 0 ); - return; - } - do { - /* Read next opcode */ - PPC = PC; - debugger_instruction_hook(PC); - op = m_cache->read_byte(PC++); - - /* process opcode and count cycles */ - m_inst_cycles = mcs51_cycles[op]; - execute_op(op); + // check interrupts + check_irqs(); - /* burn the cycles */ - m_icount -= m_inst_cycles; - - /* if in powerdown, just return */ + // if in powerdown and external IRQ did not wake us up, just return if ((m_features & FEATURE_CMOS) && GET_PD) + { + debugger_wait_hook(); + m_icount = 0; return; + } + + // if not idling, process next opcode + if (!((m_features & FEATURE_CMOS) && GET_IDL)) + { + PPC = PC; + debugger_instruction_hook(PC); + uint8_t op = m_program.read_byte(PC++); + m_inst_cycles += mcs51_cycles[op]; + execute_op(op); + } + else + m_inst_cycles++; + + // burn the cycles burn_cycles(m_inst_cycles); - /* decrement the timed access window */ + // decrement the timed access window if (m_features & FEATURE_DS5002FP) + { m_ds5002fp.ta_window = (m_ds5002fp.ta_window ? (m_ds5002fp.ta_window - 1) : 0x00); - /* If the chip entered in idle mode, end the loop */ - if ((m_features & FEATURE_CMOS) && GET_IDL) - return; + if (m_ds5002fp.rnr_delay > 0) + m_ds5002fp.rnr_delay -= m_inst_cycles; + } + + m_inst_cycles = 0; - } while( m_icount > 0 ); + } while (m_icount > 0); } @@ -2050,13 +2178,21 @@ void mcs51_cpu_device::sfr_write(size_t offset, uint8_t data) case ADDR_P0: m_port_out_cb[0](data); break; case ADDR_P1: m_port_out_cb[1](data); break; case ADDR_P2: m_port_out_cb[2](data); break; - case ADDR_P3: m_port_out_cb[3](data); break; - case ADDR_SBUF: serial_transmit(data); break; + case ADDR_P3: + // P3.1 = SFR(P3) & TxD + if (!m_uart.txd) + m_port_out_cb[3](data & ~0x02); + else + m_port_out_cb[3](data); + break; + case ADDR_SBUF: + LOGMASKED(LOG_TX, "tx byte 0x%02x\n", data); + m_uart.data_out = data; + m_uart.txbit = SIO_START; + break; case ADDR_PSW: SET_PARITY(); break; case ADDR_ACC: SET_PARITY(); break; - case ADDR_IP: update_irq_prio(data, 0); break; - /* R_SBUF = data; //This register is used only for "Receiving data coming in!" */ - + case ADDR_IP: update_irq_prio(data, 0); break; case ADDR_B: case ADDR_SP: case ADDR_DPL: @@ -2069,14 +2205,22 @@ void mcs51_cpu_device::sfr_write(size_t offset, uint8_t data) case ADDR_TL1: case ADDR_TH0: case ADDR_TH1: + break; case ADDR_SCON: + if (!GET_REN && BIT(data, 4)) + { + LOGMASKED(LOG_RX, "rx enabled SCON 0x%02x\n", data); + if (!BIT(data, 6, 2)) + logerror("mode 0 serial input is not emulated\n"); + m_uart.rxbit = SIO_IDLE; + } break; default: - LOG(("mcs51 '%s': attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", tag(), (uint32_t)offset,PC,data)); + LOG("attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", (uint32_t)offset,PC,data); /* no write in this case according to manual */ return; } - m_data->write_byte((size_t)offset | 0x100, data); + m_data.write_byte((size_t)offset | 0x100, data); } uint8_t mcs51_cpu_device::sfr_read(size_t offset) @@ -2111,10 +2255,10 @@ uint8_t mcs51_cpu_device::sfr_read(size_t offset) case ADDR_SBUF: case ADDR_IE: case ADDR_IP: - return m_data->read_byte((size_t) offset | 0x100); + return m_data.read_byte((size_t) offset | 0x100); /* Illegal or non-implemented sfr */ default: - LOG(("mcs51 '%s': attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", tag(), (uint32_t)offset,PC)); + LOG("attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", (uint32_t)offset,PC); /* according to the manual, the read may return random bits */ return 0xff; } @@ -2123,44 +2267,40 @@ uint8_t mcs51_cpu_device::sfr_read(size_t offset) void mcs51_cpu_device::device_start() { - m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<0, 0, ENDIANNESS_LITTLE>(); - m_data = &space(AS_DATA); - m_io = &space(AS_IO); - - for (auto &cb : m_port_in_cb) - cb.resolve_safe(0xff); - for (auto &cb : m_port_out_cb) - cb.resolve_safe(); - - m_serial_rx_cb.resolve_safe(0); - m_serial_tx_cb.resolve_safe(); + space(AS_PROGRAM).cache(m_program); + space(AS_DATA).specific(m_data); + space(AS_IO).specific(m_io); /* Save states */ - save_item(NAME(m_ppc)); save_item(NAME(m_pc)); + save_item(NAME(m_rwm)); + save_item(NAME(m_recalc_parity)); + save_item(NAME(m_last_line_state)); + save_item(NAME(m_t0_cnt)); + save_item(NAME(m_t1_cnt)); + save_item(NAME(m_t2_cnt)); + save_item(NAME(m_t2ex_cnt)); + save_item(NAME(m_cur_irq_prio)); + save_item(NAME(m_irq_active)); + save_item(NAME(m_irq_prio)); save_item(NAME(m_last_op)); save_item(NAME(m_last_bit)); - save_item(NAME(m_rwm) ); - save_item(NAME(m_cur_irq_prio) ); - save_item(NAME(m_last_line_state) ); - save_item(NAME(m_t0_cnt) ); - save_item(NAME(m_t1_cnt) ); - save_item(NAME(m_t2_cnt) ); - save_item(NAME(m_t2ex_cnt) ); - save_item(NAME(m_recalc_parity) ); - save_item(NAME(m_irq_prio) ); - save_item(NAME(m_irq_active) ); - save_item(NAME(m_ds5002fp.previous_ta) ); - save_item(NAME(m_ds5002fp.ta_window) ); - save_item(NAME(m_ds5002fp.range) ); + save_item(NAME(m_uart.data_out)); - save_item(NAME(m_uart.bits_to_send)); + save_item(NAME(m_uart.data_in)); + save_item(NAME(m_uart.txbit)); + save_item(NAME(m_uart.txd)); + save_item(NAME(m_uart.rxbit)); + save_item(NAME(m_uart.rxb8)); save_item(NAME(m_uart.smod_div)); save_item(NAME(m_uart.rx_clk)); save_item(NAME(m_uart.tx_clk)); - save_item(NAME(m_uart.delay_cycles)); + + save_item(NAME(m_ds5002fp.previous_ta)); + save_item(NAME(m_ds5002fp.ta_window)); + save_item(NAME(m_ds5002fp.range)); + save_item(NAME(m_ds5002fp.rnr_delay)); state_add( MCS51_PC, "PC", m_pc).formatstr("%04X"); state_add( MCS51_SP, "SP", SP).formatstr("%02X"); @@ -2193,8 +2333,8 @@ void mcs51_cpu_device::device_start() state_add( MCS51_TL1, "TL1", TL1).formatstr("%02X"); state_add( MCS51_TH1, "TH1", TH1).formatstr("%02X"); - state_add( STATE_GENPC, "GENPC", m_pc ).noshow(); - state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow(); + state_add( STATE_GENPC, "GENPC", m_pc).noshow(); + state_add( STATE_GENPCBASE, "CURPC", m_pc).noshow(); state_add( STATE_GENFLAGS, "GENFLAGS", m_rtemp).formatstr("%8s").noshow(); set_icountptr(m_icount); @@ -2226,6 +2366,7 @@ void mcs51_cpu_device::device_reset() m_t1_cnt = 0; m_t2_cnt = 0; m_t2ex_cnt = 0; + /* Flag as NO IRQ in Progress */ m_irq_active = 0; m_cur_irq_prio = -1; @@ -2233,6 +2374,8 @@ void mcs51_cpu_device::device_reset() m_last_bit = 0; /* these are all defined reset states */ + RWM = 0; + PPC = PC; PC = 0; SP = 0x7; SET_PSW(0); @@ -2251,6 +2394,7 @@ void mcs51_cpu_device::device_reset() TH0 = 0; TL1 = 0; TL0 = 0; + /* set the port configurations to all 1's */ SET_P3(0xff); SET_P2(0xff); @@ -2281,11 +2425,11 @@ void mcs51_cpu_device::device_reset() { // set initial values (some of them are set using the bootstrap loader) PCON = 0; - MCON = m_sfr_ram[ADDR_MCON-0x80]; - RPCTL = m_sfr_ram[ADDR_RPCTL-0x80]; + MCON = m_sfr_ram[ADDR_MCON - 0x80]; + RPCTL = m_sfr_ram[ADDR_RPCTL - 0x80]; RPS = 0; RNR = 0; - CRCR = m_sfr_ram[ADDR_CRCR-0x80]; + CRCR = m_sfr_ram[ADDR_CRCR - 0x80]; CRCL = 0; CRCH = 0; TA = 0; @@ -2294,13 +2438,17 @@ void mcs51_cpu_device::device_reset() m_ds5002fp.previous_ta = 0; m_ds5002fp.ta_window = 0; m_ds5002fp.range = (GET_RG1 << 1) | GET_RG0; + m_ds5002fp.rnr_delay = 160; } m_uart.data_out = 0; + m_uart.data_in = 0; m_uart.rx_clk = 0; m_uart.tx_clk = 0; - m_uart.bits_to_send = 0; - m_uart.delay_cycles = 0; + m_uart.txbit = SIO_IDLE; + m_uart.txd = 1; + m_uart.rxbit = SIO_IDLE; + m_uart.rxb8 = 0; m_uart.smod_div = 0; m_recalc_parity = 0; @@ -2321,7 +2469,7 @@ void i8052_device::sfr_write(size_t offset, uint8_t data) case ADDR_RCAP2H: case ADDR_TL2: case ADDR_TH2: - m_data->write_byte((size_t) offset | 0x100, data); + m_data.write_byte((size_t) offset | 0x100, data); break; default: @@ -2339,7 +2487,7 @@ uint8_t i8052_device::sfr_read(size_t offset) case ADDR_RCAP2H: case ADDR_TL2: case ADDR_TH2: - return m_data->read_byte((size_t) offset | 0x100); + return m_data.read_byte((size_t) offset | 0x100); default: return mcs51_cpu_device::sfr_read(offset); } @@ -2369,7 +2517,7 @@ void i80c52_device::sfr_write(size_t offset, uint8_t data) i8052_device::sfr_write(offset, data); return; } - m_data->write_byte((size_t) offset | 0x100, data); + m_data.write_byte((size_t) offset | 0x100, data); } uint8_t i80c52_device::sfr_read(size_t offset) @@ -2380,7 +2528,7 @@ uint8_t i80c52_device::sfr_read(size_t offset) case ADDR_IPH: case ADDR_SADDR: case ADDR_SADEN: - return m_data->read_byte((size_t) offset | 0x100); + return m_data.read_byte((size_t) offset | 0x100); default: return i8052_device::sfr_read(offset); } @@ -2391,9 +2539,8 @@ uint8_t i80c52_device::sfr_read(size_t offset) * DS5002FP Section ****************************************************************************/ - -#define DS5_LOGW(a, d) LOG(("ds5002fp '%s': write to " # a " register at 0x%04x, data=%x\n", tag(), PC, d)) -#define DS5_LOGR(a, d) LOG(("ds5002fp '%s': read from " # a " register at 0x%04x\n", tag(), PC)) +#define DS5_LOGW(a, d) LOG("write to " # a " register at 0x%04x, data=%x\n", PC, d) +#define DS5_LOGR(a, d) LOG("read from " # a " register at 0x%04x\n", PC) uint8_t mcs51_cpu_device::ds5002fp_protected(size_t offset, uint8_t data, uint8_t ta_mask, uint8_t mask) { @@ -2418,23 +2565,43 @@ void ds5002fp_device::sfr_write(size_t offset, uint8_t data) if ((data == 0xaa) && (m_ds5002fp.ta_window == 0)) { m_ds5002fp.ta_window = 6; /* 4*12 + 2*12 */ - LOG(("ds5002fp '%s': TA window initiated at 0x%04x\n", tag(), PC)); + LOG("TA window initiated at 0x%04x\n", PC); } break; - case ADDR_MCON: data = ds5002fp_protected(ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); break; + case ADDR_MCON: data = ds5002fp_protected(ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); break; case ADDR_RPCTL: data = ds5002fp_protected(ADDR_RPCTL, data, 0xef, 0xfe); DS5_LOGW(RPCTL, data); break; - case ADDR_CRCR: data = ds5002fp_protected(ADDR_CRCR, data, 0xff, 0x0f); DS5_LOGW(CRCR, data); break; - case ADDR_PCON: data = ds5002fp_protected(ADDR_PCON, data, 0xb9, 0xff); break; - case ADDR_IP: data = ds5002fp_protected(ADDR_IP, data, 0x7f, 0xff); break; - case ADDR_CRCL: DS5_LOGW(CRCL, data); break; - case ADDR_CRCH: DS5_LOGW(CRCH, data); break; - case ADDR_RNR: DS5_LOGW(RNR, data); break; - case ADDR_RPS: DS5_LOGW(RPS, data); break; + case ADDR_CRCR: data = ds5002fp_protected(ADDR_CRCR, data, 0xff, 0x0f); DS5_LOGW(CRCR, data); break; + case ADDR_PCON: data = ds5002fp_protected(ADDR_PCON, data, 0xb9, 0xff); break; + case ADDR_IP: data = ds5002fp_protected(ADDR_IP, data, 0x7f, 0xff); break; + case ADDR_CRCL: DS5_LOGW(CRCL, data); break; + case ADDR_CRCH: DS5_LOGW(CRCH, data); break; + case ADDR_RNR: DS5_LOGW(RNR, data); break; + case ADDR_RPS: DS5_LOGW(RPS, data); break; default: mcs51_cpu_device::sfr_write(offset, data); return; } - m_data->write_byte((size_t) offset | 0x100, data); + m_data.write_byte((size_t) offset | 0x100, data); +} + + +uint8_t ds5002fp_device::handle_rnr() +{ + if (m_ds5002fp.rnr_delay <= 0) + { + m_ds5002fp.rnr_delay = 160; // delay before another random number can be read + return machine().rand(); + } + else + return 0x00; +} + +bool ds5002fp_device::is_rnr_ready() +{ + if (m_ds5002fp.rnr_delay <= 0) + return true; + else + return false; } uint8_t ds5002fp_device::sfr_read(size_t offset) @@ -2446,8 +2613,10 @@ uint8_t ds5002fp_device::sfr_read(size_t offset) case ADDR_CRCH: DS5_LOGR(CRCH, data); break; case ADDR_MCON: DS5_LOGR(MCON, data); break; case ADDR_TA: DS5_LOGR(TA, data); break; - case ADDR_RNR: DS5_LOGR(RNR, data); break; - case ADDR_RPCTL: DS5_LOGR(RPCTL, data); return 0x80; break; /* touchgo stalls unless bit 7 is set, why? documentation is unclear */ + case ADDR_RNR: DS5_LOGR(RNR, data); + return handle_rnr(); + case ADDR_RPCTL: DS5_LOGR(RPCTL, data); /* touchgo stalls unless bit 7 is set, RNR status (Random Number status) */ + return (is_rnr_ready() ? 0x80 : 0x00); /* falling through to sfr_read for the remaining bits stops high score data loading? */ case ADDR_RPS: DS5_LOGR(RPS, data); break; case ADDR_PCON: SET_PFW(0); /* reset PFW flag */ @@ -2455,7 +2624,7 @@ uint8_t ds5002fp_device::sfr_read(size_t offset) default: return mcs51_cpu_device::sfr_read(offset); } - return m_data->read_byte((size_t) offset | 0x100); + return m_data.read_byte((size_t) offset | 0x100); } /* @@ -2465,41 +2634,55 @@ Documentation states that having the battery connected "maintains the internal s void ds5002fp_device::nvram_default() { - memset( m_scratchpad, 0, 0x80 ); - memset( m_sfr_ram, 0, 0x80 ); + memset(m_scratchpad, 0, 0x80); + memset(m_sfr_ram, 0, 0x80); int expected_bytes = 0x80 + 0x80; if (!m_region.found()) { - logerror( "ds5002fp_device region not found\n" ); + logerror("ds5002fp_device region not found\n"); } - else if( m_region->bytes() != expected_bytes ) + else if (m_region->bytes() != expected_bytes) { - logerror( "ds5002fp_device region length 0x%x expected 0x%x\n", m_region->bytes(), expected_bytes ); + logerror("ds5002fp_device region length 0x%x expected 0x%x\n", m_region->bytes(), expected_bytes); } else { uint8_t *region = m_region->base(); - memcpy( m_scratchpad, region, 0x80 ); region += 0x80; - memcpy( m_sfr_ram, region, 0x80 ); region += 0x80; + memcpy(m_scratchpad, region, 0x80); region += 0x80; + memcpy(m_sfr_ram, region, 0x80); region += 0x80; /* does anything else need storing? any registers that aren't in sfr ram? It isn't clear if the various initial MCON registers etc. are just stored in sfr ram or if the DS5002FP stores them elsewhere and the bootstrap copies them */ } } -void ds5002fp_device::nvram_read( emu_file &file ) +bool ds5002fp_device::nvram_read(util::read_stream &file) { - file.read( m_scratchpad, 0x80 ); - file.read( m_sfr_ram, 0x80 ); + std::error_condition err; + size_t actual; + std::tie(err, actual) = read(file, m_scratchpad, 0x80); + if (err || (actual != 0x80)) + return false; + std::tie(err, actual) = read(file, m_sfr_ram, 0x80); + if (err || (actual != 0x80)) + return false; + return true; } -void ds5002fp_device::nvram_write( emu_file &file ) +bool ds5002fp_device::nvram_write(util::write_stream &file) { - file.write( m_scratchpad, 0x80 ); - file.write( m_sfr_ram, 0x80 ); + std::error_condition err; + size_t actual; + std::tie(err, actual) = write(file, m_scratchpad, 0x80); + if (err || (actual != 0x80)) + return false; + std::tie(err, actual) = write(file, m_sfr_ram, 0x80); + if (err || (actual != 0x80)) + return false; + return true; } std::unique_ptr<util::disasm_interface> mcs51_cpu_device::create_disassembler() @@ -2527,12 +2710,52 @@ std::unique_ptr<util::disasm_interface> i80c52_device::create_disassembler() return std::make_unique<i80c52_disassembler>(); } +std::unique_ptr<util::disasm_interface> i87c51fa_device::create_disassembler() +{ + return std::make_unique<i8xc51fx_disassembler>(); +} + std::unique_ptr<util::disasm_interface> i80c51gb_device::create_disassembler() { return std::make_unique<i8xc51gb_disassembler>(); } +std::unique_ptr<util::disasm_interface> ds80c320_device::create_disassembler() +{ + return std::make_unique<ds80c320_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> sab80c535_device::create_disassembler() +{ + return std::make_unique<sab80c515_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> i8344_device::create_disassembler() +{ + return std::make_unique<rupi44_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> i8744_device::create_disassembler() +{ + return std::make_unique<rupi44_disassembler>(); +} + std::unique_ptr<util::disasm_interface> ds5002fp_device::create_disassembler() { return std::make_unique<ds5002fp_disassembler>(); } + +std::unique_ptr<util::disasm_interface> p80c562_device::create_disassembler() +{ + return std::make_unique<p8xc562_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> p80c552_device::create_disassembler() +{ + return std::make_unique<p8xc552_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> p87c552_device::create_disassembler() +{ + return std::make_unique<p8xc552_disassembler>(); +} diff --git a/src/devices/cpu/mcs51/mcs51.h b/src/devices/cpu/mcs51/mcs51.h index a16f302ab16..340f520eed4 100644 --- a/src/devices/cpu/mcs51/mcs51.h +++ b/src/devices/cpu/mcs51/mcs51.h @@ -2,28 +2,9 @@ // copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud /***************************************************************************** * - * mcs51.h - * Portable MCS-51 Family Emulator + * Portable MCS-51 Family Emulator + * Copyright Steve Ellenoff * - * Chips in the family: - * 8051 Product Line (8031,8051,8751) - * 8052 Product Line (8032,8052,8752) - * 8054 Product Line (8054) - * 8058 Product Line (8058) - * - * Copyright Steve Ellenoff, all rights reserved. - * - * This work is based on: - * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and - * #2) 8051 simulator by Travis Marlatte - * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE) - * - * 2008, October, Couriersud - * - Rewrite of timer, interrupt and serial code - * - addition of CMOS features - * - internal memory maps - * - addition of new processor types - * - full emulation of 8xCx2 processors *****************************************************************************/ #ifndef MAME_CPU_MCS51_MCS51_H @@ -42,15 +23,14 @@ enum enum { - MCS51_INT0_LINE = 0, /* P3.2: External Interrupt 0 */ - MCS51_INT1_LINE, /* P3.3: External Interrupt 1 */ - MCS51_RX_LINE, /* P3.0: Serial Port Receive Line */ - MCS51_T0_LINE, /* P3,4: Timer 0 External Input */ - MCS51_T1_LINE, /* P3.5: Timer 1 External Input */ - MCS51_T2_LINE, /* P1.0: Timer 2 External Input */ - MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */ - - DS5002FP_PFI_LINE /* DS5002FP Power fail interrupt */ + MCS51_INT0_LINE = 0, // P3.2: External Interrupt 0 + MCS51_INT1_LINE, // P3.3: External Interrupt 1 + MCS51_T0_LINE, // P3.4: Timer 0 External Input + MCS51_T1_LINE, // P3.5: Timer 1 External Input + MCS51_T2_LINE, // P1.0: Timer 2 External Input + MCS51_T2EX_LINE, // P1.1: Timer 2 Capture Reload Trigger + + DS5002FP_PFI_LINE // DS5002FP Power fail interrupt }; @@ -64,25 +44,24 @@ public: template <unsigned N> auto port_in_cb() { return m_port_in_cb[N].bind(); } template <unsigned N> auto port_out_cb() { return m_port_out_cb[N].bind(); } - auto serial_rx_cb() { return m_serial_rx_cb.bind(); } - auto serial_tx_cb() { return m_serial_tx_cb.bind(); } - void program_internal(address_map &map); - void data_internal(address_map &map); + void program_internal(address_map &map) ATTR_COLD; + void data_internal(address_map &map) ATTR_COLD; + protected: // construction/destruction mcs51_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); + mcs51_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map, address_map_constructor data_map, int program_width, int data_width, uint8_t features = 0); // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; // device_execute_interface overrides - virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks + 12 - 1) / 12; } - virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 12); } - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 20; } - virtual uint32_t execute_input_lines() const override { return 6; } + virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 12 - 1) / 12; } + virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 12); } + virtual uint32_t execute_min_cycles() const noexcept override { return 1; } + virtual uint32_t execute_max_cycles() const noexcept override { return 4+2; } // max opcode cycles + irq virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; @@ -95,80 +74,81 @@ protected: // device_disasm_interface overrides virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; -protected: address_space_config m_program_config; address_space_config m_data_config; address_space_config m_io_config; - //Internal stuff - uint16_t m_ppc; //previous pc - uint16_t m_pc; //current pc - uint16_t m_features; //features of this cpu - uint8_t m_rwm; //Signals that the current instruction is a read/write/modify instruction - - int m_inst_cycles; /* cycles for the current instruction */ - const uint32_t m_rom_size; /* size (in bytes) of internal program ROM/EPROM */ - int m_ram_mask; /* second ram bank for indirect access available ? */ - int m_num_interrupts; /* number of interrupts supported */ - int m_recalc_parity; /* recalculate parity before next instruction */ - uint32_t m_last_line_state; /* last state of input lines line */ - int m_t0_cnt; /* number of 0->1 transitions on T0 line */ - int m_t1_cnt; /* number of 0->1 transitions on T1 line */ - int m_t2_cnt; /* number of 0->1 transitions on T2 line */ - int m_t2ex_cnt; /* number of 0->1 transitions on T2EX line */ - int m_cur_irq_prio; /* Holds value of the current IRQ Priority Level; -1 if no irq */ - uint8_t m_irq_active; /* mask which irq levels are serviced */ - uint8_t m_irq_prio[8]; /* interrupt priority */ - - uint8_t m_forced_inputs[4]; /* allow read even if configured as output */ + // Internal stuff + uint16_t m_ppc; // previous pc + uint16_t m_pc; // current pc + uint16_t m_features; // features of this cpu + uint8_t m_rwm; // Signals that the current instruction is a read/write/modify instruction + + int m_inst_cycles; // cycles for the current instruction + const uint32_t m_rom_size; // size (in bytes) of internal program ROM/EPROM + int m_ram_mask; // second ram bank for indirect access available ? + int m_num_interrupts; // number of interrupts supported + int m_recalc_parity; // recalculate parity before next instruction + uint32_t m_last_line_state; // last state of input lines line + int m_t0_cnt; // number of 0->1 transitions on T0 line + int m_t1_cnt; // number of 0->1 transitions on T1 line + int m_t2_cnt; // number of 0->1 transitions on T2 line + int m_t2ex_cnt; // number of 0->1 transitions on T2EX line + int m_cur_irq_prio; // Holds value of the current IRQ Priority Level; -1 if no irq + uint8_t m_irq_active; // mask which irq levels are serviced + uint8_t m_irq_prio[8]; // interrupt priority + + uint8_t m_forced_inputs[4]; // allow read even if configured as output // JB-related hacks - uint8_t m_last_op; - uint8_t m_last_bit; + uint8_t m_last_op; + uint8_t m_last_bit; - int m_icount; + int m_icount; struct mcs51_uart { - uint8_t data_out; //Data to send out - uint8_t bits_to_send; //How many bits left to send when transmitting out the serial port - - int smod_div; /* signal divided by 2^SMOD */ - int rx_clk; /* rx clock */ - int tx_clk; /* tx clock */ - uint8_t delay_cycles; //Gross Hack; - } m_uart; /* internal uart */ - - /* Internal Ram */ - required_shared_ptr<uint8_t> m_sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */ - required_shared_ptr<uint8_t> m_scratchpad; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */ - - /* SFR Callbacks */ + uint8_t data_out; // data to send out + uint8_t data_in; + uint8_t txbit; + uint8_t txd; + uint8_t rxbit; + uint8_t rxb8; + + int smod_div; // signal divided by 2^SMOD + int rx_clk; // rx clock + int tx_clk; // tx clock + } m_uart; // internal uart + + // Internal Ram + required_shared_ptr<uint8_t> m_sfr_ram; // 128 SFR - these are in 0x80 - 0xFF + required_shared_ptr<uint8_t> m_scratchpad; // 128 RAM (8031/51) + 128 RAM in second bank (8032/52) + + // SFR Callbacks virtual void sfr_write(size_t offset, uint8_t data); virtual uint8_t sfr_read(size_t offset); - /* Memory spaces */ - address_space *m_program; - memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_cache; - address_space *m_data; - address_space *m_io; + void transmit(int state); - devcb_read8 m_port_in_cb[4]; - devcb_write8 m_port_out_cb[4]; + // Memory spaces + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program; + memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific m_data; + memory_access<18, 0, 0, ENDIANNESS_LITTLE>::specific m_io; - /* Serial Port TX/RX Callbacks */ - devcb_write8 m_serial_tx_cb; //Call back function when sending data out of serial port - devcb_read8 m_serial_rx_cb; //Call back function to retrieve data when receiving serial port data + devcb_read8::array<4> m_port_in_cb; + devcb_write8::array<4> m_port_out_cb; - /* DS5002FP */ + // DS5002FP struct { - uint8_t previous_ta; /* Previous Timed Access value */ - uint8_t ta_window; /* Limed Access window */ - uint8_t range; /* Memory Range */ - /* Bootstrap Configuration */ - uint8_t mcon; /* bootstrap loader MCON register */ - uint8_t rpctl; /* bootstrap loader RPCTL register */ - uint8_t crc; /* bootstrap loader CRC register */ + uint8_t previous_ta; // Previous Timed Access value + uint8_t ta_window; // Limed Access window + uint8_t range; // Memory Range + + // Bootstrap Configuration + uint8_t mcon; // bootstrap loader MCON register + uint8_t rpctl; // bootstrap loader RPCTL register + uint8_t crc; // bootstrap loader CRC register + int32_t rnr_delay; // delay before new random number available } m_ds5002fp; // for the debugger @@ -181,7 +161,7 @@ protected: void clear_current_irq(); uint8_t r_acc(); uint8_t r_psw(); - offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask); + virtual offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask); uint8_t iram_read(size_t offset); void iram_write(size_t offset, uint8_t data); void push_pc(); @@ -195,10 +175,6 @@ protected: void update_timer_t0(int cycles); void update_timer_t1(int cycles); void update_timer_t2(int cycles); - void update_timers(int cycles); - void serial_transmit(uint8_t data); - void serial_receive(); - void update_serial(int cycles); void update_irq_prio(uint8_t ipl, uint8_t iph); void execute_op(uint8_t op); void check_irqs(); @@ -316,35 +292,49 @@ protected: void xrl_a_r(uint8_t r); void illegal(uint8_t r); uint8_t ds5002fp_protected(size_t offset, uint8_t data, uint8_t ta_mask, uint8_t mask); - }; -/* variants with no internal rom and 128 byte internal memory */ +// variants with no internal rom and 128 byte internal memory DECLARE_DEVICE_TYPE(I8031, i8031_device) -/* variants with no internal rom and 256 byte internal memory */ + +// variants with no internal rom and 256 byte internal memory DECLARE_DEVICE_TYPE(I8032, i8032_device) -/* variants 4k internal rom and 128 byte internal memory */ + +// variants 4k internal rom and 128 byte internal memory DECLARE_DEVICE_TYPE(I8051, i8051_device) DECLARE_DEVICE_TYPE(I8751, i8751_device) -/* variants 8k internal rom and 128 byte internal memory (no 8052 features) */ + +// variants 8k internal rom and 128 byte internal memory (no 8052 features) DECLARE_DEVICE_TYPE(AM8753, am8753_device) -/* variants 8k internal rom and 256 byte internal memory and more registers */ + +// variants 8k internal rom and 256 byte internal memory and more registers DECLARE_DEVICE_TYPE(I8052, i8052_device) DECLARE_DEVICE_TYPE(I8752, i8752_device) -/* cmos variants */ + +// cmos variants DECLARE_DEVICE_TYPE(I80C31, i80c31_device) DECLARE_DEVICE_TYPE(I80C51, i80c51_device) DECLARE_DEVICE_TYPE(I87C51, i87c51_device) DECLARE_DEVICE_TYPE(I80C32, i80c32_device) DECLARE_DEVICE_TYPE(I80C52, i80c52_device) DECLARE_DEVICE_TYPE(I87C52, i87c52_device) +DECLARE_DEVICE_TYPE(I87C51FA, i87c51fa_device) DECLARE_DEVICE_TYPE(I80C51GB, i80c51gb_device) DECLARE_DEVICE_TYPE(AT89C52, at89c52_device) DECLARE_DEVICE_TYPE(AT89S52, at89s52_device) -/* 4k internal perom and 128 internal ram and 2 analog comparators */ +DECLARE_DEVICE_TYPE(DS80C320, ds80c320_device) +DECLARE_DEVICE_TYPE(SAB80C535, sab80c535_device) +DECLARE_DEVICE_TYPE(P80C552, p80c552_device) +DECLARE_DEVICE_TYPE(P87C552, p87c552_device) +DECLARE_DEVICE_TYPE(P80C562, p80c562_device) + +// 4k internal perom and 128 internal ram and 2 analog comparators DECLARE_DEVICE_TYPE(AT89C4051, at89c4051_device) +DECLARE_DEVICE_TYPE(I8344, i8344_device) +DECLARE_DEVICE_TYPE(I8744, i8744_device) + DECLARE_DEVICE_TYPE(DS5002FP, ds5002fp_device) @@ -388,7 +378,7 @@ protected: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; - /* SFR Callbacks */ + // SFR Callbacks virtual void sfr_write(size_t offset, uint8_t data) override; virtual uint8_t sfr_read(size_t offset) override; }; @@ -449,7 +439,7 @@ protected: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; - /* SFR Callbacks */ + // SFR Callbacks virtual void sfr_write(size_t offset, uint8_t data) override; virtual uint8_t sfr_read(size_t offset) override; }; @@ -468,7 +458,19 @@ public: i87c52_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; -class i80c51gb_device : public i80c52_device +class i87c51fa_device : public i80c52_device +{ +public: + // construction/destruction + i87c51fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + i87c51fa_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); + + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class i80c51gb_device : public i87c51fa_device { public: // construction/destruction @@ -499,6 +501,78 @@ public: at89c4051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class ds80c320_device : public i80c52_device +{ +public: + // construction/destruction + ds80c320_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class sab80c535_device : public i80c51_device +{ +public: + // construction/destruction + sab80c535_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class i8344_device : public mcs51_cpu_device +{ +public: + // construction/destruction + i8344_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class i8744_device : public mcs51_cpu_device +{ +public: + // construction/destruction + i8744_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class p80c562_device : public i80c51_device +{ +public: + // construction/destruction + p80c562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + p80c562_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); + + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class p80c552_device : public p80c562_device +{ +public: + // construction/destruction + p80c552_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class p87c552_device : public p80c562_device +{ +public: + // construction/destruction + p87c552_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + /* * The DS5002FP has 2 16 bits data address buses (the byte-wide bus and the expanded bus). The exact memory position accessed depends on the * partition mode, the memory range and the expanded bus select. The partition mode and the expanded bus select can be changed at any time. @@ -515,7 +589,7 @@ public: * Internal ram 128k and security features */ -/* these allow the default state of RAM to be set from a region */ +// these allow the default state of RAM to be set from a region #define DS5002FP_SET_MON( _mcon) \ ROM_FILL( 0xc6, 1, _mcon) @@ -538,16 +612,19 @@ public: // device_nvram_interface overrides virtual void nvram_default() override; - virtual void nvram_read( emu_file &file ) override; - virtual void nvram_write( emu_file &file ) override; + virtual bool nvram_read( util::read_stream &file ) override; + virtual bool nvram_write( util::write_stream &file ) override; protected: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; - /* SFR Callbacks */ + // SFR Callbacks virtual void sfr_write(size_t offset, uint8_t data) override; virtual uint8_t sfr_read(size_t offset) override; + uint8_t handle_rnr(); + bool is_rnr_ready(); + private: optional_memory_region m_region; }; diff --git a/src/devices/cpu/mcs51/mcs51dasm.cpp b/src/devices/cpu/mcs51/mcs51dasm.cpp index ebd77aece33..ab3489d928f 100644 --- a/src/devices/cpu/mcs51/mcs51dasm.cpp +++ b/src/devices/cpu/mcs51/mcs51dasm.cpp @@ -2,31 +2,19 @@ // copyright-holders:Steve Ellenoff /***************************************************************************** * - * i8051dasm.c - * Portable MCS-51 Family Emulator + * Portable MCS-51 Family Disassembler + * Copyright Steve Ellenoff * - * Chips in the family: - * 8051 Product Line (8031,8051,8751) - * 8052 Product Line (8032,8052,8752) - * 8054 Product Line (8054) - * 8058 Product Line (8058) - * - * Copyright Steve Ellenoff, all rights reserved. - * - * This work is based on: - * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and - * #2) 8051 simulator by Travis Marlatte - * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE) - * - ***************************************************************************** * Symbol Memory Name Tables borrowed from: * D52 8052 Disassembler - Copyright Jeffery L. Post + * *****************************************************************************/ #include "emu.h" #include "mcs51dasm.h" // Note: addresses >= 0x100 are bit addresses +// Note: place default_names last in constructors to allow other names to override it const mcs51_disassembler::mem_info mcs51_disassembler::default_names[] = { { 0x00, "rb0r0" }, @@ -226,7 +214,7 @@ const mcs51_disassembler::mem_info mcs51_disassembler::i8xc51gb_names[] = { { 0xd4, "ad5" }, { 0xe4, "ad6" }, { 0xf4, "ad7" }, - { 0x85, "acon" }, + { 0x97, "acon" }, { 0xc7, "acmp" }, { 0xe8, "c1con" }, @@ -319,16 +307,16 @@ const mcs51_disassembler::mem_info mcs51_disassembler::i8xc751_names[] = { { 0x98, "i2con" }, { 0x99, "i2dat" }, { 0xd8, "i2cfg" }, - { 0xf8, "i2sta" }, /* read only */ + { 0xf8, "i2sta" }, // read only - { 0x198, "xstp" }, /* read: no function */ - { 0x199, "xstr" }, /* read: MASTER */ - { 0x19a, "cstp" }, /* read: STP */ - { 0x19b, "cstr" }, /* read: STR */ - { 0x19c, "carl" }, /* read: ARL */ - { 0x19d, "cdr" }, /* read: DRDY */ - { 0x19e, "idle" }, /* read: ATN */ - { 0x19f, "cxa" }, /* read: RDAT */ + { 0x198, "xstp" }, // read: no function + { 0x199, "xstr" }, // read: MASTER + { 0x19a, "cstp" }, // read: STP + { 0x19b, "cstr" }, // read: STR + { 0x19c, "carl" }, // read: ARL + { 0x19d, "cdr" }, // read: DRDY + { 0x19e, "idle" }, // read: ATN + { 0x19f, "cxa" }, // read: RDAT { 0x1ac, "ei2" }, @@ -360,6 +348,409 @@ const mcs51_disassembler::mem_info mcs51_disassembler::i8xc751_names[] = { { -1 } }; +const mcs51_disassembler::mem_info mcs51_disassembler::ds80c320_names[] = { + { 0x84, "dpl1" }, + { 0x85, "dph1" }, + { 0x86, "dps" }, + { 0x8e, "ckcon" }, + { 0x91, "exif" }, + { 0x98, "scon0" }, + { 0x99, "sbuf0" }, + { 0xa9, "saddr0" }, + { 0xaa, "saddr1" }, + { 0xb9, "saden0" }, + { 0xba, "saden1" }, + { 0xc0, "scon1" }, + { 0xc1, "sbuf1" }, + { 0xc5, "status" }, + { 0xc7, "ta" }, + { 0xc9, "t2mod" }, + { 0xd8, "wdcon" }, + { 0xe8, "eie" }, + { 0xf8, "eip" }, + + { 0x198, "sm0_0" }, + { 0x199, "sm1_0" }, + { 0x19a, "sm2_0" }, + { 0x19b, "ren_0" }, + { 0x19c, "tb8_0" }, + { 0x19d, "rb8_0" }, + { 0x19e, "ti_0" }, + { 0x19f, "ri_0" }, + + { 0x1ac, "es0" }, + { 0x1ae, "es1" }, + + { 0x1bc, "ps0" }, + { 0x1be, "ps1" }, + + { 0x1c0, "sm0_1" }, + { 0x1c1, "sm1_1" }, + { 0x1c2, "sm2_1" }, + { 0x1c3, "ren_1" }, + { 0x1c4, "tb8_1" }, + { 0x1c5, "rb8_1" }, + { 0x1c6, "ti_1" }, + { 0x1c7, "ri_1" }, + + { 0x1d5, "f1" }, + + { 0x1d8, "rwt" }, + { 0x1d9, "ewt" }, + { 0x1da, "wtrf" }, + { 0x1db, "wdif" }, + { 0x1dc, "pf1" }, + { 0x1dd, "epf1" }, + { 0x1de, "por" }, + { 0x1df, "smod_1" }, + + { 0x1e8, "ex2" }, + { 0x1e9, "ex3" }, + { 0x1ea, "ex4" }, + { 0x1eb, "ex5" }, + { 0x1ec, "ewdi" }, + { 0x1ed, "eie.5" }, + { 0x1ee, "eie.6" }, + { 0x1ef, "eie.7" }, + + { 0x1f8, "px2" }, + { 0x1f9, "px3" }, + { 0x1fa, "px4" }, + { 0x1fb, "px5" }, + { 0x1fc, "pwdi" }, + { 0x1fd, "eip.5" }, + { 0x1fe, "eip.6" }, + { 0x1ff, "eip.7" }, + + { -1 } +}; + +const mcs51_disassembler::mem_info mcs51_disassembler::sab80515_names[] = { + { 0xa8, "ien0" }, + { 0xa9, "ip0" }, + { 0xb8, "ien1" }, + { 0xb9, "ip1" }, + { 0xc0, "ircon" }, + { 0xc1, "ccen" }, + { 0xc2, "ccl1" }, + { 0xc3, "cch1" }, + { 0xc4, "ccl2" }, + { 0xc5, "cch2" }, + { 0xc6, "ccl3" }, + { 0xc7, "cch3" }, + { 0xc8, "t2con" }, + { 0xca, "crcl" }, + { 0xcb, "crch" }, + { 0xcc, "tl2" }, + { 0xcd, "th2" }, + { 0xd8, "adcon" }, + { 0xd9, "addat" }, + { 0xda, "dapr" }, + { 0xe8, "p4" }, + { 0xf8, "p5" }, + + { 0x190, "cc0" }, + { 0x191, "cc1" }, + { 0x192, "cc2" }, + { 0x193, "cc3" }, + { 0x194, "int2" }, + { 0x195, "t2ex" }, + { 0x196, "clkout" }, + { 0x197, "t2" }, + + { 0x1ad, "et2" }, + { 0x1ae, "wdt" }, + + { 0x1b8, "eadc" }, + { 0x1b9, "ex2" }, + { 0x1ba, "ex3" }, + { 0x1bb, "ex4" }, + { 0x1bc, "ex5" }, + { 0x1bd, "ex6" }, + { 0x1be, "swdt" }, + { 0x1bf, "exen2" }, + + { 0x1c0, "iadc" }, + { 0x1c1, "iex2" }, + { 0x1c2, "iex3" }, + { 0x1c3, "iex4" }, + { 0x1c4, "iex5" }, + { 0x1c5, "iex6" }, + { 0x1c6, "tf2" }, + { 0x1c7, "exf2" }, + + { 0x1c8, "t2i0" }, + { 0x1c9, "t2i1" }, + { 0x1ca, "t2cm" }, + { 0x1cb, "t2r0" }, + { 0x1cc, "t2r1" }, + { 0x1cd, "i2fr" }, + { 0x1ce, "i3fr" }, + { 0x1cf, "t2ps" }, + + { 0x1d8, "mx0" }, + { 0x1d9, "mx1" }, + { 0x1da, "mx2" }, + { 0x1db, "adm" }, + { 0x1dc, "bsy" }, + { 0x1dd, "adex" }, + { 0x1de, "clk" }, + { 0x1df, "bd" }, + + { -1 } +}; + +const mcs51_disassembler::mem_info mcs51_disassembler::sab80c515_names[] = { + { 0xdb, "p6" }, + + { -1 } +}; + +const mcs51_disassembler::mem_info mcs51_disassembler::rupi44_names[] = { + { 0x00, "rb0r0" }, + { 0x01, "rb0r1" }, + { 0x02, "rb0r2" }, + { 0x03, "rb0r3" }, + { 0x04, "rb0r4" }, + { 0x05, "rb0r5" }, + { 0x06, "rb0r6" }, + { 0x07, "rb0r7" }, + { 0x08, "rb1r0" }, + { 0x09, "rb1r1" }, + { 0x0a, "rb1r2" }, + { 0x0b, "rb1r3" }, + { 0x0c, "rb1r4" }, + { 0x0d, "rb1r5" }, + { 0x0e, "rb1r6" }, + { 0x0f, "rb1r7" }, + { 0x10, "rb2r0" }, + { 0x11, "rb2r1" }, + { 0x12, "rb2r2" }, + { 0x13, "rb2r3" }, + { 0x14, "rb2r4" }, + { 0x15, "rb2r5" }, + { 0x16, "rb2r6" }, + { 0x17, "rb2r7" }, + { 0x18, "rb3r0" }, + { 0x19, "rb3r1" }, + { 0x1a, "rb3r2" }, + { 0x1b, "rb3r3" }, + { 0x1c, "rb3r4" }, + { 0x1d, "rb3r5" }, + { 0x1e, "rb3r6" }, + { 0x1f, "rb3r7" }, + + { 0x80, "p0" }, + { 0x81, "sp" }, + { 0x82, "dpl" }, + { 0x83, "dph" }, + { 0x87, "pcon" }, + { 0x88, "tcon" }, + { 0x89, "tmod" }, + { 0x8a, "tl0" }, + { 0x8b, "tl1" }, + { 0x8c, "th0" }, + { 0x8d, "th1" }, + { 0x90, "p1" }, + { 0xa0, "p2" }, + { 0xa8, "ie" }, + { 0xb0, "p3" }, + { 0xb8, "ip" }, + { 0xc8, "sts" }, + { 0xc9, "smd" }, + { 0xca, "rcb" }, + { 0xcb, "rbl" }, + { 0xcc, "rbs" }, + { 0xcd, "rfl" }, + { 0xce, "stad" }, + { 0xd0, "psw" }, + { 0xd8, "nsnr" }, + { 0xda, "tcb" }, + { 0xdb, "tbl" }, + { 0xdc, "tbc" }, + { 0xe0, "acc" }, + { 0xf0, "b" }, + + { 0x188, "it0" }, + { 0x189, "ie0" }, + { 0x18a, "it1" }, + { 0x18b, "ie1" }, + { 0x18c, "tr0" }, + { 0x18d, "tf0" }, + { 0x18e, "tr1" }, + { 0x18f, "tf1" }, + + { 0x1a8, "ex0" }, + { 0x1a9, "et0" }, + { 0x1aa, "ex1" }, + { 0x1ab, "et1" }, + { 0x1ac, "es" }, + { 0x1ad, "ie.5" }, + { 0x1ae, "ie.6" }, + { 0x1af, "ea" }, + + { 0x1b0, "io" }, + { 0x1b1, "data" }, + { 0x1b2, "int0" }, + { 0x1b3, "int1" }, + { 0x1b4, "t0" }, + { 0x1b5, "t1" }, + { 0x1b6, "wr" }, + { 0x1b7, "rd" }, + + { 0x1b8, "px0" }, + { 0x1b9, "pt0" }, + { 0x1ba, "px1" }, + { 0x1bb, "pt1" }, + { 0x1bc, "ps" }, + { 0x1bd, "ip.5" }, + { 0x1be, "ip.6" }, + { 0x1bf, "ip.7" }, + + { 0x1c8, "rbp" }, + { 0x1c9, "am" }, + { 0x1ca, "opb" }, + { 0x1cb, "bov" }, + { 0x1cc, "si" }, + { 0x1cd, "rts" }, + { 0x1ce, "rbe" }, + { 0x1cf, "tbf" }, + + { 0x1d0, "p" }, + { 0x1d1, "psw.1" }, + { 0x1d2, "ov" }, + { 0x1d3, "rs0" }, + { 0x1d4, "rs1" }, + { 0x1d5, "f0" }, + { 0x1d6, "ac" }, + { 0x1d7, "cy" }, + + { 0x1d8, "ser" }, + { 0x1d9, "nr0" }, + { 0x1da, "nr1" }, + { 0x1db, "nr2" }, + { 0x1dc, "ses" }, + { 0x1dd, "ns0" }, + { 0x1de, "ns1" }, + { 0x1df, "ns2" }, + + { -1 } +}; + +const mcs51_disassembler::mem_info mcs51_disassembler::p8xc562_names[] = { + { 0xa8, "ien0" }, + { 0xa9, "cml0" }, + { 0xaa, "cml1" }, + { 0xab, "cml2" }, + { 0xac, "ctl0" }, + { 0xad, "ctl1" }, + { 0xae, "ctl2" }, + { 0xaf, "ctl3" }, + { 0xb8, "ip0" }, + { 0xc0, "p4" }, + { 0xc4, "p5" }, + { 0xc5, "adcon" }, + { 0xc6, "adch" }, + { 0xc8, "tm2ir" }, + { 0xc9, "cmh0" }, + { 0xca, "cmh1" }, + { 0xcb, "cmh2" }, + { 0xcc, "cth0" }, + { 0xcd, "cth1" }, + { 0xce, "cth2" }, + { 0xcf, "cth3" }, + { 0xe8, "ien1" }, + { 0xea, "tm2con" }, + { 0xeb, "ctcon" }, + { 0xec, "tml2" }, + { 0xed, "tmh2" }, + { 0xee, "ste" }, + { 0xef, "rte" }, + { 0xf8, "ip1" }, + { 0xfc, "pwm0" }, + { 0xfd, "pwm1" }, + { 0xfe, "pwmp" }, + { 0xff, "t3" }, + + { 0x190, "ct0i" }, + { 0x191, "ct1i" }, + { 0x192, "ct2i" }, + { 0x193, "ct3i" }, + { 0x194, "t2" }, + { 0x195, "rt2" }, + + { 0x1ae, "ead" }, + + { 0x1be, "pad" }, + + { 0x1c0, "cmsr0" }, + { 0x1c1, "cmsr1" }, + { 0x1c2, "cmsr2" }, + { 0x1c3, "cmsr3" }, + { 0x1c4, "cmsr4" }, + { 0x1c5, "cmsr5" }, + { 0x1c6, "cmt0" }, + { 0x1c7, "cmt1" }, + + { 0x1c8, "cti0" }, + { 0x1c9, "cti1" }, + { 0x1ca, "cti2" }, + { 0x1cb, "cti3" }, + { 0x1cc, "cmi0" }, + { 0x1cd, "cmi1" }, + { 0x1ce, "cmi2" }, + { 0x1cf, "t2ov" }, + + { 0x1e8, "ect0" }, + { 0x1e9, "ect1" }, + { 0x1ea, "ect2" }, + { 0x1eb, "ect3" }, + { 0x1ec, "ecm0" }, + { 0x1ed, "ecm1" }, + { 0x1ee, "ecm2" }, + { 0x1ef, "et2" }, + + { 0x1f8, "pct0" }, + { 0x1f9, "pct1" }, + { 0x1fa, "pct2" }, + { 0x1fb, "pct3" }, + { 0x1fc, "pcm0" }, + { 0x1fd, "pcm1" }, + { 0x1fe, "pcm2" }, + { 0x1ff, "pt2" }, + + { -1 } +}; + +const mcs51_disassembler::mem_info mcs51_disassembler::p8xc552_names[] = { + { 0x98, "s0con" }, + { 0x99, "s0buf" }, + { 0xd8, "s1con" }, + { 0xd9, "s1sta" }, + { 0xda, "s1dat" }, + { 0xdb, "s1adr" }, + + { 0x196, "scl" }, + { 0x197, "sda" }, + + { 0x1ac, "es0" }, + { 0x1ad, "es1" }, + + { 0x1bc, "ps0" }, + { 0x1bd, "ps1" }, + + { 0x1d8, "cr0" }, + { 0x1d9, "cr1" }, + { 0x1da, "aa" }, + { 0x1db, "si" }, + { 0x1dc, "sto" }, + { 0x1dd, "sta" }, + { 0x1de, "ens1" }, + { 0x1df, "cr2" }, + + { -1 } +}; + mcs51_disassembler::mcs51_disassembler() { } @@ -495,6 +886,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off sym = get_bit_address(params.r8(PC++)); rel = params.r8(PC++); util::stream_format(stream, "jbc %s,$%04X", sym, PC + rel); + flags = STEP_COND; break; //ACALL code addr /* 1: aaa1 0001 */ @@ -557,6 +949,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off sym = get_bit_address(params.r8(PC++)); rel = params.r8(PC++); util::stream_format(stream, "jb %s,$%04X", sym, (PC + rel)); + flags = STEP_COND; break; //RET @@ -605,6 +998,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off sym = get_bit_address(params.r8(PC++)); rel = params.r8(PC++); util::stream_format(stream, "jnb %s,$%04X", sym, (PC + rel)); + flags = STEP_COND; break; //RETI @@ -651,6 +1045,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off case 0x40: /* 1: 0100 0000 */ rel = params.r8(PC++); util::stream_format(stream, "jc $%04X", PC + rel); + flags = STEP_COND; break; //ORL data addr, A @@ -699,6 +1094,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off case 0x50: /* 1: 0101 0000 */ rel = params.r8(PC++); util::stream_format(stream, "jnc $%04X", PC + rel); + flags = STEP_COND; break; //Unable to test @@ -749,6 +1145,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off case 0x60: /* 1: 0110 0000 */ rel = params.r8(PC++); util::stream_format(stream, "jz $%04X", PC + rel); + flags = STEP_COND; break; //Unable to test @@ -798,6 +1195,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off case 0x70: /* 1: 0111 0000 */ rel = params.r8(PC++); util::stream_format(stream, "jnz $%04X", PC + rel); + flags = STEP_COND; break; //Unable to test @@ -1013,6 +1411,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off data = params.r8(PC++); rel = params.r8(PC++); util::stream_format(stream, "cjne a,#$%02X,$%04X", data, PC + rel); + flags = STEP_COND; break; //CJNE A, data addr, code addr @@ -1020,6 +1419,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off sym = get_data_address(params.r8(PC++)); rel = params.r8(PC++); util::stream_format(stream, "cjne a,%s,$%04X", sym, PC + rel); + flags = STEP_COND; break; //Unable to test @@ -1029,6 +1429,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off data = params.r8(PC++); rel = params.r8(PC++); util::stream_format(stream, "cjne @r%d,#$%02X,$%04X", op&1, data, PC + rel); + flags = STEP_COND; break; //CJNE R0 to R7, #data, code addr/* 1: 1011 1rrr */ @@ -1043,6 +1444,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off data = params.r8(PC++); rel = params.r8(PC++); util::stream_format(stream, "cjne r%d,#$%02X,$%04X", op&7, data, PC + rel); + flags = STEP_COND; break; //PUSH data addr @@ -1119,7 +1521,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off sym = get_data_address(params.r8(PC++)); rel = params.r8(PC++); util::stream_format(stream, "djnz %s,$%04X", sym, PC + rel); - flags = STEP_OVER; + flags = STEP_COND; break; //XCHD A, @R0/@R1 /* 1: 1101 011i */ @@ -1139,7 +1541,7 @@ offs_t mcs51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, off case 0xdf: rel = params.r8(PC++); util::stream_format(stream, "djnz r%d,$%04X", op&7, (PC + rel)); - flags = STEP_OVER; + flags = STEP_COND; break; //MOVX A,@DPTR @@ -1243,7 +1645,7 @@ i8051_disassembler::i8051_disassembler() : mcs51_disassembler(default_names) { } -i8052_disassembler::i8052_disassembler() : mcs51_disassembler(default_names, i8052_names) +i8052_disassembler::i8052_disassembler() : mcs51_disassembler(i8052_names, default_names) { } @@ -1251,18 +1653,42 @@ i80c51_disassembler::i80c51_disassembler() : mcs51_disassembler(default_names) { } -i80c52_disassembler::i80c52_disassembler() : mcs51_disassembler(default_names, i8052_names, i80c52_names) +i80c52_disassembler::i80c52_disassembler() : mcs51_disassembler(i8052_names, i80c52_names, default_names) +{ +} + +i8xc51fx_disassembler::i8xc51fx_disassembler() : mcs51_disassembler(i8052_names, i80c52_names, i8xc51fx_names, default_names) +{ +} + +i8xc51gb_disassembler::i8xc51gb_disassembler() : mcs51_disassembler(i8052_names, i80c52_names, i8xc51fx_names, i8xc51gb_names, default_names) +{ +} + +ds5002fp_disassembler::ds5002fp_disassembler() : mcs51_disassembler(i8052_names, i80c52_names, ds5002fp_names, i8xc751_names, default_names) +{ +} + +ds80c320_disassembler::ds80c320_disassembler() : mcs51_disassembler(i8052_names, ds80c320_names, default_names) +{ +} + +sab80515_disassembler::sab80515_disassembler() : mcs51_disassembler(sab80515_names, default_names) +{ +} + +sab80c515_disassembler::sab80c515_disassembler() : mcs51_disassembler(sab80515_names, sab80c515_names, default_names) { } -i8xc51fx_disassembler::i8xc51fx_disassembler() : mcs51_disassembler(default_names, i8052_names, i80c52_names, i8xc51fx_names) +rupi44_disassembler::rupi44_disassembler() : mcs51_disassembler(rupi44_names) { } -i8xc51gb_disassembler::i8xc51gb_disassembler() : mcs51_disassembler(default_names, i8052_names, i80c52_names, i8xc51fx_names, i8xc51gb_names) +p8xc552_disassembler::p8xc552_disassembler() : mcs51_disassembler(p8xc562_names, p8xc552_names, default_names) { } -ds5002fp_disassembler::ds5002fp_disassembler() : mcs51_disassembler(default_names, i8052_names, i80c52_names, ds5002fp_names, i8xc751_names) +p8xc562_disassembler::p8xc562_disassembler() : mcs51_disassembler(p8xc562_names, default_names) { } diff --git a/src/devices/cpu/mcs51/mcs51dasm.h b/src/devices/cpu/mcs51/mcs51dasm.h index 9ae251af8ea..4ef2a2fd486 100644 --- a/src/devices/cpu/mcs51/mcs51dasm.h +++ b/src/devices/cpu/mcs51/mcs51dasm.h @@ -2,25 +2,9 @@ // copyright-holders:Steve Ellenoff /***************************************************************************** * - * i8051dasm.c - * Portable MCS-51 Family Emulator + * Portable MCS-51 Family Disassembler + * Copyright Steve Ellenoff * - * Chips in the family: - * 8051 Product Line (8031,8051,8751) - * 8052 Product Line (8032,8052,8752) - * 8054 Product Line (8054) - * 8058 Product Line (8058) - * - * Copyright Steve Ellenoff, all rights reserved. - * - * This work is based on: - * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and - * #2) 8051 simulator by Travis Marlatte - * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE) - * - ***************************************************************************** - * Symbol Memory Name Tables borrowed from: - * D52 8052 Disassembler - Copyright Jeffery L. Post *****************************************************************************/ #ifndef MAME_CPU_MCS51_MCS51DASM_H @@ -46,6 +30,12 @@ public: static const mem_info i8xc51gb_names[]; static const mem_info ds5002fp_names[]; static const mem_info i8xc751_names[]; + static const mem_info ds80c320_names[]; + static const mem_info sab80515_names[]; + static const mem_info sab80c515_names[]; + static const mem_info rupi44_names[]; + static const mem_info p8xc552_names[]; + static const mem_info p8xc562_names[]; template<typename ...Names> mcs51_disassembler(Names &&... names) : mcs51_disassembler() { add_names(names...); @@ -126,5 +116,47 @@ public: virtual ~ds5002fp_disassembler() = default; }; +class ds80c320_disassembler : public mcs51_disassembler +{ +public: + ds80c320_disassembler(); + virtual ~ds80c320_disassembler() = default; +}; + +class sab80515_disassembler : public mcs51_disassembler +{ +public: + sab80515_disassembler(); + virtual ~sab80515_disassembler() = default; +}; + +class sab80c515_disassembler : public mcs51_disassembler +{ +public: + sab80c515_disassembler(); + virtual ~sab80c515_disassembler() = default; +}; + +class rupi44_disassembler : public mcs51_disassembler +{ +public: + rupi44_disassembler(); + virtual ~rupi44_disassembler() = default; +}; + +class p8xc552_disassembler : public mcs51_disassembler +{ +public: + p8xc552_disassembler(); + virtual ~p8xc552_disassembler() = default; +}; + +class p8xc562_disassembler : public mcs51_disassembler +{ +public: + p8xc562_disassembler(); + virtual ~p8xc562_disassembler() = default; +}; + #endif diff --git a/src/devices/cpu/mcs51/mcs51ops.hxx b/src/devices/cpu/mcs51/mcs51ops.hxx index 99917328232..5e7885b29f9 100644 --- a/src/devices/cpu/mcs51/mcs51ops.hxx +++ b/src/devices/cpu/mcs51/mcs51ops.hxx @@ -9,7 +9,7 @@ //ACALL code addr /* 1: aaa1 0001 */ OPHANDLER( acall ) { - uint8_t addr = ROP_ARG(PC++); //Grab code address byte + uint8_t addr = ROP_ARG(PC++); //Grab code address byte PUSH_PC(); //Save PC to the stack //Thanks Gerrit for help with this! :) PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr; @@ -18,81 +18,81 @@ OPHANDLER( acall ) //ADD A, #data /* 1: 0010 0100 */ OPHANDLER( add_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t result = ACC + data; //Add data to accumulator + DO_ADD_FLAGS(ACC, data, 0); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADD A, data addr /* 1: 0010 0101 */ OPHANDLER( add_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t result = ACC + data; //Add data to accumulator + DO_ADD_FLAGS(ACC, data, 0); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADD A, @R0/@R1 /* 1: 0010 011i */ OPHANDLER( add_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 - uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t result = ACC + data; //Add data to accumulator + DO_ADD_FLAGS(ACC, data, 0); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADD A, R0 to R7 /* 1: 0010 1rrr */ OPHANDLER( add_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + uint8_t data = R_REG(r); //Grab data from R0 - R7 + uint8_t result = ACC + data; //Add data to accumulator + DO_ADD_FLAGS(ACC, data, 0); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADDC A, #data /* 1: 0011 0100 */ OPHANDLER( addc_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator - DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator + DO_ADD_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADDC A, data addr /* 1: 0011 0101 */ OPHANDLER( addc_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator - DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator + DO_ADD_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADDC A, @R0/@R1 /* 1: 0011 011i */ OPHANDLER( addc_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 - uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator - DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator + DO_ADD_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //ADDC A, R0 to R7 /* 1: 0011 1rrr */ OPHANDLER( addc_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator - DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = R_REG(r); //Grab data from R0 - R7 + uint8_t result = ACC + data + GET_CY; //Add data + carry flag to accumulator + DO_ADD_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //AJMP code addr /* 1: aaa0 0001 */ OPHANDLER( ajmp ) { - uint8_t addr = ROP_ARG(PC++); //Grab code address byte + uint8_t addr = ROP_ARG(PC++); //Grab code address byte //Thanks Gerrit for help with this! :) PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr; } @@ -100,136 +100,136 @@ OPHANDLER( ajmp ) //ANL data addr, A /* 1: 0101 0010 */ OPHANDLER( anl_mem_a ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,data & ACC); //Set data address value to it's value Logical AND with ACC + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, data & ACC); //Set data address value to it's value Logical AND with ACC } //ANL data addr, #data /* 1: 0101 0011 */ OPHANDLER( anl_mem_byte ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t srcdata = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,srcdata & data); //Set data address value to it's value Logical AND with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t srcdata = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, srcdata & data); //Set data address value to it's value Logical AND with Data } //ANL A, #data /* 1: 0101 0100 */ OPHANDLER( anl_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data + uint8_t data = ROP_ARG(PC++); //Grab data + SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data } //ANL A, data addr /* 1: 0101 0101 */ OPHANDLER( anl_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data } //ANL A, @RO/@R1 /* 1: 0101 011i */ OPHANDLER( anl_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to - SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data } //ANL A, RO to R7 /* 1: 0101 1rrr */ OPHANDLER( anl_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data + uint8_t data = R_REG(r); //Grab data from R0 - R7 + SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data } //ANL C, bit addr /* 1: 1000 0010 */ OPHANDLER( anl_c_bitaddr ) { int cy = GET_CY; - uint8_t addr = ROP_ARG(PC++); //Grab bit address - uint8_t bit = BIT_R(addr); //Grab bit data from bit address - SET_CY( (cy & bit) ); //Set Carry flag to Carry Flag Value Logical AND with Bit + uint8_t addr = ROP_ARG(PC++); //Grab bit address + uint8_t bit = BIT_R(addr); //Grab bit data from bit address + SET_CY(cy & bit); //Set Carry flag to Carry Flag Value Logical AND with Bit } //ANL C,/bit addr /* 1: 1011 0000 */ OPHANDLER( anl_c_nbitaddr ) { int cy = GET_CY; - uint8_t addr = ROP_ARG(PC++); //Grab bit address - uint8_t bit = BIT_R(addr); //Grab bit data from bit address - bit = ((~bit)&1); //Complement bit - SET_CY( (cy & bit) ); //Set Carry flag to Carry Flag Value Logical AND with Complemented Bit + uint8_t addr = ROP_ARG(PC++); //Grab bit address + uint8_t bit = BIT_R(addr); //Grab bit data from bit address + bit = (~bit & 1); //Complement bit + SET_CY(cy & bit); //Set Carry flag to Carry Flag Value Logical AND with Complemented Bit } //CJNE A, #data, code addr /* 1: 1011 0100 */ OPHANDLER( cjne_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t data = ROP_ARG(PC++); //Grab data + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(ACC != data) //Jump if values are not equal + if (ACC != data) //Jump if values are not equal { PC = PC + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value - SET_CY( (ACC < data) ); + SET_CY(ACC < data); } //CJNE A, data addr, code addr /* 1: 1011 0101 */ OPHANDLER( cjne_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - uint8_t data = IRAM_R(addr); //Pull value from data address + uint8_t addr = ROP_ARG(PC++); //Grab data address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t data = IRAM_R(addr); //Pull value from data address - if(ACC != data) //Jump if values are not equal + if (ACC != data) //Jump if values are not equal { PC = PC + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value - SET_CY( (ACC < data) ); + SET_CY(ACC < data); } //CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */ OPHANDLER( cjne_ir_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - uint8_t srcdata = IRAM_IR(R_REG(r)); //Grab value pointed to by R0 or R1 + uint8_t data = ROP_ARG(PC++); //Grab data + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t srcdata = IRAM_IR(R_REG(r)); //Grab value pointed to by R0 or R1 - if(srcdata != data) //Jump if values are not equal + if (srcdata != data) //Jump if values are not equal { PC = PC + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value - SET_CY( (srcdata < data) ); + SET_CY(srcdata < data); } //CJNE R0 to R7, #data, code addr /* 1: 1011 1rrr */ OPHANDLER( cjne_r_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - uint8_t srcdata = R_REG(r); //Grab value of R0 - R7 + uint8_t data = ROP_ARG(PC++); //Grab data + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t srcdata = R_REG(r); //Grab value of R0 - R7 - if(srcdata != data) //Jump if values are not equal + if (srcdata != data) //Jump if values are not equal { PC = PC + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value - SET_CY( (srcdata < data) ); + SET_CY(srcdata < data); } //CLR bit addr /* 1: 1100 0010 */ OPHANDLER( clr_bitaddr ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,0); //Clear bit at specified bit address + uint8_t addr = ROP_ARG(PC++); //Grab bit address + BIT_W(addr, 0); //Clear bit at specified bit address } //CLR C /* 1: 1100 0011 */ @@ -241,29 +241,29 @@ OPHANDLER( clr_c ) //CLR A /* 1: 1110 0100 */ OPHANDLER( clr_a ) { - SET_ACC(0); //Clear Accumulator + SET_ACC(0); //Clear Accumulator } //CPL bit addr /* 1: 1011 0010 */ OPHANDLER( cpl_bitaddr ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - uint8_t data = (~BIT_R(addr))&1; - BIT_W(addr,data); //Complement bit at specified bit address + uint8_t addr = ROP_ARG(PC++); //Grab bit address + uint8_t data = (~BIT_R(addr)) & 1; + BIT_W(addr, data); //Complement bit at specified bit address } //CPL C /* 1: 1011 0011 */ OPHANDLER( cpl_c ) { - uint8_t bit = (~GET_CY)&1; //Complement Carry Flag + uint8_t bit = (~GET_CY) & 1; //Complement Carry Flag SET_CY(bit); } //CPL A /* 1: 1111 0100 */ OPHANDLER( cpl_a ) { - uint8_t data = ((~ACC)&0xff); - SET_ACC(data); //Complement Accumulator + uint8_t data = ((~ACC) & 0xff); + SET_ACC(data); //Complement Accumulator } //DA A /* 1: 1101 0100 */ @@ -278,34 +278,34 @@ OPHANDLER( da_a ) The carry flag will be set if the result is > 0x99, but not cleared otherwise */ uint16_t new_acc = ACC & 0xff; - if(GET_AC || (new_acc & 0x0f) > 0x09) + if (GET_AC || (new_acc & 0x0f) > 0x09) new_acc += 0x06; - if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff)) + if (GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff)) new_acc += 0x60; - SET_ACC(new_acc&0xff); - if(new_acc & ~0xff) - SET_CY(1); + SET_ACC(new_acc & 0xff); + if (new_acc & ~0xff) + SET_CY(1); } //DEC A /* 1: 0001 0100 */ OPHANDLER( dec_a ) { - SET_ACC(ACC-1); + SET_ACC(ACC - 1); } //DEC data addr /* 1: 0001 0101 */ OPHANDLER( dec_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t addr = ROP_ARG(PC++); //Grab data address uint8_t data = IRAM_R(addr); - IRAM_W(addr,data-1); + IRAM_W(addr, data - 1); } //DEC @R0/@R1 /* 1: 0001 011i */ OPHANDLER( dec_ir ) { uint8_t data = IRAM_IR(R_REG(r)); - IRAM_IW(R_REG(r),data-1); + IRAM_IW(R_REG(r), data - 1); } //DEC R0 to R7 /* 1: 0001 1rrr */ @@ -317,14 +317,16 @@ OPHANDLER( dec_r ) //DIV AB /* 1: 1000 0100 */ OPHANDLER( div_ab ) { - if( B == 0 ) { + if (B == 0) + { //Overflow flag is set! SET_OV(1); //Really the values are undefined according to the manual, but we'll just leave them as is.. //SET_ACC(0xff); - //SFR_W(B,0xff); + //SFR_W(B, 0xff); } - else { + else + { int a = (int)ACC / B; int b = (int)ACC % B; //A gets quotient byte, B gets remainder byte @@ -340,10 +342,10 @@ OPHANDLER( div_ab ) //DJNZ data addr, code addr /* 1: 1101 0101 */ OPHANDLER( djnz_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - IRAM_W(addr,IRAM_R(addr) - 1); //Decrement value contained at data address - if(IRAM_R(addr) != 0) //Branch if contents of data address is not 0 + uint8_t addr = ROP_ARG(PC++); //Grab data address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + IRAM_W(addr, IRAM_R(addr) - 1); //Decrement value contained at data address + if (IRAM_R(addr) != 0) //Branch if contents of data address is not 0 { PC = PC + rel_addr; } @@ -352,9 +354,9 @@ OPHANDLER( djnz_mem ) //DJNZ R0 to R7,code addr /* 1: 1101 1rrr */ OPHANDLER( djnz_r ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - SET_REG(r ,R_REG(r) - 1); //Decrement value - if(R_REG(r) != 0) //Branch if contents of R0 - R7 is not 0 + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + SET_REG(r, R_REG(r) - 1); //Decrement value + if (R_REG(r) != 0) //Branch if contents of R0 - R7 is not 0 { PC = PC + rel_addr; } @@ -363,22 +365,22 @@ OPHANDLER( djnz_r ) //INC A /* 1: 0000 0100 */ OPHANDLER( inc_a ) { - SET_ACC(ACC+1); + SET_ACC(ACC + 1); } //INC data addr /* 1: 0000 0101 */ OPHANDLER( inc_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t addr = ROP_ARG(PC++); //Grab data address uint8_t data = IRAM_R(addr); - IRAM_W(addr,data+1); + IRAM_W(addr, data + 1); } //INC @R0/@R1 /* 1: 0000 011i */ OPHANDLER( inc_ir ) { uint8_t data = IRAM_IR(R_REG(r)); - IRAM_IW(R_REG(r),data+1); + IRAM_IW(R_REG(r), data + 1); } //INC R0 to R7 /* 1: 0000 1rrr */ @@ -391,16 +393,16 @@ OPHANDLER( inc_r ) //INC DPTR /* 1: 1010 0011 */ OPHANDLER( inc_dptr ) { - uint16_t dptr = (DPTR)+1; + uint16_t dptr = (DPTR) + 1; SET_DPTR(dptr); } //JB bit addr, code addr /* 1: 0010 0000 */ OPHANDLER( jb ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(BIT_R(addr)) //If bit set at specified bit address, jump + uint8_t addr = ROP_ARG(PC++); //Grab bit address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (BIT_R(addr)) //If bit set at specified bit address, jump { PC = PC + rel_addr; } @@ -409,19 +411,20 @@ OPHANDLER( jb ) //JBC bit addr, code addr /* 1: 0001 0000 */ OPHANDLER( jbc ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(BIT_R(addr)) { //If bit set at specified bit address, jump + uint8_t addr = ROP_ARG(PC++); //Grab bit address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (BIT_R(addr)) //If bit set at specified bit address, jump + { PC = PC + rel_addr; - BIT_W(addr,0); //Clear Bit also + BIT_W(addr, 0); //Clear Bit also } } //JC code addr /* 1: 0100 0000 */ OPHANDLER( jc ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(GET_CY) //Jump if Carry Flag Set + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (GET_CY) //Jump if Carry Flag Set { PC = PC + rel_addr; } @@ -436,9 +439,9 @@ OPHANDLER( jmp_iadptr ) //JNB bit addr, code addr /* 1: 0011 0000 */ OPHANDLER( jnb ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(!BIT_R(addr)) //If bit NOT set at specified bit address, jump + uint8_t addr = ROP_ARG(PC++); //Grab bit address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (!BIT_R(addr)) //If bit NOT set at specified bit address, jump { PC = PC + rel_addr; } @@ -447,8 +450,8 @@ OPHANDLER( jnb ) //JNC code addr /* 1: 0101 0000 */ OPHANDLER( jnc ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(!GET_CY) //Jump if Carry Flag not set + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (!GET_CY) //Jump if Carry Flag not set { PC = PC + rel_addr; } @@ -457,20 +460,20 @@ OPHANDLER( jnc ) //JNZ code addr /* 1: 0111 0000 */ OPHANDLER( jnz ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(ACC != 0) //Branch if ACC is not 0 + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (ACC != 0) //Branch if ACC is not 0 { - PC = PC+rel_addr; + PC = PC + rel_addr; } } //JZ code addr /* 1: 0110 0000 */ OPHANDLER( jz ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - if(ACC == 0) //Branch if ACC is 0 + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + if (ACC == 0) //Branch if ACC is 0 { - PC = PC+rel_addr; + PC = PC + rel_addr; } } @@ -481,7 +484,7 @@ OPHANDLER( lcall ) addr_hi = ROP_ARG(PC++); addr_lo = ROP_ARG(PC++); PUSH_PC(); - PC = (uint16_t)((addr_hi<<8) | addr_lo); + PC = (uint16_t)((addr_hi << 8) | addr_lo); } //LJMP code addr /* 1: 0000 0010 */ @@ -490,21 +493,21 @@ OPHANDLER( ljmp ) uint8_t addr_hi, addr_lo; addr_hi = ROP_ARG(PC++); addr_lo = ROP_ARG(PC++); - PC = (uint16_t)((addr_hi<<8) | addr_lo); + PC = (uint16_t)((addr_hi << 8) | addr_lo); } //MOV A, #data /* 1: 0111 0100 */ OPHANDLER( mov_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - SET_ACC(data); //Store data to ACC + uint8_t data = ROP_ARG(PC++); //Grab data + SET_ACC(data); //Store data to ACC } //MOV A, data addr /* 1: 1110 0101 */ OPHANDLER( mov_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC + uint8_t addr = ROP_ARG(PC++); //Grab data address + SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC } //MOV A,@RO/@R1 /* 1: 1110 011i */ @@ -522,9 +525,9 @@ OPHANDLER( mov_a_r ) //MOV data addr, #data /* 1: 0111 0101 */ OPHANDLER( mov_mem_byte ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = ROP_ARG(PC++); //Grab data - IRAM_W(addr,data); //Store data to data address location + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = ROP_ARG(PC++); //Grab data + IRAM_W(addr, data); //Store data to data address location } //MOV data addr, data addr /* 1: 1000 0101 */ @@ -534,35 +537,35 @@ OPHANDLER( mov_mem_mem ) uint8_t src,dst; src = ROP_ARG(PC++); //Grab source data address dst = ROP_ARG(PC++); //Grab destination data address - IRAM_W(dst,IRAM_R(src)); //Read source address contents and store to destination address + IRAM_W(dst, IRAM_R(src)); //Read source address contents and store to destination address } //MOV @R0/@R1, #data /* 1: 0111 011i */ OPHANDLER( mov_ir_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - IRAM_IW(R_REG(r),data); //Store data to address pointed by R0 or R1 + uint8_t data = ROP_ARG(PC++); //Grab data + IRAM_IW(R_REG(r), data); //Store data to address pointed by R0 or R1 } //MOV R0 to R7, #data /* 1: 0111 1rrr */ OPHANDLER( mov_r_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - SET_REG(r, data); //Store to R0 - R7 + uint8_t data = ROP_ARG(PC++); //Grab data + SET_REG(r, data); //Store to R0 - R7 } //MOV data addr, @R0/@R1 /* 1: 1000 011i */ OPHANDLER( mov_mem_ir ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - IRAM_W(addr,IRAM_IR(R_REG(r))); //Store contents pointed to by R0 or R1 to data address + uint8_t addr = ROP_ARG(PC++); //Grab data address + IRAM_W(addr, IRAM_IR(R_REG(r))); //Store contents pointed to by R0 or R1 to data address } //MOV data addr,R0 to R7 /* 1: 1000 1rrr */ OPHANDLER( mov_mem_r ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - IRAM_W(addr,R_REG(r)); //Store contents of R0 - R7 to data address + uint8_t addr = ROP_ARG(PC++); //Grab data address + IRAM_W(addr, R_REG(r)); //Store contents of R0 - R7 to data address } //MOV DPTR, #data16 /* 1: 1001 0000 */ @@ -571,41 +574,41 @@ OPHANDLER( mov_dptr_byte ) uint8_t data_hi, data_lo; data_hi = ROP_ARG(PC++); //Grab hi byte data_lo = ROP_ARG(PC++); //Grab lo byte - SET_DPTR((uint16_t)((data_hi<<8)|data_lo)); //Store to DPTR + SET_DPTR((uint16_t)((data_hi << 8) | data_lo)); //Store to DPTR } //MOV bit addr, C /* 1: 1001 0010 */ OPHANDLER( mov_bitaddr_c ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,GET_CY); //Store Carry Flag to Bit Address + uint8_t addr = ROP_ARG(PC++); //Grab bit address + BIT_W(addr, GET_CY); //Store Carry Flag to Bit Address } //MOV @R0/@R1, data addr /* 1: 1010 011i */ OPHANDLER( mov_ir_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - IRAM_IW(R_REG(r),IRAM_R(addr)); //Store data from data address to address pointed to by R0 or R1 + uint8_t addr = ROP_ARG(PC++); //Grab data address + IRAM_IW(R_REG(r), IRAM_R(addr)); //Store data from data address to address pointed to by R0 or R1 } //MOV R0 to R7, data addr /* 1: 1010 1rrr */ OPHANDLER( mov_r_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t addr = ROP_ARG(PC++); //Grab data address SET_REG(r, IRAM_R(addr)); //Store to R0 - R7 } //MOV data addr, A /* 1: 1111 0101 */ OPHANDLER( mov_mem_a ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - IRAM_W(addr,ACC); //Store A to data address + uint8_t addr = ROP_ARG(PC++); //Grab data address + IRAM_W(addr, ACC); //Store A to data address } //MOV @R0/@R1, A /* 1: 1111 011i */ OPHANDLER( mov_ir_a ) { - IRAM_IW(R_REG(r),ACC); //Store A to location pointed to by R0 or R1 + IRAM_IW(R_REG(r), ACC); //Store A to location pointed to by R0 or R1 } //MOV R0 to R7, A /* 1: 1111 1rrr */ @@ -618,15 +621,15 @@ OPHANDLER( mov_r_a ) OPHANDLER( movc_a_iapc ) { uint8_t data; - data = CODEMEM_R(ACC+PC); //Move a byte from CODE(Program) Memory and store to ACC + data = CODEMEM_R(ACC + PC); //Move a byte from CODE(Program) Memory and store to ACC SET_ACC(data); } //MOV C, bit addr /* 1: 1010 0010 */ OPHANDLER( mov_c_bitaddr ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - SET_CY( (BIT_R(addr)) ); //Store Bit from Bit Address to Carry Flag + uint8_t addr = ROP_ARG(PC++); //Grab bit address + SET_CY(BIT_R(addr)); //Store Bit from Bit Address to Carry Flag } //MOVC A, @A + DPTR /* 1: 1001 0011 */ @@ -641,35 +644,35 @@ OPHANDLER( movc_a_iadptr ) //(Move External Ram 16 bit address to A) OPHANDLER( movx_a_idptr ) { -// uint8_t byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr - uint32_t addr = ERAM_ADDR(DPTR, 0xFFFF); - uint8_t byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by dptr - SET_ACC(byte); //Store to ACC +// uint8_t byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr + uint32_t addr = ERAM_ADDR(DPTR, 0xffff); + uint8_t byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by dptr + SET_ACC(byte); //Store to ACC } //MOVX A, @R0/@R1 /* 1: 1110 001i */ //(Move External Ram 8 bit address to A) OPHANDLER( movx_a_ir ) { - uint32_t addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1 - uint8_t byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by address - SET_ACC(byte); //Store to ACC + uint32_t addr = ERAM_ADDR(R_REG(r), 0xff); //Grab address by reading location pointed to by R0 or R1 + uint8_t byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by address + SET_ACC(byte); //Store to ACC } //MOVX @DPTR,A /* 1: 1111 0000 */ //(Move A to External Ram 16 bit address) OPHANDLER( movx_idptr_a ) { -// DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR - uint32_t addr = ERAM_ADDR(DPTR, 0xFFFF); - DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address pointed to by DPTR +// DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR + uint32_t addr = ERAM_ADDR(DPTR, 0xffff); + DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address pointed to by DPTR } //MOVX @R0/@R1,A /* 1: 1111 001i */ //(Move A to External Ram 8 bit address) OPHANDLER( movx_ir_a ) { - uint32_t addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1 + uint32_t addr = ERAM_ADDR(R_REG(r), 0xff); //Grab address by reading location pointed to by R0 or R1 DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address } @@ -678,10 +681,10 @@ OPHANDLER( mul_ab ) { uint16_t result = ACC * B; //A gets lo bits, B gets hi bits of result - B = (uint8_t) ((result & 0xFF00) >> 8); - SET_ACC((uint8_t)(result & 0x00FF)); + B = (uint8_t)((result & 0xff00) >> 8); + SET_ACC((uint8_t)(result & 0x00ff)); //Set flags - SET_OV( ((result & 0x100) >> 8) ); //Set/Clear Overflow Flag if result > 255 + SET_OV((result & 0x100) >> 8); //Set/Clear Overflow Flag if result > 255 SET_CY(0); //Carry Flag always cleared } @@ -693,83 +696,83 @@ OPHANDLER( nop ) //ORL data addr, A /* 1: 0100 0010 */ OPHANDLER( orl_mem_a ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,data | ACC); //Set data address value to it's value Logical OR with ACC + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, data | ACC); //Set data address value to it's value Logical OR with ACC } //ORL data addr, #data /* 1: 0100 0011 */ OPHANDLER( orl_mem_byte ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t srcdata = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,srcdata | data); //Set data address value to it's value Logical OR with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t srcdata = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, srcdata | data); //Set data address value to it's value Logical OR with Data } //ORL A, #data /* 1: 0100 0100 */ OPHANDLER( orl_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data + uint8_t data = ROP_ARG(PC++); //Grab data + SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data } //ORL A, data addr /* 1: 0100 0101 */ OPHANDLER( orl_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data } //ORL A, @RO/@R1 /* 1: 0100 011i */ OPHANDLER( orl_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to - SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data } //ORL A, RO to R7 /* 1: 0100 1rrr */ OPHANDLER( orl_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data + uint8_t data = R_REG(r); //Grab data from R0 - R7 + SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data } //ORL C, bit addr /* 1: 0111 0010 */ OPHANDLER( orl_c_bitaddr ) { int cy = GET_CY; - uint8_t addr = ROP_ARG(PC++); //Grab bit address - uint8_t bit = BIT_R(addr); //Grab bit data from bit address - SET_CY( (cy | bit) ); //Set Carry flag to Carry Flag Value Logical OR with Bit + uint8_t addr = ROP_ARG(PC++); //Grab bit address + uint8_t bit = BIT_R(addr); //Grab bit data from bit address + SET_CY(cy | bit); //Set Carry flag to Carry Flag Value Logical OR with Bit } //ORL C, /bit addr /* 1: 1010 0000 */ OPHANDLER( orl_c_nbitaddr ) { int cy = GET_CY; - uint8_t addr = ROP_ARG(PC++); //Grab bit address - uint8_t bit = BIT_R(addr); //Grab bit data from bit address - bit = ((~bit)&1); //Complement bit - SET_CY( (cy | bit) ); //Set Carry flag to Carry Flag Value Logical OR with Complemented Bit + uint8_t addr = ROP_ARG(PC++); //Grab bit address + uint8_t bit = BIT_R(addr); //Grab bit data from bit address + bit = (~bit & 1); //Complement bit + SET_CY(cy | bit); //Set Carry flag to Carry Flag Value Logical OR with Complemented Bit } //POP data addr /* 1: 1101 0000 */ OPHANDLER( pop ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t addr = ROP_ARG(PC++); //Grab data address IRAM_W(addr, IRAM_IR(SP)); //Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack //IRAM_IW(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - doesn't work, sfr's are not restored this way and it's not an indirect access anyway - SP = SP-1; //Decrement SP + SP = SP - 1; //Decrement SP } //PUSH data addr /* 1: 1100 0000 */ OPHANDLER( push ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t tmpSP = SP+1; //Grab and Increment Stack Pointer - SP = tmpSP; // "" + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t tmpSP = SP + 1; //Grab and Increment Stack Pointer + SP = tmpSP; // "" IRAM_IW(tmpSP, IRAM_R(addr)); //Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway } @@ -791,8 +794,8 @@ OPHANDLER( rl_a ) { //Left Shift A, Bit 7 carries to Bit 0 int carry = ((ACC & 0x80) >> 7); - int data = (ACC<<1) & 0xfe; - SET_ACC( data | carry); + int data = (ACC << 1) & 0xfe; + SET_ACC(data | carry); } //RLC A /* 1: 0011 0011 */ @@ -800,8 +803,8 @@ OPHANDLER( rlc_a ) { //Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC int carry = ((ACC & 0x80) >> 7); - int data = ((ACC<<1) & 0xfe) | GET_CY; - SET_ACC( data); + int data = ((ACC << 1) & 0xfe) | GET_CY; + SET_ACC(data); SET_CY(carry); } @@ -810,8 +813,8 @@ OPHANDLER( rr_a ) { //Right Shift A, Bit 0 carries to Bit 7 int carry = ((ACC & 1) << 7); - int data = (ACC>>1) & 0x7f; - SET_ACC( data | carry); + int data = (ACC >> 1) & 0x7f; + SET_ACC(data | carry); } //RRC A /* 1: 0001 0011 */ @@ -819,37 +822,38 @@ OPHANDLER( rrc_a ) { //Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag int carry = (ACC & 1); - int data = ((ACC>>1) & 0x7f) | (GET_CY<<7); - SET_ACC( data); + int data = ((ACC >> 1) & 0x7f) | (GET_CY << 7); + SET_ACC(data); SET_CY(carry); } //SETB C /* 1: 1101 0011 */ OPHANDLER( setb_c ) { - SET_CY(1); //Set Carry Flag + //Set Carry Flag + SET_CY(1); } //SETB bit addr /* 1: 1101 0010 */ OPHANDLER( setb_bitaddr ) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,1); //Set Bit at Bit Address + uint8_t addr = ROP_ARG(PC++); //Grab bit address + BIT_W(addr, 1); //Set Bit at Bit Address } //SJMP code addr /* 1: 1000 0000 */ OPHANDLER( sjmp ) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address PC = PC + rel_addr; //Update PC } //SUBB A, #data /* 1: 1001 0100 */ OPHANDLER( subb_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator - DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator + DO_SUB_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } @@ -857,28 +861,28 @@ OPHANDLER( subb_a_byte ) //SUBB A, data addr /* 1: 1001 0101 */ OPHANDLER( subb_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator - DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator + DO_SUB_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //SUBB A, @R0/@R1 /* 1: 1001 011i */ OPHANDLER( subb_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 - uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator - DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator + DO_SUB_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //SUBB A, R0 to R7 /* 1: 1001 1rrr */ OPHANDLER( subb_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator - DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags + uint8_t data = R_REG(r); //Grab data from R0 - R7 + uint8_t result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator + DO_SUB_FLAGS(ACC, data, GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } @@ -888,34 +892,34 @@ OPHANDLER( swap_a ) uint8_t a_nib_lo, a_nib_hi; a_nib_hi = (ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi a_nib_lo = (ACC & 0xf0) >> 4; //Grab hi byte of ACC and move to lo - SET_ACC( a_nib_hi | a_nib_lo); + SET_ACC(a_nib_hi | a_nib_lo); } //XCH A, data addr /* 1: 1100 0101 */ OPHANDLER( xch_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data - uint8_t oldACC = ACC; //Hold value of ACC - SET_ACC(data); //Sets ACC to data - IRAM_W(addr,oldACC); //Sets data address to old value of ACC + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data + uint8_t oldACC = ACC; //Hold value of ACC + SET_ACC(data); //Sets ACC to data + IRAM_W(addr, oldACC); //Sets data address to old value of ACC } //XCH A, @RO/@R1 /* 1: 1100 011i */ OPHANDLER( xch_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 - uint8_t oldACC = ACC; //Hold value of ACC - SET_ACC(data); //Sets ACC to data - IRAM_IW(R_REG(r),oldACC); //Sets data address to old value of ACC + uint8_t data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 + uint8_t oldACC = ACC; //Hold value of ACC + SET_ACC(data); //Sets ACC to data + IRAM_IW(R_REG(r), oldACC); //Sets data address to old value of ACC } //XCH A, RO to R7 /* 1: 1100 1rrr */ OPHANDLER( xch_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0-R7 - uint8_t oldACC = ACC; //Hold value of ACC - SET_ACC(data); //Sets ACC to data + uint8_t data = R_REG(r); //Grab data from R0-R7 + uint8_t oldACC = ACC; //Hold value of ACC + SET_ACC(data); //Sets ACC to data SET_REG(r, oldACC); //Sets data address to old value of ACC } @@ -923,60 +927,60 @@ OPHANDLER( xch_a_r ) OPHANDLER( xchd_a_ir ) { uint8_t acc, ir_data; - ir_data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 - acc = ACC; //Grab ACC value - SET_ACC( (acc & 0xf0) | (ir_data & 0x0f) ); //Set ACC to lower nibble of data pointed to by R0 or R1 - IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f) ); //Set data pointed to by R0 or R1 to lower nibble of ACC + ir_data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 + acc = ACC; //Grab ACC value + SET_ACC((acc & 0xf0) | (ir_data & 0x0f)); //Set ACC to lower nibble of data pointed to by R0 or R1 + IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f)); //Set data pointed to by R0 or R1 to lower nibble of ACC } //XRL data addr, A /* 1: 0110 0010 */ OPHANDLER( xrl_mem_a ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,data ^ ACC); //Set data address value to it's value Logical XOR with ACC + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, data ^ ACC); //Set data address value to it's value Logical XOR with ACC } //XRL data addr, #data /* 1: 0110 0011 */ OPHANDLER( xrl_mem_byte ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = ROP_ARG(PC++); //Grab data - uint8_t srcdata = IRAM_R(addr); //Grab data from data address - IRAM_W(addr,srcdata ^ data); //Set data address value to it's value Logical XOR with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t srcdata = IRAM_R(addr); //Grab data from data address + IRAM_W(addr, srcdata ^ data); //Set data address value to it's value Logical XOR with Data } //XRL A, #data /* 1: 0110 0100 */ OPHANDLER( xrl_a_byte ) { - uint8_t data = ROP_ARG(PC++); //Grab data - SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data + uint8_t data = ROP_ARG(PC++); //Grab data + SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data } //XRL A, data addr /* 1: 0110 0101 */ OPHANDLER( xrl_a_mem ) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address - SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data + uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t data = IRAM_R(addr); //Grab data from data address + SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data } //XRL A, @R0/@R1 /* 1: 0110 011i */ OPHANDLER( xrl_a_ir ) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to - SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data + uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data } //XRL A, R0 to R7 /* 1: 0110 1rrr */ OPHANDLER( xrl_a_r ) { - uint8_t data = R_REG(r); //Grab data from R0 - R7 - SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data + uint8_t data = R_REG(r); //Grab data from R0 - R7 + SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data } //illegal opcodes OPHANDLER( illegal ) { - LOG(("i8051 '%s': illegal opcode at 0x%03x: %02x\n", tag(), PC-1, r)); + LOG("illegal opcode at 0x%03x: %02x\n", PC-1, r); } |