summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mcs51/mcs51.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mcs51/mcs51.h')
-rw-r--r--src/devices/cpu/mcs51/mcs51.h313
1 files changed, 195 insertions, 118 deletions
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;
};