diff options
author | 2017-06-27 04:01:05 +1000 | |
---|---|---|
committer | 2017-06-27 04:25:18 +1000 | |
commit | 5ada035d175828c577d5912033ba2ce73f872055 (patch) | |
tree | f5bc7c07686172c7bdb49575fe5d2070cea4bcc0 /src/devices/cpu/mcs40/mcs40.h | |
parent | 5ced18cf724ffd9d0e86bd7b1151cfbc61192b7a (diff) |
Rewrote 4004 core and disassembler:
* Renamed to MCS-40.
* Emulated 8-clock instruction cycle, interruptible at any point.
* Converted TEST input to an input line.
* Added SYNC and CM output lines.
* Added support for 4040 CY output, logical operations, extended registers, ROM banking and disassembly.
* Made I/O space mapping more flexible to support the variety of peripherals available.
* Notable missing features are 4040 interrupt and halt, and "program memory" space.
Diffstat (limited to 'src/devices/cpu/mcs40/mcs40.h')
-rw-r--r-- | src/devices/cpu/mcs40/mcs40.h | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/src/devices/cpu/mcs40/mcs40.h b/src/devices/cpu/mcs40/mcs40.h new file mode 100644 index 00000000000..fe7c9e3352e --- /dev/null +++ b/src/devices/cpu/mcs40/mcs40.h @@ -0,0 +1,307 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#ifndef MAME_CPU_I4004_I4004_H +#define MAME_CPU_I4004_I4004_H + +#pragma once + + +/*********************************************************************** + CONSTANTS +***********************************************************************/ + +enum +{ + I4004_A = 1, + I4004_R01, I4004_R23, I4004_R45, I4004_R67, I4004_R89, I4004_RAB, I4004_RCD, I4004_REF, + I4040_RGH, I4040_RIJ, I4040_RKL, I4040_RMN, + I4004_ADDR0, I4004_ADDR1, I4004_ADDR2, I4004_ADDR3, + I4040_ADDR4, I4040_ADDR5, I4040_ADDR6, I4040_ADDR7, + I4004_CR, I4004_RC, I4004_RCN, + I4040_SRC +}; + +enum +{ + I4004_TEST_LINE = 0, + + I4040_TEST_LINE = I4004_TEST_LINE, + I4040_INT_LINE = 1, + I4040_STP_LINE = 2 +}; + + + +/*********************************************************************** + CONFIGURATION MACROS +***********************************************************************/ + +#define MCFG_I4004_SYNC_CB(obj) \ + devcb = &i4004_cpu_device::set_sync_cb(*device, DEVCB_##obj); + +#define MCFG_I4004_CM_ROM_CB(obj) \ + devcb = &i4004_cpu_device::set_cm_rom_cb(*device, DEVCB_##obj); + +#define MCFG_I4004_CM_RAM0_CB(obj) \ + devcb = &i4004_cpu_device::set_cm_ram_cb<0>(*device, DEVCB_##obj); + +#define MCFG_I4004_CM_RAM1_CB(obj) \ + devcb = &i4004_cpu_device::set_cm_ram_cb<1>(*device, DEVCB_##obj); + +#define MCFG_I4004_CM_RAM2_CB(obj) \ + devcb = &i4004_cpu_device::set_cm_ram_cb<2>(*device, DEVCB_##obj); + +#define MCFG_I4004_CM_RAM3_CB(obj) \ + devcb = &i4004_cpu_device::set_cm_ram_cb<3>(*device, DEVCB_##obj); + + +#define MCFG_I4040_SYNC_CB(obj) \ + devcb = &i4040_cpu_device::set_sync_cb(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_ROM0_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_rom_cb<0>(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_ROM1_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_rom_cb<1>(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_RAM0_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_ram_cb<0>(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_RAM1_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_ram_cb<1>(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_RAM2_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_ram_cb<2>(*device, DEVCB_##obj); + +#define MCFG_I4040_CM_RAM3_CB(obj) \ + devcb = &i4040_cpu_device::set_cm_ram_cb<3>(*device, DEVCB_##obj); + +#define MCFG_I4040_CY_CB(obj) \ + devcb = &i4040_cpu_device::set_cy_cb(*device, DEVCB_##obj); + + + +/*********************************************************************** + TYPE DEFINITIONS +***********************************************************************/ + +class mcs40_cpu_device_base : public cpu_device +{ +protected: + enum class cycle { OP, IM, IN }; + + mcs40_cpu_device_base( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *owner, + uint32_t clock, + bool extended_cm, + unsigned rom_width, + unsigned stack_ptr_mask, + unsigned index_reg_cnt, + unsigned cr_mask); + + // device_t implementation + void device_start() override; + void device_reset() override; + + // device_execute_interface implementation + virtual void execute_run() override; + + // device_memory_interface configuration + virtual address_space_config const *memory_space_config(address_spacenum spacenum) const override; + + // device_state_interface implementation + virtual void state_import(device_state_entry const &entry) override; + virtual void state_export(device_state_entry const &entry) override; + virtual void state_string_export(device_state_entry const &entry, std::string &str) const override; + + // device_disasm_interface implementation + virtual u32 disasm_min_opcode_bytes() const override; + virtual u32 disasm_max_opcode_bytes() const override; + + // instruction execution + virtual bool is_io_op(u8 opr) = 0; + virtual cycle do_cycle1(u8 opr, u8 opa) = 0; + virtual void do_cycle2(u8 opr, u8 opa, u8 arg) = 0; + virtual void do_io(u8 opr, u8 opa) = 0; + + // register access + u8 get_a() const; + u8 get_c() const; + void set_a(u8 val); + void set_c(u8 val); + void set_a_c(u8 val); + void set_pc(u16 addr, u16 mask); + void push_pc(); + void pop_pc(); + u8 &index_reg_pair(unsigned n); + u8 get_index_reg(unsigned n); + void set_index_reg(unsigned n, u8 val); + void set_index_reg_bank(u8 val); + + // I/O control + void set_rom_addr(u16 addr, u16 mask); + u8 get_cr(); + void set_cr(u8 val, u8 mask); + void set_pending_rom_bank(u8 val); + void set_rc(u8 val); + u8 read_memory(); + void write_memory(u8 val); + u8 read_status(); + void write_status(u8 val); + u8 read_rom_port(); + void write_rom_port(u8 val); + void write_memory_port(u8 val); + + // input lines + bool get_test(); + void set_test(int state); + + // configuration helpers + template <typename Obj> devcb_base &set_sync_cb(Obj &&cb) + { return m_sync_cb.set_callback(std::forward<Obj>(cb)); } + template <unsigned N, typename Obj> devcb_base &set_cm_rom_cb(Obj &&cb) + { return m_cm_rom_cb[N].set_callback(std::forward<Obj>(cb)); } + template <unsigned N, typename Obj> devcb_base &set_cm_ram_cb(Obj &&cb) + { return m_cm_ram_cb[N].set_callback(std::forward<Obj>(cb)); } + template <typename Obj> devcb_base &set_cy_cb(Obj &&cb) + { return m_cy_cb.set_callback(std::forward<Obj>(cb)); } + +private: + enum class phase { A1, A2, A3, M1, M2, X1, X2, X3 }; + + // internal helpers + u16 &pc() { return m_addr_stack[m_stack_ptr]; } + u16 rom_bank() const { return BIT(m_cr, 3) ? 0x1000U : 0x0000U; } + void update_cm_rom(u8 val); + void update_cm_ram(u8 val); + void update_cy(u8 val); + + // address spaces + address_space_config m_program_config, m_data_config, m_io_config; + address_space *m_program, *m_data, *m_io; + direct_read_data *m_direct; + + // output callbacks + devcb_write_line m_sync_cb; + devcb_write_line m_cm_rom_cb[2], m_cm_ram_cb[4]; + devcb_write_line m_cy_cb; + + // configuration + bool const m_extended_cm; + u8 const m_stack_ptr_mask; + u8 const m_index_reg_cnt; + u8 const m_cr_mask; + u16 const m_pc_mask; + + // machine/instruction phase + int m_icount; + phase m_phase; + cycle m_cycle; + bool m_io_pending; + + // instruction ROM fetch/decode + u16 m_rom_bank, m_rom_addr; + u8 m_opr, m_opa, m_arg; + + // ALU registers + u8 m_a, m_c; + + // address stack + std::unique_ptr<u16 []> m_addr_stack; + u8 m_stack_ptr; + + // index registers + std::unique_ptr<u8 []> m_index_regs; + u8 m_index_reg_bank; + + // RAM/I/O control + u8 m_cr, m_pending_cr3, m_latched_rc, m_new_rc, m_src; + bool m_rc_pending; + + // input/output lines + int m_test; + u8 m_cm_rom, m_cm_ram, m_cy; + + // state export/import + u16 m_pc, m_pcbase; + u8 m_genflags; +}; + + +class i4004_cpu_device : public mcs40_cpu_device_base +{ +public: + // configuration helpers + template <typename Obj> static devcb_base &set_sync_cb(device_t &device, Obj &&cb) + { return downcast<i4004_cpu_device &>(device).set_sync_cb(std::forward<Obj>(cb)); } + template <typename Obj> static devcb_base &set_cm_rom_cb(device_t &device, Obj &&cb) + { return downcast<i4004_cpu_device &>(device).set_cm_rom_cb<0>(std::forward<Obj>(cb)); } + template <unsigned N, typename Obj> static devcb_base &set_cm_ram_cb(device_t &device, Obj &&cb) + { return downcast<i4004_cpu_device &>(device).set_cm_ram_cb<N>(std::forward<Obj>(cb)); } + + i4004_cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + using mcs40_cpu_device_base::mcs40_cpu_device_base; + + // device_execute_interface implementation + u32 execute_input_lines() const override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_disasm_interface implementation + virtual offs_t disasm_disassemble( + std::ostream &stream, + offs_t pc, + uint8_t const *oprom, + uint8_t const *opram, + uint32_t options) override; + + // mcs40_cpu_device_base implementation + virtual bool is_io_op(u8 opr) override; + virtual cycle do_cycle1(u8 opr, u8 opa) override; + virtual void do_cycle2(u8 opr, u8 opa, u8 arg) override; + virtual void do_io(u8 opr, u8 opa) override; +}; + + +class i4040_cpu_device : public i4004_cpu_device +{ +public: + // configuration helpers + template <typename Obj> static devcb_base &set_sync_cb(device_t &device, Obj &&cb) + { return downcast<i4040_cpu_device &>(device).set_sync_cb(std::forward<Obj>(cb)); } + template <unsigned N, typename Obj> static devcb_base &set_cm_rom_cb(device_t &device, Obj &&cb) + { return downcast<i4040_cpu_device &>(device).set_cm_rom_cb<N>(std::forward<Obj>(cb)); } + template <unsigned N, typename Obj> static devcb_base &set_cm_ram_cb(device_t &device, Obj &&cb) + { return downcast<i4040_cpu_device &>(device).set_cm_ram_cb<N>(std::forward<Obj>(cb)); } + template <typename Obj> static devcb_base &set_cy_cb(device_t &device, Obj &&cb) + { return downcast<i4040_cpu_device &>(device).set_cy_cb(std::forward<Obj>(cb)); } + + i4040_cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + // device_disasm_interface implementation + virtual offs_t disasm_disassemble( + std::ostream &stream, + offs_t pc, + uint8_t const *oprom, + uint8_t const *opram, + uint32_t options) override; + + // mcs40_cpu_device_base implementation + virtual cycle do_cycle1(u8 opr, u8 opa) override; +}; + + + +/*********************************************************************** + DEVICE TYPE DECLARATIONS +***********************************************************************/ + +DECLARE_DEVICE_TYPE(I4004, i4004_cpu_device) +DECLARE_DEVICE_TYPE(I4040, i4040_cpu_device) + +#endif // MAME_CPU_I4004_I4004_H |