// license:BSD-3-Clause // copyright-holders:Olivier Galibert, R. Belmont, hap /* Panasonic MN10200 emulator Written by Olivier Galibert MAME conversion by R. Belmont */ #ifndef MAME_CPU_MN10200_MN10200_H #define MAME_CPU_MN10200_MN10200_H #pragma once enum { MN10200_PORT0 = 0, MN10200_PORT1, MN10200_PORT2, MN10200_PORT3, MN10200_PORT4 }; enum { MN10200_IRQ0 = 0, MN10200_IRQ1, MN10200_IRQ2, MN10200_IRQ3, MN10200_MAX_EXT_IRQ }; class mn10200_device : public cpu_device { public: // configuration helpers template auto read_port() { return m_read_port[Port].bind(); } template auto write_port() { return m_write_port[Port].bind(); } uint8_t io_control_r(offs_t offset); void io_control_w(offs_t offset, uint8_t data); void mn1020012a_internal_map(address_map &map); protected: static constexpr unsigned MN10200_NUM_PRESCALERS = 2; static constexpr unsigned MN10200_NUM_TIMERS_8BIT = 10; static constexpr unsigned MN10200_NUM_IRQ_GROUPS = 31; // construction/destruction mn10200_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program); // device-level overrides virtual void device_start() override; virtual void device_reset() override; // device_execute_interface overrides virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 2 - 1) / 2; } // internal /2 divider virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 2); } // internal /2 divider virtual uint32_t execute_min_cycles() const noexcept override { return 1; } virtual uint32_t execute_max_cycles() const noexcept override { return 13+7; } // max opcode cycles + interrupt duration virtual uint32_t execute_input_lines() const noexcept override { return 4; } virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; // device_memory_interface overrides virtual space_config_vector memory_space_config() const override; // device_state_interface overrides virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides virtual std::unique_ptr create_disassembler() override; private: address_space_config m_program_config; address_space *m_program; // i/o handlers devcb_read8::array<5> m_read_port; devcb_write8::array<5> m_write_port; int m_cycles; // The UINT32s are really UINT24 uint32_t m_pc; uint32_t m_d[4]; uint32_t m_a[4]; uint16_t m_psw; uint16_t m_mdr; // interrupts void take_irq(int level, int group); void check_irq(); void check_ext_irq(); uint8_t m_icrl[MN10200_NUM_IRQ_GROUPS]; uint8_t m_icrh[MN10200_NUM_IRQ_GROUPS]; uint8_t m_nmicr; uint8_t m_iagr; uint8_t m_extmdl; uint8_t m_extmdh; bool m_possible_irq; // timers void refresh_timer(int tmr); void refresh_all_timers(); int timer_tick_simple(int tmr); TIMER_CALLBACK_MEMBER( simple_timer_cb ); attotime m_sysclock_base; emu_timer *m_timer_timers[MN10200_NUM_TIMERS_8BIT]; struct { uint8_t mode; uint8_t base; uint8_t cur; } m_simple_timer[MN10200_NUM_TIMERS_8BIT]; struct { uint8_t mode; uint8_t base; uint8_t cur; } m_prescaler[MN10200_NUM_PRESCALERS]; // dma struct { uint32_t adr; uint32_t count; uint16_t iadr; uint8_t ctrll; uint8_t ctrlh; uint8_t irq; } m_dma[8]; // serial struct { uint8_t ctrll; uint8_t ctrlh; uint8_t buf; uint8_t recv; } m_serial[2]; // ports uint8_t m_pplul; uint8_t m_ppluh; uint8_t m_p3md; uint8_t m_p4; struct { uint8_t out; uint8_t dir; } m_port[4]; // internal read/write inline uint8_t read_arg8(uint32_t address) { return m_program->read_byte(address); } inline uint16_t read_arg16(uint32_t address) { return m_program->read_byte(address) | m_program->read_byte(address + 1) << 8; } inline uint32_t read_arg24(uint32_t address) { return m_program->read_byte(address) | m_program->read_byte(address + 1) << 8 | m_program->read_byte(address + 2) << 16; } inline uint8_t read_mem8(uint32_t address) { return m_program->read_byte(address); } inline uint16_t read_mem16(uint32_t address) { return m_program->read_word(address & ~1); } inline uint32_t read_mem24(uint32_t address) { return m_program->read_word(address & ~1) | m_program->read_byte((address & ~1) + 2) << 16; } inline void write_mem8(uint32_t address, uint8_t data) { m_program->write_byte(address, data); } inline void write_mem16(uint32_t address, uint16_t data) { m_program->write_word(address & ~1, data); } inline void write_mem24(uint32_t address, uint32_t data) { m_program->write_word(address & ~1, data); m_program->write_byte((address & ~1) + 2, data >> 16); } inline void change_pc(uint32_t pc) { m_pc = pc & 0xffffff; } // opcode helpers void illegal(uint8_t prefix, uint8_t op); uint32_t do_add(uint32_t a, uint32_t b, uint32_t c = 0); uint32_t do_sub(uint32_t a, uint32_t b, uint32_t c = 0); void test_nz16(uint16_t v); void do_jsr(uint32_t to, uint32_t ret); void do_branch(int condition = 1); }; class mn1020012a_device : public mn10200_device { public: mn1020012a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; DECLARE_DEVICE_TYPE(MN1020012A, mn1020012a_device) #endif // MAME_CPU_MN10200_MN10200_H