mame/src/devices/cpu/mn10200/mn10200.h
2020-03-31 18:58:53 +02:00

201 lines
5.3 KiB
C++

// 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 <std::size_t Port> auto read_port() { return m_read_port[Port].bind(); }
template <std::size_t Port> 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<util::disasm_interface> 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