From 7d346689de53e02bfc8500025dcbb46e649cc948 Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Sun, 21 Aug 2022 00:33:41 +0100 Subject: Greatly improve Monon Color emulation (#10158) * added emulation of required/used AXC51 / AX208 extended operations * added preliminary emulation of required/used AXC51 / AX208 features * added support for many Monon specific features, such as the video controller * most games are playable, those not requiring a card/badge scanner to function at all are promoted * no music, as it's contained in a game specific MCU under a glob on each cart --- hash/monon_color.xml | 142 +-- scripts/src/bus.lua | 17 + scripts/src/cpu.lua | 1 + scripts/src/machine.lua | 12 + src/devices/bus/mononcol/carts.cpp | 13 + src/devices/bus/mononcol/carts.h | 11 + src/devices/bus/mononcol/rom.cpp | 37 + src/devices/bus/mononcol/rom.h | 55 + src/devices/bus/mononcol/slot.cpp | 157 +++ src/devices/bus/mononcol/slot.h | 133 +++ src/devices/cpu/axc51/axc51.cpp | 1109 ++++++++++++++------- src/devices/cpu/axc51/axc51.h | 509 ++++++---- src/devices/cpu/axc51/axc51dasm.cpp | 220 ++-- src/devices/cpu/axc51/axc51dasm.h | 6 +- src/devices/cpu/axc51/axc51extops.hxx | 694 +++++++++++++ src/devices/cpu/axc51/axc51ops.hxx | 700 +++++++------ src/devices/machine/generic_spi_flash.cpp | 199 ++++ src/devices/machine/generic_spi_flash.h | 83 ++ src/mame/mame.lst | 2 +- src/mame/mess.flt | 2 +- src/mame/misc/monon_color.cpp | 951 ++++++++++++++++++ src/mame/skeleton/monon_color.cpp | 160 --- src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp | 1 + src/mame/tvgames/st2302u_bbl_spi.cpp | 2 + 24 files changed, 3956 insertions(+), 1260 deletions(-) create mode 100644 src/devices/bus/mononcol/carts.cpp create mode 100644 src/devices/bus/mononcol/carts.h create mode 100644 src/devices/bus/mononcol/rom.cpp create mode 100644 src/devices/bus/mononcol/rom.h create mode 100644 src/devices/bus/mononcol/slot.cpp create mode 100644 src/devices/bus/mononcol/slot.h create mode 100644 src/devices/cpu/axc51/axc51extops.hxx create mode 100644 src/devices/machine/generic_spi_flash.cpp create mode 100644 src/devices/machine/generic_spi_flash.h create mode 100644 src/mame/misc/monon_color.cpp delete mode 100644 src/mame/skeleton/monon_color.cpp diff --git a/hash/monon_color.xml b/hash/monon_color.xml index eb55bbc04d7..fd7038a0912 100644 --- a/hash/monon_color.xml +++ b/hash/monon_color.xml @@ -4,8 +4,10 @@ license:CC0 --> - + - + Sài ěr hào: Zhànshén dòu hún - 2011 + 2014 M&D - - + + - + Luòkè wángguó-mófǎ zhèn - 2011 + 2014 M&D - - + + - + Jī jiǎ xuànfēng-gédòu dàshī (set 1) - 2011 + 2014 M&D - - + + - + Jī jiǎ xuànfēng-gédòu dàshī (set 2) - 2011 + 2014 M&D - - + + - + Shén pò-shīluò de yíjī - 2011 + 2014 M&D - - + + - + Sài ěr hào-néngyuán dà zuòzhàn - 2011 + 2014 M&D - - + + - + Gāngtiě xiá-yīngxióng fǎnjí zhàn - 2011 + 2014 M&D - - + + - + Jiāngshī lièrén - 2011 + 2014 M&D - + - + Luòkè wángguó-dà màoxiǎn - 2011 + 2014 M&D - + - + Luòkè wángguó-bīng zhī lán - 2011 + 2014 M&D - + - + Luòkè wángguó-hēi zhī yán - 2011 + 2014 M&D - + + Luòkè wángguó-kǎ pái zhàn jì - 2011 + 2015 M&D - + - + Kǎijiǎ yǒngshì dàluàn dòu - 2011 + 2015 M&D - + + + + + + + + Luòkè wángguó-wángzhě huīzhāng + 2015 + M&D + + + + - + Luójí pīn yī pīn - 2011 + 2015 M&D - - + + - + Xǐyángyáng yǔ huītàiláng-juézhàn miē xīng - 2011 + 2015 M&D - - + + - + Lóngzhū-wǔdào dàhuì - 2011 + 2015 M&D - + - + Yīngxióng liánméng-zhōngjí gédòu - 2011 + 2015 M&D - + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 80e275558a5..e193cac816d 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3272,6 +3272,23 @@ if (BUSES["MEGADRIVE"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/bus/generic/slot.h,BUSES["MONONCOL"] = true +--------------------------------------------------- + +if (BUSES["MONONCOL"]~=null) then + files { + MAME_DIR .. "src/devices/bus/mononcol/slot.cpp", + MAME_DIR .. "src/devices/bus/mononcol/slot.h", + MAME_DIR .. "src/devices/bus/mononcol/carts.cpp", + MAME_DIR .. "src/devices/bus/mononcol/carts.h", + MAME_DIR .. "src/devices/bus/mononcol/rom.cpp", + MAME_DIR .. "src/devices/bus/mononcol/rom.h", + } +end + + --------------------------------------------------- -- --@src/devices/bus/neogeo/slot.h,BUSES["NEOGEO"] = true diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 1f350423a33..b1b4de967be 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1109,6 +1109,7 @@ if CPUS["AXC51"] then MAME_DIR .. "src/devices/cpu/axc51/axc51.cpp", MAME_DIR .. "src/devices/cpu/axc51/axc51.h", MAME_DIR .. "src/devices/cpu/axc51/axc51ops.hxx", + MAME_DIR .. "src/devices/cpu/axc51/axc51extops.hxx", } end diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 0fb0e109de5..fb211d9c6b0 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1475,6 +1475,18 @@ if (MACHINES["GT913"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/machine/acorn_ioc.h,MACHINES["GENERIC_SPI_FLASH"] = true +-------------------------------------------------- + +if (MACHINES["GENERIC_SPI_FLASH"]~=null) then + files { + MAME_DIR .. "src/devices/machine/generic_spi_flash.cpp", + MAME_DIR .. "src/devices/machine/generic_spi_flash.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/hd63450.h,MACHINES["HD63450"] = true diff --git a/src/devices/bus/mononcol/carts.cpp b/src/devices/bus/mononcol/carts.cpp new file mode 100644 index 00000000000..cb34373c98a --- /dev/null +++ b/src/devices/bus/mononcol/carts.cpp @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli + +#include "emu.h" +#include "carts.h" +#include "rom.h" + + +device_slot_interface &mononcol_plain_slot(device_slot_interface &device) +{ + device.option_add_internal("rom", MONONCOL_ROM_PLAIN); + return device; +} diff --git a/src/devices/bus/mononcol/carts.h b/src/devices/bus/mononcol/carts.h new file mode 100644 index 00000000000..b1620c0d098 --- /dev/null +++ b/src/devices/bus/mononcol/carts.h @@ -0,0 +1,11 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli + +#ifndef MAME_BUS_MONONCOL_CARTS_H +#define MAME_BUS_MONONCOL_CARTS_H + +#pragma once + +device_slot_interface &mononcol_plain_slot(device_slot_interface &device); + +#endif // MAME_BUS_MONONCOL_CARTS_H diff --git a/src/devices/bus/mononcol/rom.cpp b/src/devices/bus/mononcol/rom.cpp new file mode 100644 index 00000000000..4bf78b9731d --- /dev/null +++ b/src/devices/bus/mononcol/rom.cpp @@ -0,0 +1,37 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli + +#include "emu.h" +#include "rom.h" + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +DEFINE_DEVICE_TYPE(MONONCOL_ROM_PLAIN, mononcol_rom_plain_device, "mononcol_rom_plain", "Monon Color ROM cartridge") + +void mononcol_rom_device::device_start() +{ +} + +mononcol_rom_device::mononcol_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock), device_mononcol_cart_interface(mconfig, *this) +{ +} + +mononcol_rom_plain_device::mononcol_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : mononcol_rom_device(mconfig, type, tag, owner, clock) + , m_spi(*this, "spi") +{ +} + +mononcol_rom_plain_device::mononcol_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mononcol_rom_plain_device(mconfig, MONONCOL_ROM_PLAIN, tag, owner, clock) +{ +} + + +void mononcol_rom_plain_device::device_add_mconfig(machine_config &config) +{ + GENERIC_SPI_FLASH(config, m_spi, 0); +} diff --git a/src/devices/bus/mononcol/rom.h b/src/devices/bus/mononcol/rom.h new file mode 100644 index 00000000000..23c24d4d1d4 --- /dev/null +++ b/src/devices/bus/mononcol/rom.h @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli +#ifndef MAME_BUS_MONONCOL_ROM_H +#define MAME_BUS_MONONCOL_ROM_H + +#pragma once + +#include "slot.h" + +#include "machine/generic_spi_flash.h" + +// ======================> mononcol_rom_device + +class mononcol_rom_device : public device_t, public device_mononcol_cart_interface +{ +protected: + // construction/destruction + mononcol_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; +}; + + +// ======================> mononcol_rom_plain_device + +class mononcol_rom_plain_device : public mononcol_rom_device +{ +public: + // construction/destruction + mononcol_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint8_t read() override { return m_spi->read(); } + DECLARE_WRITE_LINE_MEMBER(dir_w) override { m_spi->dir_w(state); } + void write(uint8_t data) override { m_spi->write(data); } + void set_ready() override { m_spi->set_ready(); } + void set_spi_region(uint8_t* region) override { m_spi->set_rom_ptr(region); } + void set_spi_size(size_t size) override { m_spi->set_rom_size(size); } + + +protected: + mononcol_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_add_mconfig(machine_config &config) override; + +private: + required_device m_spi; + +}; + +// device type definition +DECLARE_DEVICE_TYPE(MONONCOL_ROM_PLAIN, mononcol_rom_plain_device) + + +#endif // MAME_BUS_MONONCOL_ROM_H diff --git a/src/devices/bus/mononcol/slot.cpp b/src/devices/bus/mononcol/slot.cpp new file mode 100644 index 00000000000..4fc194d6376 --- /dev/null +++ b/src/devices/bus/mononcol/slot.cpp @@ -0,0 +1,157 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli + +#include "emu.h" +#include "slot.h" + +#define VERBOSE 0 +#include "logmacro.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(MONONCOL_CARTSLOT, mononcol_cartslot_device, "mononcol_cartslot", "Monon Color Cartridge Slot") + + +//************************************************************************** +// device_mononcol_cart_interface +//************************************************************************** + +device_mononcol_cart_interface::device_mononcol_cart_interface(machine_config const &mconfig, device_t &device) : + device_interface(device, "genslot"), + m_rom(nullptr), + m_rom_size(0) +{ +} + +device_mononcol_cart_interface::~device_mononcol_cart_interface() +{ +} + +void device_mononcol_cart_interface::rom_alloc(u32 size, int width, endianness_t endian) +{ + if (m_rom) + { + throw emu_fatalerror( + "%s: Request to allocate ROM when already allocated (allocated size %u, requested size %u)\n", + device().tag(), + m_rom_size, + size); + } + + std::string fulltag = device().subtag("^cart:rom"); + + device().logerror("Allocating %u byte ROM region with tag '%s' (width %d)\n", size, fulltag, width); + m_rom = device().machine().memory().region_alloc(fulltag, size, width, endian)->base(); + m_rom_size = size; + + if (!(m_rom_size && !(m_rom_size & (m_rom_size - 1)))) + { + fatalerror("m_rom_size is NOT a power of 2"); + } +} + + + +//************************************************************************** +// mononcol_cartslot_device +//************************************************************************** + +mononcol_cartslot_device::mononcol_cartslot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + device_rom_image_interface(mconfig, *this), + device_single_card_slot_interface(mconfig, *this), + m_cart(nullptr) +{ +} + + +mononcol_cartslot_device::mononcol_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mononcol_cartslot_device(mconfig, MONONCOL_CARTSLOT, tag, owner, clock) +{ +} + +mononcol_cartslot_device::~mononcol_cartslot_device() +{ +} + +void mononcol_cartslot_device::device_start() +{ + m_cart = get_card_device(); +} + + +/*------------------------------------------------- + call load + -------------------------------------------------*/ + +image_init_result mononcol_cartslot_device::call_load() +{ + if (m_cart) + { + u32 len = common_get_size("rom"); + + rom_alloc(len, 1, ENDIANNESS_LITTLE); + common_load_rom(get_rom_base(), len, "rom"); + + m_cart->set_spi_region(get_rom_base()); + m_cart->set_spi_size(get_rom_size()); + + return image_init_result::PASS; + } + + return image_init_result::PASS; +} + + + +/*------------------------------------------------- + get default card software + -------------------------------------------------*/ + +std::string mononcol_cartslot_device::get_default_card_software(get_default_card_software_hook &hook) const +{ + return software_get_default_slot("rom"); +} + + +/************************************************** + + Implementation + + **************************************************/ + + +/*------------------------------------------------- + common_get_size - it gets image file size both + for fullpath and for softlist + -------------------------------------------------*/ + +u32 mononcol_cartslot_device::common_get_size(char const *region) +{ + // if we are loading from softlist, you have to specify a region + assert(!loaded_through_softlist() || (region != nullptr)); + + return !loaded_through_softlist() ? length() : get_software_region_length(region); +} + +/*------------------------------------------------- + common_load_rom - it loads from image file both + for fullpath and for softlist + -------------------------------------------------*/ + +void mononcol_cartslot_device::common_load_rom(u8 *ROM, u32 len, char const *region) +{ + // basic sanity check + assert((ROM != nullptr) && (len > 0)); + + // if we are loading from softlist, you have to specify a region + assert(!loaded_through_softlist() || (region != nullptr)); + + if (!loaded_through_softlist()) + fread(ROM, len); + else + memcpy(ROM, get_software_region(region), len); +} diff --git a/src/devices/bus/mononcol/slot.h b/src/devices/bus/mononcol/slot.h new file mode 100644 index 00000000000..43cd23709df --- /dev/null +++ b/src/devices/bus/mononcol/slot.h @@ -0,0 +1,133 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli +#ifndef MAME_BUS_MONONCOL_SLOT_H +#define MAME_BUS_MONONCOL_SLOT_H + +#pragma once + +#include "imagedev/cartrom.h" + +#include + +/*************************************************************************** + TYPE DEFINITIONS + ***************************************************************************/ + +class device_mononcol_cart_interface : public device_interface +{ +public: + + // construction/destruction + virtual ~device_mononcol_cart_interface(); + + // reading and writing + virtual void rom_alloc(u32 size, int width, endianness_t end); + + u8 *get_rom_base() { return m_rom; } + u32 get_rom_size() { return m_rom_size; } + + virtual uint8_t read() = 0; + virtual DECLARE_WRITE_LINE_MEMBER(dir_w) = 0; + virtual void write(uint8_t data) = 0; + virtual void set_ready() = 0; + + virtual void set_spi_region(uint8_t* region) = 0; + virtual void set_spi_size(size_t size) = 0; + +protected: + device_mononcol_cart_interface(machine_config const &mconfig, device_t &device); + + // internal state + u8 *m_rom; + u32 m_rom_size; +}; + + +class mononcol_cartslot_device : public device_t, + public device_rom_image_interface, + public device_single_card_slot_interface +{ +public: + template + mononcol_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts) + : mononcol_cartslot_device(mconfig, tag, owner, u32(0)) + { + opts(*this); + set_fixed(false); + } + + mononcol_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); + + virtual ~mononcol_cartslot_device(); + + // device_image_interface implementation + virtual image_init_result call_load() override; + virtual bool is_reset_on_load() const noexcept override { return true; } + virtual char const *image_interface() const noexcept override { return "monon_color_cart"; } + virtual char const *file_extensions() const noexcept override { return "bin"; } + + // slot interface overrides + virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; + + u32 common_get_size(char const *region); + void common_load_rom(u8 *ROM, u32 len, char const *region); + + virtual void rom_alloc(u32 size, int width, endianness_t end) { if (m_cart) m_cart->rom_alloc(size, width, end); } + + u8* get_rom_base() + { + if (!m_cart) + return nullptr; + + return m_cart->get_rom_base(); + } + u32 get_rom_size() + { + if (!m_cart) + return 0U; + + return m_cart->get_rom_size(); + } + + uint8_t read() + { + return m_cart->read(); + } + + DECLARE_WRITE_LINE_MEMBER(dir_w) + { + m_cart->dir_w(state); + } + + void set_ready() + { + m_cart->set_ready(); + } + + void write(uint8_t data) + { + m_cart->write(data); + } + + void set_spi_region(uint8_t* region) { m_cart->set_spi_region(region); } + void set_spi_size(size_t size) { m_cart->set_spi_size(size); } + + +protected: + mononcol_cartslot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); + + // device-level overrides + virtual void device_start() override ATTR_COLD; + + device_mononcol_cart_interface *m_cart; + + virtual const char *image_type_name() const noexcept override { return "cartridge"; } + virtual const char *image_brief_type_name() const noexcept override { return "cart"; } + +}; + + +// device type definition +DECLARE_DEVICE_TYPE(MONONCOL_CARTSLOT, mononcol_cartslot_device) + +#endif // MAME_BUS_MONONCOL_SLOT_H diff --git a/src/devices/cpu/axc51/axc51.cpp b/src/devices/cpu/axc51/axc51.cpp index d0bb3b1ec9d..c2751ac53ff 100644 --- a/src/devices/cpu/axc51/axc51.cpp +++ b/src/devices/cpu/axc51/axc51.cpp @@ -1,13 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud - -/* - This is currently mostly copied from the mcs51 core - but as the axc51 has many differences, it will eventually - diverge more greatly. For now assume a lot of what is here - is still incorrect. - -*/ +// copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud, David Haywood /***************************************************************************** @@ -28,9 +20,19 @@ #include "axc51.h" #include "axc51dasm.h" -#define VERBOSE 0 +#define LOG_UNSORTED (1U << 1) +#define LOG_PORTS (1U << 2) +#define LOG_UNHANDLED (1U << 3) +#define LOG_UNHANDLED_XSFR (1U << 4) + + + +#define VERBOSE (0) + +#include "logmacro.h" + + -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) /*************************************************************************** CONSTANTS @@ -46,45 +48,64 @@ DEFINE_DEVICE_TYPE(AX208P, ax208p_cpu_device, "ax208p", "AppoTech AX208 (AXC51-C void axc51base_cpu_device::program_internal(address_map &map) { + map(0x4000, 0x6fff).ram().share("mainram"); } void axc51base_cpu_device::data_internal(address_map &map) { - map(0x0000, 0x00ff).ram().share("scratchpad"); - map(0x0100, 0x01ff).ram().share("sfr_ram"); /* SFR */ + map(0x0000, 0x03ff).ram().share("scratchpad"); // DRAM? } void ax208_cpu_device::ax208_internal_program_mem(address_map &map) { + map(0x4000, 0x6fff).ram().share("mainram"); map(0x8000, 0x9fff).rom().region("rom", 0); // this can only be read from code running within the same region } +void axc51base_cpu_device::io_internal(address_map& map) +{ + map(0x0000, 0x03ff).ram().share("scratchpad"); + map(0x3000, 0x3fff).rw(FUNC(axc51base_cpu_device::xsfr_read), FUNC(axc51base_cpu_device::xsfr_write)); + map(0x4000, 0x6fff).ram().share("mainram"); -axc51base_cpu_device::axc51base_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) + map(0x7000, 0x77ff).ram(); // JPEG RAM +} + + +axc51base_cpu_device::axc51base_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, address_map_constructor io_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, program_map) - , m_data_config("data", ENDIANNESS_LITTLE, 8, 9, 0, data_map) - , m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0) + , m_data_config("data", ENDIANNESS_LITTLE, 8, 11, 0, data_map) + , m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0, io_map) , m_pc(0) , m_features(features) , m_rom_size(program_width > 0 ? 1 << program_width : 0) , m_num_interrupts(5) - , m_sfr_ram(*this, "sfr_ram") , m_scratchpad(*this, "scratchpad") + , m_mainram(*this, "mainram") , m_port_in_cb(*this) , m_port_out_cb(*this) - , m_serial_tx_cb(*this) - , m_serial_rx_cb(*this) + , m_dac_out_cb(*this) + , m_spi_in_cb(*this) + , m_spi_out_cb(*this) + , m_spi_out_dir_cb(*this) , m_rtemp(0) { - /* default to standard cmos interfacing */ - for (auto & elem : m_forced_inputs) - elem = 0; + for (int i = 0; i < 0x80; i++) + { + m_sfr_regs[i] = 0x00; + m_xsfr_regs[i] = 0x00; + } + + m_uid[0] = 0x00; // not used? + m_uid[1] = 0x00; // used in RTC / USB code? + m_uid[2] = 0x91; // used in crypt code? + m_uid[3] = 0xb5; } axc51base_cpu_device::axc51base_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) - : axc51base_cpu_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(axc51base_cpu_device::program_internal), this), address_map_constructor(FUNC(axc51base_cpu_device::data_internal), this), program_width, data_width, features) + : axc51base_cpu_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(axc51base_cpu_device::program_internal), this), address_map_constructor(FUNC(axc51base_cpu_device::data_internal), this), address_map_constructor(FUNC(axc51base_cpu_device::io_internal), this), program_width, data_width, features) { } @@ -98,148 +119,143 @@ device_memory_interface::space_config_vector axc51base_cpu_device::memory_space_ }; } +/* Read/Write a byte from/to the Internal RAM indirectly */ +/* (called from indirect addressing) */ +/* these go through DBASE register on axc51 (at least stack accesses) */ +uint8_t axc51base_cpu_device::iram_indirect_read(offs_t a) { return m_data.read_byte((m_sfr_regs[SFR_DBASE] * 4) + a); } +void axc51base_cpu_device::iram_indirect_write(offs_t a, uint8_t d) { m_data.write_byte((m_sfr_regs[SFR_DBASE] * 4) + a, d); } /*************************************************************************** - MACROS + SHORTCUTS ***************************************************************************/ -/* Read Opcode/Opcode Arguments from Program Code */ -#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) - -/* 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) - -/* Read/Write a byte from/to the Internal RAM */ - -#define IRAM_R(a) iram_read(a) -#define IRAM_W(a, d) iram_write(a, d) - -/* Read/Write a byte from/to the Internal RAM indirectly */ -/* (called from indirect addressing) */ -uint8_t axc51base_cpu_device::iram_iread(offs_t a) { return m_data.read_byte(a); } -void axc51base_cpu_device::iram_iwrite(offs_t a, uint8_t d) { m_data.write_byte(a, d); } +/* SFR Registers - These are accessed directly for speed on read */ +/* Read accessors */ -#define IRAM_IR(a) iram_iread(a) -#define IRAM_IW(a, d) iram_iwrite(a, d) +#define SET_SFR_A(a,v) do { m_sfr_regs[a] = (v); } while (0) -/* Form an Address to Read/Write to External RAM indirectly */ -/* (called from indirect addressing) */ -#define ERAM_ADDR(a,m) external_ram_iaddr(a,m) +#define ACC m_sfr_regs[SFR_ACC] +#define PSW m_sfr_regs[SFR_PSW] -/* Read/Write a bit from Bit Addressable Memory */ -#define BIT_R(a) bit_address_r(a) -#define BIT_W(a,v) bit_address_w(a, v) +#define P0 ((const uint8_t) m_sfr_regs[SFR_P0]) +#define P1 ((const uint8_t) m_sfr_regs[SFR_P1]) +#define P2 ((const uint8_t) m_sfr_regs[SFR_P2]) +#define P3 ((const uint8_t) m_sfr_regs[SFR_P3]) +#define P4 ((const uint8_t) m_sfr_regs[SFR_P4]) +#define SP m_sfr_regs[SFR_SP] +#define DPL0 m_sfr_regs[SFR_DPL0] +#define DPH0 m_sfr_regs[SFR_DPH0] +#define PCON m_sfr_regs[SFR_PCON] +#define IE m_sfr_regs[SFR_IE] +#define IE1 m_sfr_regs[SFR_IE1] +#define IP m_sfr_regs[SFR_IP] +#define B m_sfr_regs[SFR_B] +#define ER8 m_sfr_regs[SFR_ER8] -/*************************************************************************** - SHORTCUTS -***************************************************************************/ +#define DPL1 m_sfr_regs[SFR_DPL1] +#define DPH1 m_sfr_regs[SFR_DPH1] -#define PPC m_ppc -#define PC m_pc -/* SFR Registers - These are accessed directly for speed on read */ -/* Read accessors */ +#define ER00 m_sfr_regs[SFR_ER00] +#define ER01 m_sfr_regs[SFR_ER01] -#define SFR_A(a) m_sfr_ram[(a)] -#define SET_SFR_A(a,v) do { SFR_A(a) = (v); } while (0) +#define ER10 m_sfr_regs[SFR_ER10] +#define ER11 m_sfr_regs[SFR_ER11] -#define ACC SFR_A(ADDR_ACC) -#define PSW SFR_A(ADDR_PSW) +#define ER20 m_sfr_regs[SFR_ER20] +#define ER21 m_sfr_regs[SFR_ER21] -#define P0 ((const uint8_t) SFR_A(ADDR_P0)) -#define P1 ((const uint8_t) SFR_A(ADDR_P1)) -#define P2 ((const uint8_t) SFR_A(ADDR_P2)) -#define P3 ((const uint8_t) SFR_A(ADDR_P3)) +#define ER30 m_sfr_regs[SFR_ER30] +#define ER31 m_sfr_regs[SFR_ER31] -#define SP SFR_A(ADDR_SP) -#define DPL SFR_A(ADDR_DPL) -#define DPH SFR_A(ADDR_DPH) -#define PCON SFR_A(ADDR_PCON) -#define IE SFR_A(ADDR_IE) -#define IP SFR_A(ADDR_IP) -#define B SFR_A(ADDR_B) +#define GP0 m_sfr_regs[SFR_GP0] +#define GP1 m_sfr_regs[SFR_GP1] +#define GP2 m_sfr_regs[SFR_GP2] +#define GP3 m_sfr_regs[SFR_GP3] +#define GP4 m_sfr_regs[SFR_GP4] +#define GP5 m_sfr_regs[SFR_GP5] +#define GP6 m_sfr_regs[SFR_GP6] +#define GP7 m_sfr_regs[SFR_GP7] #define R_REG(r) m_scratchpad[(r) | (PSW & 0x18)] -#define DPTR ((DPH<<8) | DPL) -/* WRITE accessors */ +#define DPTR0 ((DPH0<<8) | DPL0) +#define DPTR1 ((DPH1<<8) | DPL1) -/* Shortcuts */ +#define ER0 ((ER01<<8) | ER00) +#define ER1 ((ER11<<8) | ER10) +#define ER2 ((ER21<<8) | ER20) +#define ER3 ((ER31<<8) | ER30) -#define SET_PSW(v) do { SFR_A(ADDR_PSW) = (v); SET_PARITY(); } while (0) -#define SET_ACC(v) do { SFR_A(ADDR_ACC) = (v); SET_PARITY(); } while (0) +#define SET_PSW(v) do { m_sfr_regs[SFR_PSW] = (v); SET_PARITY(); } while (0) +#define SET_ACC(v) do { m_sfr_regs[SFR_ACC] = (v); SET_PARITY(); } while (0) /* These trigger actions on modification and have to be written through SFR_W */ -#define SET_P0(v) IRAM_W(ADDR_P0, v) -#define SET_P1(v) IRAM_W(ADDR_P1, v) -#define SET_P2(v) IRAM_W(ADDR_P2, v) -#define SET_P3(v) IRAM_W(ADDR_P3, v) - - +#define SET_P0(v) iram_write(SFR_P0, v) +#define SET_P1(v) iram_write(SFR_P1, v) +#define SET_P2(v) iram_write(SFR_P2, v) +#define SET_P3(v) iram_write(SFR_P3, v) /* No actions triggered on write */ #define SET_REG(r, v) do { m_scratchpad[(r) | (PSW & 0x18)] = (v); } while (0) -#define SET_DPTR(n) do { DPH = ((n) >> 8) & 0xff; DPL = (n) & 0xff; } while (0) +#define SET_DPTR0(n) do { DPH0 = ((n) >> 8) & 0xff; DPL0 = (n) & 0xff; } while (0) + +#define SET_DPTR1(n) do { DPH1 = ((n) >> 8) & 0xff; DPL1 = (n) & 0xff; } while (0) + +#define SET_ER0(n) do { ER01 = ((n) >> 8) & 0xff; ER00 = (n) & 0xff; } while (0) +#define SET_ER1(n) do { ER11 = ((n) >> 8) & 0xff; ER10 = (n) & 0xff; } while (0) +#define SET_ER2(n) do { ER21 = ((n) >> 8) & 0xff; ER20 = (n) & 0xff; } while (0) +#define SET_ER3(n) do { ER31 = ((n) >> 8) & 0xff; ER30 = (n) & 0xff; } while (0) + +#define SET_ER8(n) do { ER8 = (n);} while (0) + +#define SET_GP0(n) do { GP0 = (n);} while (0) +#define SET_GP1(n) do { GP1 = (n);} while (0) +#define SET_GP2(n) do { GP2 = (n);} while (0) +#define SET_GP3(n) do { GP3 = (n);} while (0) +#define SET_GP4(n) do { GP4 = (n);} while (0) +#define SET_GP5(n) do { GP5 = (n);} while (0) +#define SET_GP6(n) do { GP6 = (n);} while (0) +#define SET_GP7(n) do { GP7 = (n);} while (0) /* 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_EC(n) SET_PSW((PSW & 0xdf) | (n<<5)) //Extended Instruction Carry Flag EC (not FO) #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_EZ(n) SET_PSW((PSW & 0xfd) | (n<<1)) //Extended Instruction Zero Flag EZ #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 - /* Macros for accessing flags */ #define GET_CY GET_BIT(PSW, 7) #define GET_AC GET_BIT(PSW, 6) -#define GET_FO GET_BIT(PSW, 5) +#define GET_EC GET_BIT(PSW, 5) //Extended Instruction Carry Flag EC (not FO) #define GET_RS GET_BIT(PSW, 3) #define GET_OV GET_BIT(PSW, 2) +#define GET_EZ GET_BIT(PSW, 1) //Extended Instruction Zero Flag EZ #define GET_P GET_BIT(PSW, 0) -#define GET_EA GET_BIT(IE, 7) -#define GET_ET2 GET_BIT(IE, 5) -#define GET_ES GET_BIT(IE, 4) -#define GET_ET1 GET_BIT(IE, 3) -#define GET_EX1 GET_BIT(IE, 2) -#define GET_ET0 GET_BIT(IE, 1) -#define GET_EX0 GET_BIT(IE, 0) +#define GET_DMAIRQEN GET_BIT(IE1, 6) - - -/*Add and Subtract Flag settings*/ -#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 GET_EA GET_BIT(IE, 7) +#define GET_SDCIRQEN GET_BIT(IE, 6) +#define GET_SPIIRQEN GET_BIT(IE, 5) +#define GET_USBIRQEN GET_BIT(IE, 4) +#define GET_T3IRQEN GET_BIT(IE, 3) +#define GET_T2IRQEN GET_BIT(IE, 2) +#define GET_T1IRQEN GET_BIT(IE, 1) +#define GET_T0IRQEN GET_BIT(IE, 0) #define SET_PARITY() do {m_recalc_parity |= 1;} while (0) -#define PUSH_PC() push_pc() -#define POP_PC() pop_pc() - -/* Clear Current IRQ */ -#define CLEAR_CURRENT_IRQ() clear_current_irq() - - -/* Hold callback functions so they can be set by caller (before the cpu reset) */ /*************************************************************************** INLINE FUNCTIONS @@ -247,28 +263,18 @@ void axc51base_cpu_device::iram_iwrite(offs_t a, uint8_t d) { m_data.write_byte( void axc51base_cpu_device::clear_current_irq() { - if (m_cur_irq_prio >= 0) - m_irq_active &= ~(1 << m_cur_irq_prio); - if (m_irq_active & 4) - m_cur_irq_prio = 2; - else if (m_irq_active & 2) - m_cur_irq_prio = 1; - else if (m_irq_active & 1) - m_cur_irq_prio = 0; - else - m_cur_irq_prio = -1; - LOG(("New: %d %02x\n", m_cur_irq_prio, m_irq_active)); + LOGMASKED(LOG_UNHANDLED,"clear irq\n"); } -uint8_t axc51base_cpu_device::r_acc() { return SFR_A(ADDR_ACC); } +uint8_t axc51base_cpu_device::r_acc() { return m_sfr_regs[SFR_ACC]; } -uint8_t axc51base_cpu_device::r_psw() { return SFR_A(ADDR_PSW); } +uint8_t axc51base_cpu_device::r_psw() { return m_sfr_regs[SFR_PSW]; } offs_t axc51base_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) { if (mem_mask == 0x00ff) - return (offset & mem_mask) | (P2 << 8); + return (offset & mem_mask) | 0x000; return offset; } @@ -277,7 +283,7 @@ offs_t axc51base_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) uint8_t axc51base_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 & 0x7f)); } void axc51base_cpu_device::iram_write(size_t offset, uint8_t data) @@ -285,25 +291,25 @@ void axc51base_cpu_device::iram_write(size_t offset, uint8_t data) if ((offset) < 0x80) m_data.write_byte(offset, data); else - sfr_write(offset, data); + sfr_write(offset & 0x7f, data); } /*Push the current PC to the stack*/ void axc51base_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) + iram_indirect_write(tmpSP, (m_pc & 0xff)); //Store low byte of PC to Internal Ram (Use iram_indirect_write 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_indirect_write(tmpSP, ( (m_pc & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use iram_indirect_write to store stack above 128 bytes) } /*Pop the current PC off the stack and into the pc*/ void axc51base_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) + m_pc = (iram_indirect_read(tmpSP--) & 0xff) << 8; //Store hi byte to PC (must use iram_indirect_read to access stack pointing above 128 bytes) + m_pc = m_pc | iram_indirect_read(tmpSP--); //Store lo byte to PC (must use iram_indirect_read to access stack pointing above 128 bytes) SP = tmpSP; //Decrement Stack Pointer } @@ -339,7 +345,7 @@ uint8_t axc51base_cpu_device::bit_address_r(uint8_t offset) word = ( (offset & 0x78) >> 3) * distance + 0x20; bit_pos = offset & 0x7; mask = (0x1 << bit_pos); - return((IRAM_R(word) & mask) >> bit_pos); + return((iram_read(word) & mask) >> bit_pos); } //SFR bit addressable registers else { @@ -347,7 +353,7 @@ uint8_t axc51base_cpu_device::bit_address_r(uint8_t offset) word = ( (offset & 0x78) >> 3) * distance + 0x80; bit_pos = offset & 0x7; mask = (0x1 << bit_pos); - return ((IRAM_R(word) & mask) >> bit_pos); + return ((iram_read(word) & mask) >> bit_pos); } } @@ -367,9 +373,9 @@ void axc51base_cpu_device::bit_address_w(uint8_t offset, uint8_t bit) bit_pos = offset & 0x7; bit = (bit & 0x1) << bit_pos; mask = ~(1 << bit_pos) & 0xff; - result = IRAM_R(word) & mask; + result = iram_read(word) & mask; result = result | bit; - IRAM_W(word, result); + iram_write(word, result); } /* SFR bit addressable registers */ else { @@ -378,9 +384,9 @@ void axc51base_cpu_device::bit_address_w(uint8_t offset, uint8_t bit) bit_pos = offset & 0x7; bit = (bit & 0x1) << bit_pos; mask = ~(1 << bit_pos) & 0xff; - result = IRAM_R(word) & mask; + result = iram_read(word) & mask; result = result | bit; - IRAM_W(word, result); + iram_write(word, result); } } @@ -406,53 +412,56 @@ void axc51base_cpu_device::do_sub_flags(uint8_t a, uint8_t data, uint8_t c) SET_OV((result1 < -128 || result1 > 127)); } -void axc51base_cpu_device::transmit_receive(int source) -{ -} - -void axc51base_cpu_device::update_timer_t0(int cycles) -{ -} - - - -void axc51base_cpu_device::update_timer_t1(int cycles) -{ -} - -void axc51base_cpu_device::update_timer_t2(int cycles) +uint32_t axc51base_cpu_device::get_dptr0_with_autoinc(uint8_t auto_inc) { -} - -void axc51base_cpu_device::update_timers(int cycles) -{ - while (cycles--) + uint32_t addr = external_ram_iaddr(DPTR0, 0xffff); + if (auto_inc) // auto-increment enabled { - update_timer_t0(1); - update_timer_t1(1); + if (m_sfr_regs[SFR_DPCON] & 0x20) // DPID0 DPTR0 increase direction control + { + uint16_t dptr = (DPTR0)-1; + SET_DPTR0(dptr); + } + else + { + uint16_t dptr = (DPTR0)+1; + SET_DPTR0(dptr); + } } + return addr; } -void axc51base_cpu_device::serial_transmit(uint8_t data) +uint32_t axc51base_cpu_device::get_dptr1_with_autoinc(uint8_t auto_inc) { + uint32_t addr = external_ram_iaddr(DPTR1, 0xffff); + if (auto_inc) // auto-increment enabled + { + if (m_sfr_regs[SFR_DPCON] & 0x10) // DPID1 DPTR1 increase direction control + { + uint16_t dptr = (DPTR1)-1; + SET_DPTR1(dptr); + } + else + { + uint16_t dptr = (DPTR1)+1; + SET_DPTR1(dptr); + } + } + return addr; } -void axc51base_cpu_device::serial_receive() +uint32_t axc51base_cpu_device::process_dptr_access() { -} + uint8_t auto_inc = m_sfr_regs[SFR_DPCON] & 0x08; + uint32_t addr = (m_sfr_regs[SFR_DPCON] & 0x01) ? get_dptr1_with_autoinc(auto_inc) : get_dptr0_with_autoinc(auto_inc); -/* Check and update status of serial port */ -void axc51base_cpu_device::update_serial(int cycles) -{ - while (--cycles>=0) - transmit_receive(0); -} + if (m_sfr_regs[SFR_DPCON] & 0x04) + { + // auto toggle DPR + m_sfr_regs[SFR_DPCON] ^= 0x01; + } -/* Check and update status of serial port */ -void axc51base_cpu_device::update_irq_prio(uint8_t ipl, uint8_t iph) -{ - for (int i=0; i<8; i++) - m_irq_prio[i] = ((ipl >> i) & 1) | (((iph >>i ) & 1) << 1); + return addr; } @@ -463,6 +472,8 @@ void axc51base_cpu_device::update_irq_prio(uint8_t ipl, uint8_t iph) #define OPHANDLER( _name ) void axc51base_cpu_device::_name (uint8_t r) #include "axc51ops.hxx" +#include "axc51extops.hxx" + void axc51base_cpu_device::execute_op(uint8_t op) @@ -672,7 +683,7 @@ void axc51base_cpu_device::execute_op(uint8_t op) 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 0xa5: axc51_extended_a5(op); break; case 0xa6: case 0xa7: mov_ir_mem(op&1); break; //MOV @R0/@R1, data addr @@ -812,23 +823,73 @@ const uint8_t axc51base_cpu_device::axc51_cycles[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; +uint16_t axc51base_cpu_device::get_irq_base() +{ + int base = 0; -void axc51base_cpu_device::check_irqs() + switch (m_sfr_regs[SFR_DPCON] & 0xc0) + { + case 0x00: + case 0xc0: + base = 0; // invalid + break; + + case 0x80: + base = 0x8000; + break; + + case 0x40: + base = 0x4000; + break; + } + + return base; +} + +TIMER_CALLBACK_MEMBER(axc51base_cpu_device::timer0_cb) { + // TODO: this logic is not correct + + m_timer0irq = true; } -void axc51base_cpu_device::burn_cycles(int cycles) +TIMER_CALLBACK_MEMBER(axc51base_cpu_device::dactimer_cb) { - /* Update Timer (if any timers are running) */ - update_timers(cycles); + // TODO: this logic is not correct + + m_dactimerirq = true; +} - /* Update Serial (only for mode 0) */ - update_serial(cycles); - /* check_irqs */ - check_irqs(); +void axc51base_cpu_device::check_irqs() +{ + // TODO: this logic is not correct + + if (!GET_EA) + return; + + uint16_t base = get_irq_base(); + + if (!base) + return; + + if (m_timer0irq && GET_T0IRQEN) + { + push_pc(); + m_pc = base + V_TIMER0; + m_timer0irq = false; + } + else if (m_dactimerirq && GET_DMAIRQEN) + { + push_pc(); + m_pc = base + V_DAC; + m_dactimerirq = false; + } } + + + void axc51base_cpu_device::execute_set_input(int irqline, int state) { uint32_t new_state = (m_last_line_state & ~(1 << irqline)) | ((state != CLEAR_LINE) << irqline); @@ -850,14 +911,13 @@ void axc51base_cpu_device::execute_run() check_irqs(); m_icount -= m_inst_cycles; - burn_cycles(m_inst_cycles); do { /* Read next opcode */ - PPC = PC; - debugger_instruction_hook(PC); - op = m_program.read_byte(PC++); + m_ppc = m_pc; + debugger_instruction_hook(m_pc); + op = m_program.read_byte(m_pc++); /* process opcode and count cycles */ m_inst_cycles = axc51_cycles[op]; @@ -866,73 +926,291 @@ void axc51base_cpu_device::execute_run() /* burn the cycles */ m_icount -= m_inst_cycles; - burn_cycles(m_inst_cycles); + check_irqs(); } while( m_icount > 0 ); } +uint8_t axc51base_cpu_device::xsfr_read(offs_t offset) +{ + offset &= 0x7f; + + LOGMASKED(LOG_UNHANDLED_XSFR,"%s: reading unhandled XSFR reg %04x\n", machine().describe_context(), offset + 0x3000); + + return m_xsfr_regs[offset]; +} + +void axc51base_cpu_device::xsfr_write(offs_t offset, uint8_t data) +{ + offset &= 0x7f; + + switch (offset) + { + case XSFR_PUP0: // 0x3010 + case XSFR_PUP1: // 0x3011 + case XSFR_PUP2: // 0x3012 + case XSFR_PUP3: // 0x3013 + case XSFR_PUP4: // 0x3014 + + case XSFR_PDN0: // 0x3015 + case XSFR_PDN1: // 0x3016 + case XSFR_PDN2: // 0x3017 + case XSFR_PDN3: // 0x3018 + case XSFR_PDN4: // 0x3019 + break; + + case XSFR_PHD0: // 0x301a + case XSFR_PHD1: // 0x301b + case XSFR_PHD2: // 0x301c + case XSFR_PHD3: // 0x301d + case XSFR_PHD4: // 0x301e + break; + + default: + LOGMASKED(LOG_UNHANDLED_XSFR,"%s: writing to unhandled XSFR reg %04x data %02x\n", machine().describe_context(), offset + 0x3000, data); + break; + } + m_xsfr_regs[offset] = data; +} void axc51base_cpu_device::sfr_write(size_t offset, uint8_t data) { /* update register */ - assert(offset >= 0x80 && offset <= 0xff); - switch (offset) { - 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_PSW: SET_PARITY(); break; - case ADDR_ACC: SET_PARITY(); break; - case ADDR_IP: update_irq_prio(data, 0); break; - - case ADDR_B: - case ADDR_SP: - case ADDR_DPL: - case ADDR_DPH: - case ADDR_PCON: - case ADDR_IE: - break; - default: - LOG(("axc51 '%s': attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", tag(), (uint32_t)offset,PC,data)); - /* no write in this case according to manual */ - return; + case SFR_P0: write_port(0, data); break; + case SFR_P1: write_port(1, data); break; + case SFR_P2: write_port(2, data); break; + case SFR_P3: write_port(3, data); break; + case SFR_PSW: SET_PARITY(); break; + case SFR_ACC: SET_PARITY(); break; + case SFR_IP: break; + + case SFR_B: + case SFR_SP: + case SFR_DPL0: + case SFR_DPH0: + case SFR_PCON: + break; + + case SFR_DPL1: // 0x84 + case SFR_DPH1: // 0x85 + break; + + case SFR_IE: + break; + + case SFR_IE1: + break; + + case SFR_GP0: // 0xa1 + case SFR_GP1: // 0xa2 + case SFR_GP2: // 0xa3 + case SFR_GP3: // 0xa4 + case SFR_GP4: // 0xb1 + case SFR_GP5: // 0xb2 + case SFR_GP6: // 0xb3 + case SFR_GP7: // 0xb5 + break; + + case SFR_DACLCH: // 0xa6 + m_dac_out_cb[0](data); + break; + + case SFR_DACRCH: // 0xa7 + m_dac_out_cb[1](data); + break; + + case SFR_P0DIR: // 0xba + case SFR_P1DIR: // 0xbb + case SFR_P2DIR: // 0xbc + case SFR_P3DIR: // 0xbd + case SFR_P4DIR: // 0xbe + break; + + case SFR_ER00: // 0xe6 + case SFR_ER01: // 0xe7 + case SFR_ER10: // 0xe8 + case SFR_ER11: // 0xe9 + case SFR_ER20: // 0xea + case SFR_ER21: // 0xeb + case SFR_ER30: // 0xec + case SFR_ER31: // 0xed + case SFR_ER8: // 0xee + break; + + case SFR_P4: write_port(4, data); break; // 0xb4 + + case SFR_TMR0CON: // 0xf8 + case SFR_TMR0CNT: // 0xf9 + case SFR_TMR0PR: // 0xfa + case SFR_TMR0PSR: // 0xfb + break; + + case SFR_IE2CRPT: // 0x95 controls automatic encryption + ie2crypt_w(data); + return; + + case SFR_DPCON: dpcon_w(data); return; // 0x86 + + case SFR_DBASE: // 0x9b + m_sfr_regs[SFR_DBASE] = data; + return; + + + case SFR_SPIDMAADR: spidmaadr_w(data); return; // 0xd6 + case SFR_SPIDMACNT: spidmacnt_w(data); return; // 0xd7 + case SFR_SPICON: spicon_w(data); return; // 0xd8 + case SFR_SPIBUF: spibuf_w(data); return; // 0xd9 + case SFR_SPIBAUD: spibaud_w(data); return; // 0xda + + + default: + LOGMASKED(LOG_UNHANDLED,"%s: attemping to write to an invalid/non-implemented SFR address: %02x data=%02x\n", machine().describe_context(), (uint32_t)offset, data); + /* no write in this case according to manual */ + return; } - m_data.write_byte((size_t)offset | 0x100, data); + m_sfr_regs[offset] = data; } -uint8_t axc51base_cpu_device::sfr_read(size_t offset) +uint8_t axc51base_cpu_device::read_port(int i) { - assert(offset >= 0x80 && offset <= 0xff); + uint8_t latched_out_data = 0x00; + uint8_t port_direction = 0x00; + uint8_t pup = 0x00; + uint8_t pdn = 0x00; + + // direction 0xff = all bits set to input? + + // pdn and pup registers are mentioned as 'pull down' and 'pull up' but other than + // there being 5 of them it isn't clear if they're used for these ports or not + + switch (i) + { + case 0: latched_out_data = P0; port_direction = m_sfr_regs[SFR_P0DIR]; pup = m_xsfr_regs[XSFR_PUP0]; pdn = m_xsfr_regs[XSFR_PDN0]; break; + case 1: latched_out_data = P1; port_direction = m_sfr_regs[SFR_P1DIR]; pup = m_xsfr_regs[XSFR_PUP1]; pdn = m_xsfr_regs[XSFR_PDN1]; break; + case 2: latched_out_data = P2; port_direction = m_sfr_regs[SFR_P2DIR]; pup = m_xsfr_regs[XSFR_PUP2]; pdn = m_xsfr_regs[XSFR_PDN2]; break; + case 3: latched_out_data = P3; port_direction = m_sfr_regs[SFR_P3DIR]; pup = m_xsfr_regs[XSFR_PUP3]; pdn = m_xsfr_regs[XSFR_PDN3]; break; + case 4: latched_out_data = P4; port_direction = m_sfr_regs[SFR_P4DIR]; pup = m_xsfr_regs[XSFR_PUP4]; pdn = m_xsfr_regs[XSFR_PDN4]; break; + } + + uint8_t incoming = m_port_in_cb[i](); + + LOGMASKED(LOG_PORTS,"%s: reading port %d with direction %02x pup %02x pdn %02x latched output %02x incoming data %02x\n", machine().describe_context(), i, port_direction, pup, pdn, latched_out_data, incoming); + return incoming; +} + +void axc51base_cpu_device::write_port(int i, uint8_t data) +{ + uint8_t port_direction = 0x00; + uint8_t pup = 0x00; + uint8_t pdn = 0x00; + + switch (i) + { + case 0: port_direction = m_sfr_regs[SFR_P0DIR]; pup = m_xsfr_regs[XSFR_PUP0]; pdn = m_xsfr_regs[XSFR_PDN0]; break; + case 1: port_direction = m_sfr_regs[SFR_P1DIR]; pup = m_xsfr_regs[XSFR_PUP1]; pdn = m_xsfr_regs[XSFR_PDN1]; break; + case 2: port_direction = m_sfr_regs[SFR_P2DIR]; pup = m_xsfr_regs[XSFR_PUP2]; pdn = m_xsfr_regs[XSFR_PDN2]; break; + case 3: port_direction = m_sfr_regs[SFR_P3DIR]; pup = m_xsfr_regs[XSFR_PUP3]; pdn = m_xsfr_regs[XSFR_PDN3]; break; + case 4: port_direction = m_sfr_regs[SFR_P4DIR]; pup = m_xsfr_regs[XSFR_PUP4]; pdn = m_xsfr_regs[XSFR_PDN4]; break; + } + LOGMASKED(LOG_PORTS,"%s: writing port %d with direction %02x pup %02x pdn %02x data %02x\n", machine().describe_context(), i, port_direction, pup, pdn, data); + m_port_out_cb[i](data); // also send port direction?? +} + +uint8_t axc51base_cpu_device::sfr_read(size_t offset) +{ switch (offset) { - /* Move to memory map */ - case ADDR_P0: return (P0 | m_forced_inputs[0]) & m_port_in_cb[0](); - case ADDR_P1: return (P1 | m_forced_inputs[1]) & m_port_in_cb[1](); - case ADDR_P2: return (P2 | m_forced_inputs[2]) & m_port_in_cb[2](); - case ADDR_P3: return (P3 | m_forced_inputs[3]) & m_port_in_cb[3]() - & ~(GET_BIT(m_last_line_state, AXC51_INT0_LINE) ? 4 : 0) - & ~(GET_BIT(m_last_line_state, AXC51_INT1_LINE) ? 8 : 0); - - case ADDR_PSW: - case ADDR_ACC: - case ADDR_B: - case ADDR_SP: - case ADDR_DPL: - case ADDR_DPH: - case ADDR_PCON: - case ADDR_IE: - case ADDR_IP: - return m_data.read_byte((size_t) offset | 0x100); + case SFR_P0: return read_port(0); + case SFR_P1: return read_port(1); + case SFR_P2: return read_port(2); + case SFR_P3: return read_port(3); + + case SFR_PSW: + case SFR_ACC: + case SFR_B: + case SFR_SP: + case SFR_DPL0: + case SFR_DPH0: + case SFR_PCON: + case SFR_IE: + case SFR_IE1: + + case SFR_DPL1: // 0x84 + case SFR_DPH1: // 0x85 + + case SFR_IP: + + case SFR_GP0: // 0xa1 + case SFR_GP1: // 0xa2 + case SFR_GP2: // 0xa3 + case SFR_GP3: // 0xa4 + case SFR_GP4: // 0xb1 + case SFR_GP5: // 0xb2 + case SFR_GP6: // 0xb3 + case SFR_GP7: // 0xb5 + return m_sfr_regs[offset]; + + case SFR_P4: // 0xb4 + return read_port(4); + + case SFR_P0DIR: // 0xba + case SFR_P1DIR: // 0xbb + case SFR_P2DIR: // 0xbc + case SFR_P3DIR: // 0xbd + case SFR_P4DIR: // 0xbe + + case SFR_ER00: // 0xe6 + case SFR_ER01: // 0xe7 + case SFR_ER10: // 0xe8 + case SFR_ER11: // 0xe9 + case SFR_ER20: // 0xea + case SFR_ER21: // 0xeb + case SFR_ER30: // 0xec + case SFR_ER31: // 0xed + case SFR_ER8: // 0xee + + case SFR_TMR0CON: // 0xf8 + case SFR_TMR0CNT: // 0xf9 + case SFR_TMR0PR: // 0xfa + case SFR_TMR0PSR: // 0xfb + + case SFR_IE2CRPT: // 0x95 controls automatic encryption + return m_sfr_regs[offset]; + + + case SFR_DPCON: // 0x86 + return dpcon_r(); + + case SFR_IRTCON: // 0x9f + return 0x00;// machine().rand(); + + case SFR_SPICON: // 0xd8 + return spicon_r(); + + case SFR_SPIBUF: // 0xd9 + return spibuf_r(); + + case SFR_UID0: return m_uid[0]; // 0xe2 Chip-ID, can only be read from code in internal area? + case SFR_UID1: return m_uid[1]; // 0xe3 + case SFR_UID2: return m_uid[2]; // 0xe4 + case SFR_UID3: return m_uid[3]; // 0xe5 + + case SFR_LFSRFIFO: // 0xf6 + return 0x00;// machine().rand(); + + case SFR_UARTSTA: // 0xfc + return uartsta_r(); + /* Illegal or non-implemented sfr */ - default: - LOG(("axc51 '%s': attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", tag(), (uint32_t)offset,PC)); - /* according to the manual, the read may return random bits */ - return 0xff; + default: + LOGMASKED(LOG_UNHANDLED,"%s: attemping to read an invalid/non-implemented SFR address: %02x\n", machine().describe_context(), (uint32_t)offset); + /* according to the manual, the read may return random bits */ + return 0xff; } } @@ -945,50 +1223,64 @@ void axc51base_cpu_device::device_start() m_port_in_cb.resolve_all_safe(0xff); m_port_out_cb.resolve_all_safe(); - m_serial_rx_cb.resolve_safe(0); - m_serial_tx_cb.resolve_safe(); + m_dac_out_cb.resolve_all_safe(); + + m_spi_in_cb.resolve_safe(0xff); + m_spi_out_cb.resolve_safe(); + m_spi_out_dir_cb.resolve_safe(); /* Save states */ save_item(NAME(m_ppc)); save_item(NAME(m_pc)); save_item(NAME(m_last_op)); save_item(NAME(m_last_bit)); - save_item(NAME(m_cur_irq_prio) ); save_item(NAME(m_last_line_state) ); save_item(NAME(m_recalc_parity) ); - save_item(NAME(m_irq_prio) ); - save_item(NAME(m_irq_active) ); - save_item(NAME(m_uart.data_out)); - save_item(NAME(m_uart.bits_to_send)); - 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)); - - state_add( AXC51_PC, "PC", m_pc).formatstr("%04X"); - state_add( AXC51_SP, "SP", SP).formatstr("%02X"); - state_add( AXC51_PSW, "PSW", PSW).formatstr("%02X"); - state_add( AXC51_ACC, "A", ACC).formatstr("%02X"); - state_add( AXC51_B, "B", B).formatstr("%02X"); - state_add( AXC51_DPTR, "DPTR", [this](){ return DPTR; }, [this](uint16_t dp){ SET_DPTR(dp); }).formatstr("%04X"); - state_add( AXC51_DPH, "DPH", DPH).noshow(); - state_add( AXC51_DPL, "DPL", DPL).noshow(); - state_add( AXC51_IE, "IE", IE).formatstr("%02X"); - state_add( AXC51_IP, "IP", IP).formatstr("%02X"); + save_item(NAME(m_sfr_regs)); + save_item(NAME(m_xsfr_regs)); + + state_add( SFR_STATEREG_PC, "PC", m_pc).formatstr("%04X"); + state_add( SFR_STATEREG_SP, "SP", SP).formatstr("%02X"); + state_add( SFR_STATEREG_PSW, "PSW", PSW).formatstr("%02X"); + state_add( SFR_STATEREG_ACC, "A", ACC).formatstr("%02X"); + state_add( SFR_STATEREG_B, "B", B).formatstr("%02X"); + state_add( SFR_STATEREG_DPTR0, "DPTR0", [this](){ return DPTR0; }, [this](uint16_t dp){ SET_DPTR0(dp); }).formatstr("%04X"); + state_add( SFR_STATEREG_DPTR1, "DPTR1", [this](){ return DPTR1; }, [this](uint16_t dp){ SET_DPTR1(dp); }).formatstr("%04X"); + state_add( SFR_STATEREG_DPH0, "DPH0", DPH0).noshow(); + state_add( SFR_STATEREG_DPL0, "DPL0", DPL0).noshow(); + state_add( SFR_STATEREG_IE, "IE", IE).formatstr("%02X"); + state_add( SFR_STATEREG_IP, "IP", IP).formatstr("%02X"); if (m_rom_size > 0) - state_add( AXC51_P0, "P0", [this](){ return P0; }, [this](uint8_t p){ SET_P0(p); }).formatstr("%02X"); - state_add( AXC51_P1, "P1", [this](){ return P1; }, [this](uint8_t p){ SET_P1(p); }).formatstr("%02X"); - state_add( AXC51_P2, "P2", [this](){ return P2; }, [this](uint8_t p){ SET_P2(p); }).formatstr("%02X"); - state_add( AXC51_P3, "P3", [this](){ return P3; }, [this](uint8_t p){ SET_P3(p); }).formatstr("%02X"); - state_add( AXC51_R0, "R0", [this](){ return R_REG(0); }, [this](uint8_t r){ SET_REG(0, r); }).formatstr("%02X"); - state_add( AXC51_R1, "R1", [this](){ return R_REG(1); }, [this](uint8_t r){ SET_REG(1, r); }).formatstr("%02X"); - state_add( AXC51_R2, "R2", [this](){ return R_REG(2); }, [this](uint8_t r){ SET_REG(2, r); }).formatstr("%02X"); - state_add( AXC51_R3, "R3", [this](){ return R_REG(3); }, [this](uint8_t r){ SET_REG(3, r); }).formatstr("%02X"); - state_add( AXC51_R4, "R4", [this](){ return R_REG(4); }, [this](uint8_t r){ SET_REG(4, r); }).formatstr("%02X"); - state_add( AXC51_R5, "R5", [this](){ return R_REG(5); }, [this](uint8_t r){ SET_REG(5, r); }).formatstr("%02X"); - state_add( AXC51_R6, "R6", [this](){ return R_REG(6); }, [this](uint8_t r){ SET_REG(6, r); }).formatstr("%02X"); - state_add( AXC51_R7, "R7", [this](){ return R_REG(7); }, [this](uint8_t r){ SET_REG(7, r); }).formatstr("%02X"); - state_add( AXC51_RB, "RB", [this](){ return (PSW & 0x18)>>3; }, [this](uint8_t rb){ SET_RS(rb); }).mask(0x03).formatstr("%02X"); + state_add( SFR_STATEREG_P0, "P0", [this](){ return P0; }, [this](uint8_t p){ SET_P0(p); }).formatstr("%02X"); + state_add( SFR_STATEREG_P1, "P1", [this](){ return P1; }, [this](uint8_t p){ SET_P1(p); }).formatstr("%02X"); + state_add( SFR_STATEREG_P2, "P2", [this](){ return P2; }, [this](uint8_t p){ SET_P2(p); }).formatstr("%02X"); + state_add( SFR_STATEREG_P3, "P3", [this](){ return P3; }, [this](uint8_t p){ SET_P3(p); }).formatstr("%02X"); + state_add( SFR_STATEREG_R0, "R0", [this](){ return R_REG(0); }, [this](uint8_t r){ SET_REG(0, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R1, "R1", [this](){ return R_REG(1); }, [this](uint8_t r){ SET_REG(1, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R2, "R2", [this](){ return R_REG(2); }, [this](uint8_t r){ SET_REG(2, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R3, "R3", [this](){ return R_REG(3); }, [this](uint8_t r){ SET_REG(3, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R4, "R4", [this](){ return R_REG(4); }, [this](uint8_t r){ SET_REG(4, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R5, "R5", [this](){ return R_REG(5); }, [this](uint8_t r){ SET_REG(5, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R6, "R6", [this](){ return R_REG(6); }, [this](uint8_t r){ SET_REG(6, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_R7, "R7", [this](){ return R_REG(7); }, [this](uint8_t r){ SET_REG(7, r); }).formatstr("%02X"); + state_add( SFR_STATEREG_RB, "RB", [this](){ return (PSW & 0x18)>>3; }, [this](uint8_t rb){ SET_RS(rb); }).mask(0x03).formatstr("%02X"); + + state_add( SFR_STATEREG_ER0, "ER0", [this](){ return ER0; }, [this](uint16_t dp){ SET_ER0(dp); }).formatstr("%04X"); + state_add( SFR_STATEREG_ER1, "ER1", [this](){ return ER1; }, [this](uint16_t dp){ SET_ER1(dp); }).formatstr("%04X"); + state_add( SFR_STATEREG_ER2, "ER2", [this](){ return ER2; }, [this](uint16_t dp){ SET_ER2(dp); }).formatstr("%04X"); + state_add( SFR_STATEREG_ER3, "ER3", [this](){ return ER3; }, [this](uint16_t dp){ SET_ER3(dp); }).formatstr("%04X"); + + state_add( SFR_ER8, "ER8", [this](){ return ER8; }, [this](uint8_t r){ SET_ER8(r); }).formatstr("%02X"); + + state_add( SFR_STATEREG_GP0, "GP0", [this](){ return GP0; }, [this](uint8_t r){ SET_GP0(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP1, "GP1", [this](){ return GP1; }, [this](uint8_t r){ SET_GP1(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP2, "GP2", [this](){ return GP2; }, [this](uint8_t r){ SET_GP2(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP3, "GP3", [this](){ return GP3; }, [this](uint8_t r){ SET_GP3(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP4, "GP4", [this](){ return GP4; }, [this](uint8_t r){ SET_GP4(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP5, "GP5", [this](){ return GP5; }, [this](uint8_t r){ SET_GP5(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP6, "GP6", [this](){ return GP6; }, [this](uint8_t r){ SET_GP6(r); }).formatstr("%02X"); + state_add( SFR_STATEREG_GP7, "GP7", [this](){ return GP7; }, [this](uint8_t r){ SET_GP7(r); }).formatstr("%02X"); + state_add( STATE_GENPC, "GENPC", m_pc ).noshow(); @@ -996,6 +1288,10 @@ void axc51base_cpu_device::device_start() state_add( STATE_GENFLAGS, "GENFLAGS", m_rtemp).formatstr("%8s").noshow(); set_icountptr(m_icount); + + m_timer0 = timer_alloc(FUNC(axc51base_cpu_device::timer0_cb), this); + m_dactimer = timer_alloc(FUNC(axc51base_cpu_device::dactimer_cb), this); + } void axc51base_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const @@ -1006,11 +1302,11 @@ void axc51base_cpu_device::state_string_export(const device_state_entry &entry, str = string_format("%c%c%c%c%c%c%c%c", PSW & 0x80 ? 'C':'.', PSW & 0x40 ? 'A':'.', - PSW & 0x20 ? 'F':'.', + PSW & 0x20 ? 'c':'.', // EC PSW & 0x10 ? '0':'.', PSW & 0x08 ? '1':'.', PSW & 0x04 ? 'V':'.', - PSW & 0x02 ? '?':'.', + PSW & 0x02 ? 'z':'.', // EZ PSW & 0x01 ? 'P':'.'); break; } @@ -1022,40 +1318,38 @@ void axc51base_cpu_device::device_reset() m_last_line_state = 0; /* Flag as NO IRQ in Progress */ - m_irq_active = 0; - m_cur_irq_prio = -1; m_last_op = 0; m_last_bit = 0; /* these are all defined reset states */ - PPC = PC; - PC = 0; + m_ppc = m_pc; + m_pc = 0; SP = 0x7; SET_PSW(0); SET_ACC(0); - DPH = 0; - DPL = 0; + DPH0 = 0; + DPL0 = 0; B = 0; IP = 0; - update_irq_prio(IP, 0); IE = 0; PCON = 0; - /* set the port configurations to all 1's */ SET_P3(0xff); SET_P2(0xff); SET_P1(0xff); SET_P0(0xff); - m_uart.data_out = 0; - m_uart.rx_clk = 0; - m_uart.tx_clk = 0; - m_uart.bits_to_send = 0; - m_uart.delay_cycles = 0; - m_uart.smod_div = 0; - m_recalc_parity = 0; + + m_spi_dma_addr = 0; + +// m_timer0->adjust(attotime::never); +// m_dactimer->adjust(attotime::never); + + + m_timer0->adjust(attotime::from_hz(120), 0, attotime::from_hz(120)); + m_dactimer->adjust(attotime::from_hz(8000), 0, attotime::from_hz(8000)); } @@ -1066,151 +1360,171 @@ std::unique_ptr axc51base_cpu_device::create_disassemble -// AX208 (specific CPU) -ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : axc51base_cpu_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(ax208_cpu_device::ax208_internal_program_mem), this), address_map_constructor(FUNC(ax208_cpu_device::data_internal), this), 0, 8) -{ -} +/* -ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ax208_cpu_device(mconfig, AX208, tag, owner, clock) -{ -} +SFR_SPICON (at 0xd8) +7 SPIPND (0 = Send not finished, 1 = finished) +6 SPISM (0 = Master, 1 = Slave) +5 SPIRT (RX/TX select for 2-wire mode / DMA, 0 = TX, 1 = RX) +4 SPIWS (0 = 3-wire mode, 1 = 2-wire mode) +3 SPIGSEL (0 = group 0, 1 = group 1) +2 SPIEDGE (if SPIIDST == 0 then 0 = falling edge, 1 = rising edge, if SPIIDST == 1 inverted) +1 SPIDST (0 = clock signal is 0 when idle, 1 = clock signal is 1 when idle) +0 SPIEN (0 = SPI disable, 1 = enable) +*/ -std::unique_ptr ax208_cpu_device::create_disassembler() +uint8_t axc51base_cpu_device::spicon_r() { - return std::make_unique(); + uint8_t result = m_sfr_regs[SFR_SPICON] | 0x80; +// LOGMASKED(LOG_UNSORTED,"%s: sfr_read SFR_SPICON %02x\n", machine().describe_context(), result); + return result; } +/* +SFR_UARTSTA (at 0xfc) +7 UTRXNB (9th bit of data of RX buffer) +6 FEF (0 = stop bit was 1 in last frame, 1 = stop bit was 0) +5 RXIF (0 = receive not done, 1 = done) +4 TXIF (0 = transmit not done, 1 = done) +3 --- +2 --- +1 --- +0 PSEL (UART port / pin select) -offs_t ax208_cpu_device::external_ram_iaddr(offs_t offset, offs_t mem_mask) -{ - if (mem_mask == 0x00ff) - return (offset & mem_mask); +*/ - return offset; +uint8_t axc51base_cpu_device::uartsta_r() +{ + //uint8_t result = m_sfr_regs[SFR_UARTSTA]; + uint8_t result = 0x30; + LOGMASKED(LOG_UNSORTED, "%s: sfr_read SFR_UARTSTA %02x\n", machine().describe_context(), result); + return result; } -uint8_t ax208_cpu_device::spicon_r() + +void axc51base_cpu_device::spicon_w(uint8_t data) { - logerror("%s: sfr_read AXC51_SPICON\n", machine().describe_context()); - return axc51base_cpu_device::sfr_read(AXC51_SPICON); +// LOGMASKED(LOG_UNSORTED,"%s: sfr_write SFR_SPICON %02x\n", machine().describe_context(), data); + m_sfr_regs[SFR_SPICON] = data; + m_spi_out_dir_cb((data & 0x20) ? true : false); } -uint8_t ax208_cpu_device::dpcon_r() + + +uint8_t axc51base_cpu_device::dpcon_r() { - logerror("%s: sfr_read AXC51_DPCON\n", machine().describe_context()); - return axc51base_cpu_device::sfr_read(AXC51_DPCON); + LOGMASKED(LOG_UNSORTED,"%s: sfr_read SFR_DPCON\n", machine().describe_context()); + return m_sfr_regs[SFR_DPCON]; } -uint8_t ax208_cpu_device::spibuf_r() +uint8_t axc51base_cpu_device::spibuf_r() { - // HACK while we figure things out - - if (state_int(AXC51_PC) == 0x8910) - { - logerror("%s: sfr_read AXC51_SPIBUF (reading from %08x)\n", machine().describe_context(), m_spiaddr); + // TODO: encryption here (if enabled) + uint8_t ret = m_spi_in_cb(); + if (m_sfr_regs[SFR_IE2CRPT] & 0x03) + ret = machine().rand(); - return m_spiptr[m_spiaddr++]; - } + return ret; +} - logerror("%s: sfr_read AXC51_SPIBUF\n", machine().describe_context()); +void axc51base_cpu_device::spibuf_w(uint8_t data) +{ + // TODO: encryption here (if enabled) + m_spi_out_cb(data); +} - return machine().rand(); - //return axc51base_cpu_device::sfr_read(AXC51_SPIBUF); +void axc51base_cpu_device::spibaud_w(uint8_t data) +{ + LOGMASKED(LOG_UNSORTED,"%s: sfr_write SFR_SPIBAUD %02x\n", machine().describe_context(), data); + m_sfr_regs[SFR_SPIBAUD] = data; } -uint8_t ax208_cpu_device::sfr_read(size_t offset) +/* +SFR_DPCON (at 0x86) + +7 IA 01 = vector base 0x4003, 10 = vector base 0x8003, 00/11 invalid +6 IA +5 DPID0 DPTR0 increase direction control, 0 = increase, 1 = decrease +4 DPID1 DPTR1 increase direction control, 0 = increase, 1 = descrese +3 DPAID DPTR auto increase enable +2 DPTSL DPSEL auto-toggle enable (0 = no auto toggle, 1 = auto toggle) +1 --- +0 DPSEL DPTR Select (0 = use DPTR0, 1 = use DPTR1) +*/ + +void axc51base_cpu_device::dpcon_w(uint8_t data) { - switch (offset) - { - case 0x82: - case 0x83: - case 0xe0: // ACC - return axc51base_cpu_device::sfr_read(offset); + m_sfr_regs[SFR_DPCON] = data; +} - case AXC51_DPCON: // 0x86 - return dpcon_r(); +/* +SFR_IE2CRPT (at 0x95) - case AXC51_IRTCON: // 0x9f - return machine().rand(); +7 ---- +6 ---- +5 wdt_int_enable +4 soft_int +3 sd_do_crypt +2 sd_di_crypt +1 spi_do_crypt +0 spi_di_crypt - case AXC51_SPICON: // 0xd8 - return spicon_r(); +*/ - case AXC51_SPIBUF: // 0xd9 - return spibuf_r(); +void axc51base_cpu_device::ie2crypt_w(uint8_t data) +{ + LOGMASKED(LOG_UNSORTED,"%s: sfr_write SFR_IE2CRPT %02x\n", machine().describe_context(), data); + m_sfr_regs[SFR_IE2CRPT] = data; + if (data & 0x03) + { + LOGMASKED(LOG_UNSORTED,"SPI encryption turned on!\n"); } - logerror("%s: sfr_read (%02x)\n", machine().describe_context(), offset); - return axc51base_cpu_device::sfr_read(offset); -} -void ax208_cpu_device::spicon_w(uint8_t data) -{ - logerror("%s: sfr_write AXC51_SPICON %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_SPICON, data); + if (data & 0x0c) + { + LOGMASKED(LOG_UNSORTED,"SD Card encryption turned on!\n"); + } } -void ax208_cpu_device::spibuf_w(uint8_t data) -{ - logerror("%s: sfr_write AXC51_SPIBUF %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_SPIBUF, data); -} -void ax208_cpu_device::spibaud_w(uint8_t data) -{ - logerror("%s: sfr_write AXC51_SPIBAUD %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_SPIBAUD, data); -} -void ax208_cpu_device::dpcon_w(uint8_t data) +void axc51base_cpu_device::spidmaadr_w(uint8_t data) { - logerror("%s: sfr_write AXC51_DPCON %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_DPCON, data); -} + m_sfr_regs[SFR_SPIDMAADR] = data; + m_spi_dma_addr <<= 8; + m_spi_dma_addr = (m_spi_dma_addr & 0xff00) | data; -void ax208_cpu_device::spidmaadr_w(uint8_t data) -{ - logerror("%s: sfr_write AXC51_SPIDMAADR %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_SPIDMAADR, data); } -void ax208_cpu_device::spidmacnt_w(uint8_t data) +void axc51base_cpu_device::spidmacnt_w(uint8_t data) { - logerror("%s: sfr_write AXC51_SPIDMACNT %02x\n", machine().describe_context(), data); - axc51base_cpu_device::sfr_write(AXC51_SPIDMACNT, data); -} + m_sfr_regs[SFR_SPIDMACNT] = data; -void ax208_cpu_device::sfr_write(size_t offset, uint8_t data) -{ - switch (offset) + if (((m_sfr_regs[SFR_SPICON]) & 0x20) == 0x20) // Read from SPI { - case 0x82: - case 0x83: - case 0xe0: - axc51base_cpu_device::sfr_write(offset, data); - return; - - - case AXC51_DPCON: dpcon_w(data); return; // 0x86 - - case AXC51_SPIDMAADR: spidmaadr_w(data); return; // 0xd6 - case AXC51_SPIDMACNT: spidmacnt_w(data); return; // 0xd7 - case AXC51_SPICON: spicon_w(data); return; // 0xd8 - case AXC51_SPIBUF: spibuf_w(data); return; // 0xd9 - case AXC51_SPIBAUD: spibaud_w(data); return; // 0xda - + for (int i = 0; i < (data + 1) * 2; i++) + { + spibuf_w(0x00); // clock + uint8_t romdat = spibuf_r(); + m_io.write_byte(m_spi_dma_addr++, romdat); // is this the correct destination space? + } } + else + { + for (int i = 0; i < (data + 1) * 2; i++) + { + uint8_t ramdat = m_io.read_byte(m_spi_dma_addr++); + spibuf_w(ramdat); + } - logerror("%s: sfr_write (%02x) %02x\n", machine().describe_context(), offset, data); - axc51base_cpu_device::sfr_write(offset, data); + } } ROM_START( ax208 ) // assume all production ax208 chips use this internal ROM @@ -1226,12 +1540,31 @@ const tiny_rom_entry *ax208_cpu_device::device_rom_region() const void ax208_cpu_device::device_reset() { axc51base_cpu_device::device_reset(); - set_state_int(AXC51_PC, 0x8000); + set_state_int(SFR_STATEREG_PC, 0x8000); +} + + +// AX208 (specific CPU) - m_spiaddr = 0; +ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : axc51base_cpu_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(ax208_cpu_device::ax208_internal_program_mem), this), address_map_constructor(FUNC(ax208_cpu_device::data_internal), this), address_map_constructor(FUNC(axc51base_cpu_device::io_internal), this), 0, 8) +{ +} + +ax208_cpu_device::ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ax208_cpu_device(mconfig, AX208, tag, owner, clock) +{ } +std::unique_ptr ax208_cpu_device::create_disassembler() +{ + return std::make_unique(); +} + + + + ax208p_cpu_device::ax208p_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ax208_cpu_device(mconfig, AX208P, tag, owner, clock) { diff --git a/src/devices/cpu/axc51/axc51.h b/src/devices/cpu/axc51/axc51.h index 305eef8095f..445ceac60ac 100644 --- a/src/devices/cpu/axc51/axc51.h +++ b/src/devices/cpu/axc51/axc51.h @@ -1,58 +1,49 @@ // license:BSD-3-Clause -// copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud +// copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud, David Haywood -#ifndef MAME_CPU_AXC51_AXC51_H -#define MAME_CPU_AXC51_AXC51_H +#ifndef MAME_CPU_SFR_SFR_H +#define MAME_CPU_SFR_SFR_H #pragma once - -enum +// used for getting / setting current register state in debugger +enum { - AXC51_PC=1, AXC51_SP, AXC51_PSW, AXC51_ACC, AXC51_B, AXC51_DPTR, AXC51_DPH, AXC51_DPL, AXC51_IE, AXC51_IP, - AXC51_P0, AXC51_P1, AXC51_P2, AXC51_P3, - AXC51_R0, AXC51_R1, AXC51_R2, AXC51_R3, AXC51_R4, AXC51_R5, AXC51_R6, AXC51_R7, AXC51_RB, -}; + SFR_STATEREG_PC=1, SFR_STATEREG_SP, SFR_STATEREG_PSW, SFR_STATEREG_ACC, SFR_STATEREG_B, SFR_STATEREG_DPTR0, SFR_STATEREG_DPTR1, SFR_STATEREG_DPH0, SFR_STATEREG_DPL0, SFR_STATEREG_IE, SFR_STATEREG_IP, + SFR_STATEREG_P0, SFR_STATEREG_P1, SFR_STATEREG_P2, SFR_STATEREG_P3, + SFR_STATEREG_R0, SFR_STATEREG_R1, SFR_STATEREG_R2, SFR_STATEREG_R3, SFR_STATEREG_R4, SFR_STATEREG_R5, SFR_STATEREG_R6, SFR_STATEREG_R7, SFR_STATEREG_RB, -enum -{ - AXC51_INT0_LINE = 0, /* P3.2: External Interrupt 0 */ - AXC51_INT1_LINE, /* P3.3: External Interrupt 1 */ - AXC51_RX_LINE, /* P3.0: Serial Port Receive Line */ - AXC51_T0_LINE, /* P3,4: Timer 0 External Input */ - AXC51_T1_LINE, /* P3.5: Timer 1 External Input */ - AXC51_T2_LINE, /* P1.0: Timer 2 External Input */ - AXC51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */ + SFR_STATEREG_ER0, SFR_STATEREG_ER1, SFR_STATEREG_ER2, SFR_STATEREG_ER3, SFR_ER8, + SFR_STATEREG_GP0, SFR_STATEREG_GP1, SFR_STATEREG_GP2, SFR_STATEREG_GP3, SFR_STATEREG_GP4, SFR_STATEREG_GP5, SFR_STATEREG_GP6, SFR_STATEREG_GP7, }; - class axc51base_cpu_device : public cpu_device { public: - /* At least CMOS devices may be forced to read from ports configured as output. - * All you need is a low impedance output connect to the port. - */ - void set_port_forced_input(uint8_t port, uint8_t forced_input) { m_forced_inputs[port] = forced_input; } - template auto port_in_cb() { return m_port_in_cb[N].bind(); } template 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(); } + + template auto dac_out_cb() { return m_dac_out_cb[N].bind(); } + + + auto spi_in_cb() { return m_spi_in_cb.bind(); } + auto spi_out_cb() { return m_spi_out_cb.bind(); } + auto spi_out_dir_cb() { return m_spi_out_dir_cb.bind(); } void program_internal(address_map &map); void data_internal(address_map &map); + void io_internal(address_map &map); + protected: // construction/destruction axc51base_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); - axc51base_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); + axc51base_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, address_map_constructor io_map, int program_width, int data_width, uint8_t features = 0); // 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 + 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 20; } virtual uint32_t execute_input_lines() const noexcept override { return 6; } @@ -87,7 +78,8 @@ protected: 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 */ + uint16_t m_spi_dma_addr; + // JB-related hacks uint8_t m_last_op; @@ -95,48 +87,44 @@ protected: int m_icount; - struct axc51_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 m_sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */ - required_shared_ptr m_scratchpad; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */ + uint8_t m_sfr_regs[128]; + uint8_t m_xsfr_regs[128]; + required_shared_ptr m_scratchpad; + required_shared_ptr m_mainram; + + uint8_t m_uid[4]; /* SFR Callbacks */ - virtual void sfr_write(size_t offset, uint8_t data); - virtual uint8_t sfr_read(size_t offset); + void sfr_write(size_t offset, uint8_t data); + uint8_t sfr_read(size_t offset); /* Memory spaces */ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program; - memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific m_data; + memory_access<11, 0, 0, ENDIANNESS_LITTLE>::specific m_data; memory_access<17, 0, 0, ENDIANNESS_LITTLE>::specific m_io; - devcb_read8::array<4> m_port_in_cb; - devcb_write8::array<4> m_port_out_cb; + devcb_read8::array<5> m_port_in_cb; + devcb_write8::array<5> m_port_out_cb; + devcb_write8::array<2> m_dac_out_cb; + + devcb_read8 m_spi_in_cb; + devcb_write8 m_spi_out_cb; + devcb_write_line m_spi_out_dir_cb; - /* 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 // for the debugger uint8_t m_rtemp; static const uint8_t axc51_cycles[256]; - uint8_t iram_iread(offs_t a); - void iram_iwrite(offs_t a, uint8_t d); + uint8_t iram_indirect_read(offs_t a); + void iram_indirect_write(offs_t a, uint8_t d); + void clear_current_irq(); uint8_t r_acc(); uint8_t r_psw(); - virtual offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask); + 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(); @@ -146,18 +134,32 @@ protected: void bit_address_w(uint8_t offset, uint8_t bit); void do_add_flags(uint8_t a, uint8_t data, uint8_t c); void do_sub_flags(uint8_t a, uint8_t data, uint8_t c); - void transmit_receive(int source); - 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(); void burn_cycles(int cycles); + uint32_t process_dptr_access(); + uint32_t get_dptr0_with_autoinc(uint8_t auto_inc); + uint32_t get_dptr1_with_autoinc(uint8_t auto_inc); + uint8_t xsfr_read(offs_t offset); + void xsfr_write(offs_t offset, uint8_t data); + + uint8_t read_port(int i); + void write_port(int i, uint8_t data); + + uint8_t spicon_r(); + uint8_t spibuf_r(); + uint8_t dpcon_r(); + uint8_t uartsta_r(); + + void spidmaadr_w(uint8_t data); + void spidmacnt_w(uint8_t data); + + void spicon_w(uint8_t data); + void spibuf_w(uint8_t data); + void spibaud_w(uint8_t data); + void dpcon_w(uint8_t data); + void ie2crypt_w(uint8_t data); + void acall(uint8_t r); void add_a_byte(uint8_t r); void add_a_mem(uint8_t r); @@ -271,146 +273,241 @@ protected: void xrl_a_r(uint8_t r); void illegal(uint8_t r); + void do_ez_flags(uint16_t val); + void do_ec_ez_flags(uint32_t res); + + void axc51_extended_a5(uint8_t r); + void extended_a5_0e(); + void extended_a5_0f(); + void extended_a5_d0(); + void extended_a5_d1(); + + uint16_t get_erx(int m); + void set_erx(int n, uint16_t val); + uint16_t get_dpt(int i); + + /* Internal address in SFR of registers, these map at 0x80, so SFR_P0 is at 0x80 etc. */ + enum + { + SFR_P0 = 0x00, + SFR_SP = 0x01, // SPL + SFR_DPL0 = 0x02, // DPL00 + SFR_DPH0 = 0x03, // DPH00 + SFR_DPL1 = 0x04, + SFR_DPH1 = 0x05, + SFR_DPCON = 0x06, + SFR_PCON = 0x07, // PCON0 + SFR_SDCON0 = 0x08, // not SFR_TCON + SFR_SDCON1 = 0x09, // not SFR_TMOD + SFR_SDCON2 = 0x0a, // not SFR_TL0 + SFR_JPGCON4 = 0x0b, // not SFR_TL1 + SFR_JPGCON3 = 0x0c, // not SFR_TH0 + SFR_JPGCON2 = 0x0d, // not SFR_TH1 + SFR_JPGCON1 = 0x0e, + SFR_TRAP = 0x0f, + SFR_P1 = 0x10, + SFR_SDBAUD = 0x11, + SFR_SDCPTR = 0x12, + SFR_SDDCNT = 0x13, + SFR_SDDPTR = 0x14, + SFR_IE2CRPT = 0x15, // controls automatic encryption + SFR_UARTBAUDH = 0x16, + SFR_PWKEN = 0x17, + SFR_PWKPND = 0x18, // not SFR_SCON + SFR_PWKEDGE = 0x19, // not SFR_SBUF + SFR_PIE0 = 0x1a, + SFR_DBASE = 0x1b, + SFR_PCON1 = 0x1c, + SFR_PIE1 = 0x1d, + SFR_IRTDATA = 0x1e, + SFR_IRTCON = 0x1f, + SFR_P2 = 0x20, + SFR_GP0 = 0x21, + SFR_GP1 = 0x22, + SFR_GP2 = 0x23, + SFR_GP3 = 0x24, + SFR_DACCON = 0x25, + SFR_DACLCH = 0x26, + SFR_DACRCH = 0x27, + SFR_IE = 0x28, // IE0 + SFR_IE1 = 0x29, + SFR_KEY0 = 0x2a, + SFR_KEY1 = 0x2b, + SFR_TMR3CON = 0x2c, + SFR_TMR3CNT = 0x2d, + SFR_TMR3PR = 0x2e, + SFR_TMR3PSR = 0x2f, + SFR_P3 = 0x30, + SFR_GP4 = 0x31, + SFR_GP5 = 0x32, + SFR_GP6 = 0x33, + SFR_P4 = 0x34, + SFR_GP7 = 0x35, + SFR_LCDCON = 0x36, + SFR_PLLCON = 0x37, + SFR_IP = 0x38, // IP0 + SFR_IP1 = 0x39, + SFR_P0DIR = 0x3a, + SFR_P1DIR = 0x3b, + SFR_P2DIR = 0x3c, + SFR_P3DIR = 0x3d, + SFR_P4DIR = 0x3e, + SFR_LVDCON = 0x3f, + SFR_JPGCON0 = 0x40, + SFR_TMR2CON = 0x41, + SFR_JPGCON9 = 0x42, + SFR_JPGCON5 = 0x43, + SFR_JPGCON6 = 0x44, + SFR_JPGCON7 = 0x45, + SFR_JPGCON8 = 0x46, + SFR_LCDPR = 0x47, + SFR_LCDTCON = 0x48, + SFR_USBCON0 = 0x49, + SFR_USBCON1 = 0x4a, + SFR_USBCON2 = 0x4b, + SFR_USBDATA = 0x4c, + SFR_USBADR = 0x4d, + SFR_ILLEGAL = 0x4e, + SFR_MICCON = 0x4f, + SFR_PSW = 0x50, + SFR_PGCON = 0x51, + SFR_ADCCON = 0x52, + SFR_PCON2 = 0x53, + SFR_ADCDATAL = 0x54, + SFR_ADCDATAH = 0x55, + SFR_SPIDMAADR = 0x56, + SFR_SPIDMACNT = 0x57, + SFR_SPICON = 0x58, + SFR_SPIBUF = 0x59, + SFR_SPIBAUD = 0x5a, + SFR_CLKCON = 0x5b, + SFR_CLKCON1 = 0x5c, + SFR_USBDPDM = 0x5d, + SFR_LFSRPOLY0 = 0x5e, + SFR_LFSRPOLY1 = 0x5f, + SFR_ACC = 0x60, + SFR_TMR1CON = 0x61, + SFR_UID0 = 0x62, + SFR_UID1 = 0x63, + SFR_UID2 = 0x64, + SFR_UID3 = 0x65, + SFR_ER00 = 0x66, + SFR_ER01 = 0x67, + SFR_ER10 = 0x68, + SFR_ER11 = 0x69, + SFR_ER20 = 0x6a, + SFR_ER21 = 0x6b, + SFR_ER30 = 0x6c, + SFR_ER31 = 0x6d, + SFR_ER8 = 0x6e, + SFR_ILLEGAL2 = 0x6f, + SFR_B = 0x70, + SFR_HUFFBUF = 0x71, + SFR_HUFFSFT = 0x72, + SFR_HUFFDCL = 0x73, + SFR_HUFFDCH = 0x74, + SFR_CRC = 0x75, + SFR_LFSRFIFO = 0x76, + SFR_WDTCON = 0x77, + SFR_TMR0CON = 0x78, + SFR_TMR0CNT = 0x79, + SFR_TMR0PR = 0x7a, + SFR_TMR0PSR = 0x7b, + SFR_UARTSTA = 0x7c, + SFR_UARTCON = 0x7d, + SFR_UARTBAUD = 0x7e, + SFR_UARTDATA = 0x7f, + }; - /* Internal address in SFR of registers */ + // XSFR regs map at 0x3000, so XSFR_PUP0 at is 0x3010 etc. enum { - ADDR_P0 = 0x80, - ADDR_SP = 0x81, // SPL - ADDR_DPL = 0x82, // DPL0 - ADDR_DPH = 0x83, // DPH0 - AXC51_DPL1 = 0x84, - AXC51_DPH1 = 0x85, - AXC51_DPCON = 0x86, - ADDR_PCON = 0x87, // PCON0 - AXC51_SDCON0 = 0x88, // not ADDR_TCON = 0x88, - AXC51_SDCON1 = 0x89, // not ADDR_TMOD = 0x89, - AXC51_SDCON2 = 0x8a, // not ADDR_TL0 = 0x8a, - AXC51_JPGCON4 = 0x8b, // not ADDR_TL1 = 0x8b, - AXC51_JPGCON3 = 0x8c, // not ADDR_TH0 = 0x8c, - AXC51_JPGCON2 = 0x8d, // not ADDR_TH1 = 0x8d, - AXC51_JPGCON1 = 0x8e, - AXC51_TRAP = 0x8f, - ADDR_P1 = 0x90, - AXC51_SDBAUD = 0x91, - AXC51_SDCPTR = 0x92, - AXC51_SDDCNT = 0x93, - AXC51_SDDPTR = 0x94, - AXC51_IE2CRPT = 0x95, // controls automatic encryption - AXC51_UARTBAUDH = 0x96, - AXC51_PWKEN = 0x97, - AXC51_PWKPND = 0x98, // not ADDR_SCON = 0x98, - AXC51_PWKEDGE = 0x99, // not ADDR_SBUF = 0x99, - AXC51_PIE0 = 0x9a, - AXC51_DBASE = 0x9b, - AXC51_PCON1 = 0x9c, - AXC51_PIE1 = 0x9d, - AXC51_IRTDATA = 0x9e, - AXC51_IRTCON = 0x9f, - ADDR_P2 = 0xa0, - AXC51_GP0 = 0xa1, - AXC51_GP1 = 0xa2, - AXC51_GP2 = 0xa3, - AXC51_GP3 = 0xa4, - AXC51_DACCON = 0xa5, - AXC51_DACLCH = 0xa6, - AXC51_DACRCH = 0xa7, - ADDR_IE = 0xa8, // IE0 - AXC51_IE1 = 0xa9, - AXC51_KEY0 = 0xaa, - AXC51_KEY1 = 0xab, - AXC51_TMR3CON = 0xac, - AXC51_TMR3CNT = 0xad, - AXC51_TMR3PR = 0xae, - AXC51_TMR3PSR = 0xaf, - ADDR_P3 = 0xb0, - AXC51_GP4 = 0xb1, - AXC51_GP5 = 0xb2, - AXC51_GP6 = 0xb3, - AXC51_P4 = 0xb4, - AXC51_GP7 = 0xb5, - AXC51_LCDCON = 0xb6, - AXC51_PLLCON = 0xb7, - ADDR_IP = 0xb8, // IP0 - AXC51_IP1 = 0xb9, - AXC51_P0DIR = 0xba, - AXC51_P1DIR = 0xbb, - AXC51_P2DIR = 0xbc, - AXC51_P3DIR = 0xbd, - AXC51_P4DIR = 0xbe, - AXC51_LVDCON = 0xbf, - AXC51_JPGCON0 = 0xc0, - AXC51_TMR2CON = 0xc1, - AXC51_JPGCON9 = 0xc2, - AXC51_JPGCON5 = 0xc3, - AXC51_JPGCON6 = 0xc4, - AXC51_JPGCON7 = 0xc5, - AXC51_JPGCON8 = 0xc6, - AXC51_LCDPR = 0xc7, - AXC51_LCDTCON = 0xc8, - AXC51_USBCON0 = 0xc9, - AXC51_USBCON1 = 0xca, - AXC51_USBCON2 = 0xcb, - AXC51_USBDATA = 0xcc, - AXC51_USBADR = 0xcd, - AXC51_ILLEGAL = 0xce, - AXC51_MICCON = 0xcf, - ADDR_PSW = 0xd0, - AXC51_PGCON = 0xd1, - AXC51_ADCCON = 0xd2, - AXC51_PCON2 = 0xd3, - AXC51_ADCDATAL = 0xd4, - AXC51_ADCDATAH = 0xd5, - AXC51_SPIDMAADR = 0xd6, - AXC51_SPIDMACNT = 0xd7, - AXC51_SPICON = 0xd8, - AXC51_SPIBUF = 0xd9, - AXC51_SPIBAUD = 0xda, - AXC51_CLKCON = 0xdb, - AXC51_CLKCON1 = 0xdc, - AXC51_USBDPDM = 0xdd, - AXC51_LFSRPOLY0 = 0xde, - AXC51_LFSRPOLY1 = 0xdf, - ADDR_ACC = 0xe0, - AXC51_TMR1CON = 0xe1, - AXC51_UID0 = 0xe2, - AXC51_UID1 = 0xe3, - AXC51_UID2 = 0xe4, - AXC51_UID3 = 0xe5, - AXC51_ER00 = 0xe6, - AXC51_ER01 = 0xe7, - AXC51_ER10 = 0xe8, - AXC51_ER11 = 0xe9, - AXC51_ER20 = 0xea, - AXC51_ER21 = 0xeb, - AXC51_ER30 = 0xec, - AXC51_ER31 = 0xed, - AXC51_ER8 = 0xee, - AXC51_ILLEGAL2 = 0xef, - ADDR_B = 0xf0, - AXC51_HUFFBUF = 0xf1, - AXC51_HUFFSFT = 0xf2, - AXC51_HUFFDCL = 0xf3, - AXC51_HUFFDCH = 0xf4, - AXC51_CRC = 0xf5, - AXC51_LFSRFIFO = 0xf6, - AXC51_WDTCON = 0xf7, - AXC51_TMR0CON = 0xf8, - AXC51_TMR0CNT = 0xf9, - AXC51_TMR0PR = 0xfa, - AXC51_TMR0PSR = 0xfb, - AXC51_UARTSTA = 0xfc, - AXC51_UARTCON = 0xfd, - AXC51_UARTBAUD = 0xfe, - AXC51_UARTDATA = 0xff, + XSFR_PUP0 = 0x10, + XSFR_PUP1 = 0x11, + XSFR_PUP2 = 0x12, + XSFR_PUP3 = 0x13, + XSFR_PUP4 = 0x14, + XSFR_PDN0 = 0x15, + XSFR_PDN1 = 0x16, + XSFR_PDN2 = 0x17, + XSFR_PDN3 = 0x18, + XSFR_PDN4 = 0x19, + XSFR_PHD0 = 0x1a, + XSFR_PHD1 = 0x1b, + XSFR_PHD2 = 0x1c, + XSFR_PHD3 = 0x1d, + XSFR_PHD4 = 0x1e, + + XSFR_TMR1CNTL = 0x20, // Timer 1 Counter (low) + XSFR_TMR1CNTH = 0x21, // Timer 1 Counter (high) + XSFR_TMR1PRL = 0x22, // Timer 1 Period (low) + XSFR_TMR1PRH = 0x23, // Timer 1 Period (high) + XSFR_TMR1PWML = 0x24, // Timer 1 Duty (low) + XSFR_TMR1PWMH = 0x25, // Timer 1 Duty (high) + + XSFR_TMR2CNTL = 0x30, // Timer 2 Counter (low) + XSFR_TMR2CNTH = 0x31, // Timer 2 Counter (high) + XSFR_TMR2PRL = 0x32, // Timer 2 Period (low) + XSFR_TMR2PRH = 0x33, // Timer 2 Period (high) + XSFR_TMR2PWML = 0x34, // Timer 2 Duty (low) + XSFR_TMR2PWMH = 0x35, // Timer 2 Duty (high) + + XSFR_ADCBAUD = 0x40, // ARADC Baud + + XSFR_USBEP0ADL = 0x50, + XSFR_USBEP0ADH = 0x51, + XSFR_USBEP1RXADL = 0x52, + XSFR_USBEP1RXADH = 0x53, + XSFR_USBEP1TXADL = 0x54, + XSFR_USBEP1TXADH = 0x55, + XSFR_USBEP2RXADL = 0x56, + XSFR_USBEP2RXADH = 0x57, + XSFR_USBEP2TXADL = 0x58, + XSFR_USBEP2TXADH = 0x59, + + XSFR_SFSCON = 0x60, + XSFR_SFSPID = 0x61, + XSFR_SFSCNTH = 0x62, + XSFR_SFSCNTL = 0x63, + + XSFR_DACPTR = 0x70, // DAC DMA Pointer + XSFR_DACCNT = 0x71, // DAC DMA Counter }; enum { + // always at 8000 V_RESET = 0x000, /* power on address */ - V_IE0 = 0x003, /* External Interrupt 0 */ + // below can be at 4000 or 8000 (although don't make sense for internal ROM at 8000?) + V_TIMER0 = 0x003, // IE0.0 IP0.0 + V_TIMER1 = 0x00b, // IE0.1 IP0.1 + V_TIMER2 = 0x013, // IE0.2 IP0.2 + V_TIMER3 = 0x01b, // IE0.3 IP0.3 + V_USB = 0x023, // IE0.4 IP0.4 + V_SPI = 0x02b, // IE0.5 IP0.5 + V_SDC = 0x033, // IE0.6 IP0.6 + V_SOFT = 0x03b, // IE2.4 IP0.7 IE2 is the 'encrypt' register + V_HUFFEMPTY = 0x043, // IE1.0 IP1.0 + V_IDCT = 0x04b, // IE1.1 IP1.1 + V_YUV2RGB = 0x053, // IE1.2 IP1.2 + V_PORT = 0x05b, // IE1.3 IP1.3 + V_WDT_LVD = 0x063, // IE1.4 IP1.4 Watchdog also needs to be enabled with IE2.5? LVD with LVDCON.5? + V_IRTCC_UART = 0x06b, // IE1.5 IP1.5 + V_DAC = 0x073, // IE1.6 IP1.6 + V_SFS_INT = 0x07b, // IE1.7 IP1.7 }; + uint16_t get_irq_base(); + + TIMER_CALLBACK_MEMBER(timer0_cb); + TIMER_CALLBACK_MEMBER(dactimer_cb); + + bool m_timer0irq = false; + bool m_dactimerirq = false; + + + emu_timer *m_timer0; + emu_timer *m_dactimer; }; @@ -424,8 +521,6 @@ public: // construction/destruction ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void set_spi_ptr(uint8_t* ptr, size_t size) { m_spiptr = ptr; m_spisize = size; } - protected: ax208_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -435,28 +530,6 @@ protected: virtual const tiny_rom_entry *device_rom_region() const override; void ax208_internal_program_mem(address_map &map); - - virtual void sfr_write(size_t offset, uint8_t data) override; - virtual uint8_t sfr_read(size_t offset) override; - - uint8_t spicon_r(); - uint8_t spibuf_r(); - uint8_t dpcon_r(); - - void spidmaadr_w(uint8_t data); - void spidmacnt_w(uint8_t data); - - void spicon_w(uint8_t data); - void spibuf_w(uint8_t data); - void spibaud_w(uint8_t data); - void dpcon_w(uint8_t data); - - uint8_t* m_spiptr; - size_t m_spisize; - - uint32_t m_spiaddr; - - virtual offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask) override; }; class ax208p_cpu_device : public ax208_cpu_device @@ -470,4 +543,4 @@ protected: }; -#endif // MAME_CPU_AXC51_AXC51_H +#endif // MAME_CPU_SFR_SFR_H diff --git a/src/devices/cpu/axc51/axc51dasm.cpp b/src/devices/cpu/axc51/axc51dasm.cpp index c30166f7a2a..e3c94e53436 100644 --- a/src/devices/cpu/axc51/axc51dasm.cpp +++ b/src/devices/cpu/axc51/axc51dasm.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Steve Ellenoff +// copyright-holders:Steve Ellenoff, David Haywood #include "emu.h" #include "axc51dasm.h" @@ -150,7 +150,7 @@ std::string axc51_disassembler::get_bit_address( uint8_t arg ) const { if(arg < 0x80) { - //Bit address 0-7F can be referred to as 20.0, 20.1, to 20.7 for address 0, and 2f.0,2f.1 to 2f.7 for address 7f + //Bit address 0-7f can be referred to as 20.0, 20.1, to 20.7 for address 0, and 2f.0,2f.1 to 2f.7 for address 7f return util::string_format("$%02X.%d", (arg >> 3) | 0x20, arg & 0x07); } else @@ -1025,12 +1025,12 @@ const axc51core_disassembler::mem_info axc51core_disassembler::axc51core_names[] { 0x87, "PCON0" }, // Power Control 0 { 0x88, "SDCON0" }, { 0x89, "SDCON1" }, - { 0x8A, "SDCON2" }, - { 0x8B, "JPGCON4" }, - { 0x8C, "JPGCON3" }, - { 0x8D, "JPGCON2" }, - { 0x8E, "JPGCON1" }, - { 0x8F, "TRAP" }, + { 0x8a, "SDCON2" }, + { 0x8b, "JPGCON4" }, + { 0x8c, "JPGCON3" }, + { 0x8d, "JPGCON2" }, + { 0x8e, "JPGCON1" }, + { 0x8f, "TRAP" }, { 0x90, "P1" }, { 0x91, "SDBAUD" }, { 0x92, "SDCPTR" }, @@ -1041,108 +1041,108 @@ const axc51core_disassembler::mem_info axc51core_disassembler::axc51core_names[] { 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 + { 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 diff --git a/src/devices/cpu/axc51/axc51dasm.h b/src/devices/cpu/axc51/axc51dasm.h index 95521f6e9f1..a5b66315bbc 100644 --- a/src/devices/cpu/axc51/axc51dasm.h +++ b/src/devices/cpu/axc51/axc51dasm.h @@ -1,8 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Steve Ellenoff +// copyright-holders:Steve Ellenoff, David Haywood -#ifndef MAME_CPU_AXC51_AXC51DASM_H -#define MAME_CPU_AXC51_AXC51DASM_H +#ifndef MAME_CPU_SFR_AXC51DASM_H +#define MAME_CPU_SFR_AXC51DASM_H #pragma once diff --git a/src/devices/cpu/axc51/axc51extops.hxx b/src/devices/cpu/axc51/axc51extops.hxx new file mode 100644 index 00000000000..b0095036a6f --- /dev/null +++ b/src/devices/cpu/axc51/axc51extops.hxx @@ -0,0 +1,694 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +void axc51base_cpu_device::do_ez_flags(uint16_t val) +{ + if (!val) + SET_EZ(1); + else + SET_EZ(0); +} + +void axc51base_cpu_device::do_ec_ez_flags(uint32_t res) +{ + if (res & 0xffff0000) + SET_EC(1); + else + SET_EC(0); + + res &= 0xffff; + + if (!res) + SET_EZ(1); + else + SET_EZ(0); +} + +uint16_t axc51base_cpu_device::get_erx(int m) +{ + switch (m & 3) + { + case 0x00: return (ER0); + case 0x01: return (ER1); + case 0x02: return (ER2); + case 0x03: return (ER3); + } + return 0; +} + +void axc51base_cpu_device::set_erx(int n, uint16_t val) +{ + switch (n & 3) + { + case 0x00: SET_ER0(val); break; + case 0x01: SET_ER1(val); break; + case 0x02: SET_ER2(val); break; + case 0x03: SET_ER3(val); break; + } +} + +uint16_t axc51base_cpu_device::get_dpt(int i) +{ + switch (i & 1) + { + case 0x00: return DPTR0; break; + case 0x01: return DPTR1; break; + } + return 0x0000; +} + +void axc51base_cpu_device::axc51_extended_a5(uint8_t r) +{ + uint8_t prm = m_program.read_byte(m_pc++); + + switch (prm) + { + case 0x00: + { + // INCDP0 + uint16_t dptr = (DPTR0)+1; + SET_DPTR0(dptr); + break; + } + + case 0x01: + { + // INCDP1 + uint16_t dptr = (DPTR1)+1; + SET_DPTR1(dptr); + break; + } + + case 0x02: + { + // DECDP0 + uint16_t dptr = (DPTR0)-1; + SET_DPTR0(dptr); + break; + } + + case 0x03: + { + // DECDP1 + uint16_t dptr = (DPTR1)-1; + SET_DPTR1(dptr); + break; + } + + case 0x04: + { + // ADDDP0 + uint16_t increment = (B) | ((ER8) << 8); + uint16_t dptr = (DPTR0)+increment; + SET_DPTR0(dptr); + + break; + } + + case 0x05: + fatalerror("%s: ADDDP1", machine().describe_context()); + break; + + case 0x06: + fatalerror("%s: SUBDP0", machine().describe_context()); + break; + + case 0x07: + fatalerror("%s: SUBDP1", machine().describe_context()); + break; + + case 0x08: + { + // INC2DP0 + uint16_t dptr = (DPTR0)+2; + SET_DPTR0(dptr); + break; + } + + case 0x09: + fatalerror("%s: INC2DP1", machine().describe_context()); + break; + + case 0x0a: + { + // DEC2DP0 + uint16_t dptr = (DPTR0)-2; + SET_DPTR0(dptr); + break; + } + + case 0x0b: + fatalerror("%s: DEC2DP1", machine().describe_context()); + break; + + case 0x0c: + { + // ROTR8 EACC, ER8 + uint8_t acc = ACC; + uint8_t shift = (ER8) & 0x7; + uint8_t newacc = (acc >> shift) | (acc << (8 - shift)); + SET_ACC(newacc); + + break; + } + + case 0x0d: + { + // ROTL8 EACC, ER8 + uint8_t acc = ACC; + uint8_t shift = (ER8) & 0x7; + uint8_t newacc = (acc << shift) | (acc >> (8 - shift)); + SET_ACC(newacc); + + break; + } + + case 0x0e: // ADD16 + extended_a5_0e(); + break; + + case 0x0f: // SUB16 + extended_a5_0f(); + break; + + case 0x10: case 0x14: case 0x18: case 0x1c: + { + uint8_t n = (prm & 0x0c) >> 2; + fatalerror("%s: NOT16 ER%01x", machine().describe_context(), n); + break; + } + + case 0x11: case 0x15: case 0x19: case 0x1d: + { + uint8_t n = (prm & 0x0c) >> 2; + fatalerror("%s: CLR16 ER%01x", machine().describe_context(), n); + break; + } + + case 0x12: case 0x16: case 0x1a: case 0x1e: + { + // INC16 ERn + uint8_t n = (prm & 0x0c) >> 2; + + uint16_t val = get_erx(n); + val = val + 1; + set_erx(n, val); + + do_ez_flags(val); + + break; + } + + case 0x13: case 0x17: case 0x1b: case 0x1f: + { + // DEC16 ERn + uint8_t n = (prm & 0x0c) >> 2; + + uint16_t val = get_erx(n); + val = val - 1; + set_erx(n, val); + + do_ez_flags(val); + + 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; + + fatalerror("%s: ANL16 ER%01x, EDP%01x", machine().describe_context(), 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; + + fatalerror("%s: ANL16 EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: ANL16 ER%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: ORL16 ER%01x, EDP%01x", machine().describe_context(), 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; + + fatalerror("%s: ORL16 EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: ORL16 ER%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: XRL16 ER%01x, EDP%01x", machine().describe_context(), 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; + + fatalerror("%s: XRL16 EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: XRL16 ER%01x, ER%01x", machine().describe_context(), n, m); + break; + } + + case 0x80: case 0x81: case 0x84: case 0x85: case 0x88: case 0x89: case 0x8c: case 0x8d: + { + // MOV16 ERn, DPTRi + + uint8_t n = (prm & 0x0c) >> 2; + uint8_t i = (prm & 0x01) >> 0; + + uint16_t dpt = get_dpt(i); + uint16_t val = m_io.read_word(dpt); + + set_erx(n, val); + + do_ez_flags(val); + + break; + } + + case 0x82: case 0x83: case 0x86: case 0x87: case 0x8a: case 0x8b: case 0x8e: case 0x8f: + { + // MOV16 DPTRi, ERn + uint8_t n = (prm & 0x0c) >> 2; + uint8_t i = (prm & 0x01) >> 0; + + uint16_t dpt = get_dpt(i); + uint16_t val = get_erx(n); + + m_io.write_word(dpt, val); + + do_ez_flags(val); + + 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: + { + // MOV16 ERn, ERm + uint8_t n = (prm & 0x0c) >> 2; + uint8_t m = (prm & 0x03) >> 0; + + uint16_t val = get_erx(m); + set_erx(n, val); + + do_ez_flags(val); + + 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: + { + // MUL16 ERn, ERm; + + uint8_t n = (prm & 0x0c) >> 2; + uint8_t m = (prm & 0x03) >> 0; + + int16_t a = (int16_t)get_erx(n); + int16_t b = (int16_t)get_erx(m); + + int32_t res = a * b; + uint32_t res2 = (uint32_t)res; + + set_erx(n, (res2 >> 16)); + set_erx(m, (res2 & 0xffff)); + + 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; + + fatalerror("%s: MULS16 ER%01x, ER%01x", machine().describe_context(), n, m); + break; + } + + case 0xc0: case 0xc4: case 0xc8: case 0xcc: + { + // ROTR16 ERn, ER8 + uint8_t n = (prm & 0x0c) >> 2; + uint16_t val = get_erx(n); + uint8_t shift = (ER8) & 0xf; + uint16_t newval = (val >> shift) | (val << (16 - shift)); + set_erx(n, newval); + + break; + } + + case 0xc1: case 0xc5: case 0xc9: case 0xcd: + { + // ROTL16 ERn, ER8 + uint8_t n = (prm & 0x0c) >> 2; + uint16_t val = get_erx(n); + uint8_t shift = (ER8) & 0xf; + uint16_t newval = (val << shift) | (val >> (16 - shift)); + set_erx(n, newval); + + break; + } + + case 0xc2: case 0xc6: case 0xca: case 0xce: + { + // SHIFTL ERn, ER8 + uint8_t n = (prm & 0x0c) >> 2; + + uint16_t val = get_erx(n); + uint8_t shift = (ER8) & 0xf; + + uint16_t newval = val >> shift; + set_erx(n, newval); + + break; + } + + case 0xc3: case 0xc7: case 0xcb: case 0xcf: + { + uint8_t n = (prm & 0x0c) >> 2; + fatalerror("%s: SHIFTA ER%01x, ER8", machine().describe_context(), n); + break; + } + + case 0xd0: // ADDS16 + extended_a5_d0(); + break; + + case 0xd1: // SUBS16 + extended_a5_d1(); + break; + + case 0xd2: case 0xd6: case 0xda: case 0xde: + { + // SWAP16 ERn + uint8_t n = (prm & 0x0c) >> 2; + uint16_t val = get_erx(n); + uint16_t newval = (val << 8) | (val >> 8); + set_erx(n, newval); + break; + } + + case 0xd3: case 0xd4: case 0xd5: case 0xd7: case 0xd8: case 0xd9: case 0xdb: case 0xdc: case 0xdd: case 0xdf: + fatalerror("%s: invalid ax208 a5 $%02X", machine().describe_context(), 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: + fatalerror("%s: invalid ax208 a5 $%02X", machine().describe_context(), 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: + fatalerror("%s: invalid ax208 a5 $%02X", machine().describe_context(), prm); + break; + + default: + fatalerror("%s: unknown ax208 a5 $%02X", machine().describe_context(), prm); + break; + } +} + + +void axc51base_cpu_device::extended_a5_0e() +{ + uint8_t prm2 = m_program.read_byte(m_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; + + fatalerror("%s: ADD16 ER%01x, EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: ADD16 EDP%01x, ER%01x, ER%01x", machine().describe_context(), 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: + { + // ADD16 ERp, ERn, ERm + + uint8_t p = (prm2 & 0x30) >> 4; + uint8_t n = (prm2 & 0x0c) >> 2; + uint8_t m = (prm2 & 0x03) >> 0; + + uint16_t val = get_erx(n); + uint16_t val2 = get_erx(m); + uint32_t res = val + val2 + (GET_EC); + set_erx(p, res); + + do_ec_ez_flags(res); + + break; + } + + default: + fatalerror("%s: illegal ax208 a5 0e $%02X", machine().describe_context(), prm2); + break; + } +} + +void axc51base_cpu_device::extended_a5_0f() +{ + uint8_t prm2 = m_program.read_byte(m_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: + { + // SUB16 ERp, EDPi, ERn + + uint8_t p = (prm2 & 0x30) >> 4; + uint8_t n = (prm2 & 0x0c) >> 2; + uint8_t i = (prm2 & 0x01) >> 0; + + uint16_t dpt = get_dpt(i); + uint16_t val = m_io.read_word(dpt); + uint16_t val2 = get_erx(n); + + uint32_t res = val - val2 - (GET_EC); + set_erx(p, res); + + do_ec_ez_flags(res); + + 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: + { + // SUB16 EDPi, ERn, ERp; + uint8_t p = (prm2 & 0x30) >> 4; + uint8_t n = (prm2 & 0x0c) >> 2; + uint8_t i = (prm2 & 0x01) >> 0; + + uint16_t val = get_erx(n); + uint16_t val2 = get_erx(p); + uint16_t dpt = get_dpt(i); + uint32_t res = val - val2 - (GET_EC); + + m_io.write_word(dpt, res); + + do_ec_ez_flags(res); + + 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: + { + // SUB16 ERp, ERn, ERm + + uint8_t p = (prm2 & 0x30) >> 4; + uint8_t n = (prm2 & 0x0c) >> 2; + uint8_t m = (prm2 & 0x03) >> 0; + + uint16_t val = get_erx(n); + uint16_t val2 = get_erx(m); + uint32_t res = val - val2 - (GET_EC); + set_erx(p, res); + + do_ec_ez_flags(res); + + break; + } + + + default: + fatalerror("%s: illegal ax208 a5 0f $%02X", machine().describe_context(), prm2); + break; + } +} + +void axc51base_cpu_device::extended_a5_d0() +{ + uint8_t prm2 = m_program.read_byte(m_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; + + fatalerror("%s: ADDS16 ER%01x, EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: ADDS16 EDP%01x, ER%01x, ER%01x", machine().describe_context(), 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; + fatalerror("%s: ADDS16 ER%01x, ER%01x, ER%01x", machine().describe_context(), p, n, m); + break; + } + + default: + fatalerror("%s: illegal ax208 a5 d0 $%02X", machine().describe_context(), prm2); + break; + } +} + +void axc51base_cpu_device::extended_a5_d1() +{ + uint8_t prm2 = m_program.read_byte(m_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; + + fatalerror("%s: SUBS16 ER%01x, EDP%01x, ER%01x", machine().describe_context(), 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; + + fatalerror("%s: SUBS16 EDP%01x, ER%01x, ER%01x", machine().describe_context(), 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; + fatalerror("%s: SUBS16 ER%01x, ER%01x, ER%01x", machine().describe_context(), p, n, m); + break; + } + + default: + fatalerror("%s: illegal ax208 a5 d1 $%02X", machine().describe_context(), prm2); + break; + } +} diff --git a/src/devices/cpu/axc51/axc51ops.hxx b/src/devices/cpu/axc51/axc51ops.hxx index 99917328232..b752733c420 100644 --- a/src/devices/cpu/axc51/axc51ops.hxx +++ b/src/devices/cpu/axc51/axc51ops.hxx @@ -3,174 +3,174 @@ /******************************************************************************************* NOTE: All registers are accessed directly, instead of using the SFR_R() function for speed Direct register access is availabe from the R_(register name) macros.. ex: ACC for the ACC - with the exception of the PC + with the exception of the m_pc ********************************************************************************************/ //ACALL code addr /* 1: aaa1 0001 */ -OPHANDLER( acall ) +void axc51base_cpu_device::acall(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab code address byte - PUSH_PC(); //Save PC to the stack + uint8_t addr = m_program.read_byte(m_pc++); //Grab code address byte + push_pc(); //Save m_pc to the stack //Thanks Gerrit for help with this! :) - PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr; + m_pc = (m_pc & 0xf800) | ((r & 0xe0) << 3) | addr; } //ADD A, #data /* 1: 0010 0100 */ -OPHANDLER( add_a_byte ) +void axc51base_cpu_device::add_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_pc++); //Grab data uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + 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 ) +void axc51base_cpu_device::add_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); //Grab data from data address uint8_t result = ACC + data; //Add data to accumulator - DO_ADD_FLAGS(ACC,data,0); //Set Flags + 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 ) +void axc51base_cpu_device::add_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t data = iram_indirect_read(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 + 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 ) +void axc51base_cpu_device::add_a_r(uint8_t 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 + 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 ) +void axc51base_cpu_device::addc_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_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 + 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 ) +void axc51base_cpu_device::addc_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 + 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 ) +void axc51base_cpu_device::addc_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t data = iram_indirect_read(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 + 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 ) +void axc51base_cpu_device::addc_a_r(uint8_t 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 + 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 ) +void axc51base_cpu_device::ajmp(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab code address byte + uint8_t addr = m_program.read_byte(m_pc++); //Grab code address byte //Thanks Gerrit for help with this! :) - PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr; + m_pc = (m_pc & 0xf800) | ((r & 0xe0) << 3) | addr; } //ANL data addr, A /* 1: 0101 0010 */ -OPHANDLER( anl_mem_a ) +void axc51base_cpu_device::anl_mem_a(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::anl_mem_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + uint8_t srcdata = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::anl_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_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 ) +void axc51base_cpu_device::anl_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 ) +void axc51base_cpu_device::anl_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + uint8_t data = iram_indirect_read(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 ) +void axc51base_cpu_device::anl_a_r(uint8_t 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 } //ANL C, bit addr /* 1: 1000 0010 */ -OPHANDLER( anl_c_bitaddr ) +void axc51base_cpu_device::anl_c_bitaddr(uint8_t r) { 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + uint8_t bit = bit_address_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 ) +void axc51base_cpu_device::anl_c_nbitaddr(uint8_t r) { 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + uint8_t bit = bit_address_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 ) +void axc51base_cpu_device::cjne_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address if(ACC != data) //Jump if values are not equal { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value @@ -178,15 +178,15 @@ OPHANDLER( cjne_a_byte ) } //CJNE A, data addr, code addr /* 1: 1011 0101 */ -OPHANDLER( cjne_a_mem ) +void axc51base_cpu_device::cjne_a_mem(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + uint8_t data = iram_read(addr); //Pull value from data address if(ACC != data) //Jump if values are not equal { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value @@ -194,15 +194,15 @@ OPHANDLER( cjne_a_mem ) } //CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */ -OPHANDLER( cjne_ir_byte ) +void axc51base_cpu_device::cjne_ir_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + uint8_t srcdata = iram_indirect_read(R_REG(r)); //Grab value pointed to by R0 or R1 if(srcdata != data) //Jump if values are not equal { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value @@ -210,15 +210,15 @@ OPHANDLER( cjne_ir_byte ) } //CJNE R0 to R7, #data, code addr /* 1: 1011 1rrr */ -OPHANDLER( cjne_r_byte ) +void axc51base_cpu_device::cjne_r_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + int8_t rel_addr = m_program.read_byte(m_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 { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } //Set carry flag to 1 if 1st compare value is < 2nd compare value @@ -226,48 +226,48 @@ OPHANDLER( cjne_r_byte ) } //CLR bit addr /* 1: 1100 0010 */ -OPHANDLER( clr_bitaddr ) +void axc51base_cpu_device::clr_bitaddr(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,0); //Clear bit at specified bit address + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + bit_address_w(addr,0); //Clear bit at specified bit address } //CLR C /* 1: 1100 0011 */ -OPHANDLER( clr_c ) +void axc51base_cpu_device::clr_c(uint8_t r) { SET_CY(0); //Clear Carry Flag } //CLR A /* 1: 1110 0100 */ -OPHANDLER( clr_a ) +void axc51base_cpu_device::clr_a(uint8_t r) { SET_ACC(0); //Clear Accumulator } //CPL bit addr /* 1: 1011 0010 */ -OPHANDLER( cpl_bitaddr ) +void axc51base_cpu_device::cpl_bitaddr(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab bit address + uint8_t data = (~bit_address_r(addr))&1; + bit_address_w(addr,data); //Complement bit at specified bit address } //CPL C /* 1: 1011 0011 */ -OPHANDLER( cpl_c ) +void axc51base_cpu_device::cpl_c(uint8_t r) { uint8_t bit = (~GET_CY)&1; //Complement Carry Flag SET_CY(bit); } //CPL A /* 1: 1111 0100 */ -OPHANDLER( cpl_a ) +void axc51base_cpu_device::cpl_a(uint8_t r) { uint8_t data = ((~ACC)&0xff); SET_ACC(data); //Complement Accumulator } //DA A /* 1: 1101 0100 */ -OPHANDLER( da_a ) +void axc51base_cpu_device::da_a(uint8_t r) { /*From several sources, since none said the same thing: The decimal adjust instruction is associated with the use of the ADD and ADDC instructions. @@ -288,34 +288,34 @@ OPHANDLER( da_a ) } //DEC A /* 1: 0001 0100 */ -OPHANDLER( dec_a ) +void axc51base_cpu_device::dec_a(uint8_t r) { SET_ACC(ACC-1); } //DEC data addr /* 1: 0001 0101 */ -OPHANDLER( dec_mem ) +void axc51base_cpu_device::dec_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); - IRAM_W(addr,data-1); + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); + iram_write(addr,data-1); } //DEC @R0/@R1 /* 1: 0001 011i */ -OPHANDLER( dec_ir ) +void axc51base_cpu_device::dec_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); - IRAM_IW(R_REG(r),data-1); + uint8_t data = iram_indirect_read(R_REG(r)); + iram_indirect_write(R_REG(r),data-1); } //DEC R0 to R7 /* 1: 0001 1rrr */ -OPHANDLER( dec_r ) +void axc51base_cpu_device::dec_r(uint8_t r) { SET_REG(r, R_REG(r) - 1); } //DIV AB /* 1: 1000 0100 */ -OPHANDLER( div_ab ) +void axc51base_cpu_device::div_ab(uint8_t r) { if( B == 0 ) { //Overflow flag is set! @@ -338,456 +338,524 @@ OPHANDLER( div_ab ) } //DJNZ data addr, code addr /* 1: 1101 0101 */ -OPHANDLER( djnz_mem ) +void axc51base_cpu_device::djnz_mem(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + iram_write(addr,iram_read(addr) - 1); //Decrement value contained at data address + if(iram_read(addr) != 0) //Branch if contents of data address is not 0 { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } } //DJNZ R0 to R7,code addr /* 1: 1101 1rrr */ -OPHANDLER( djnz_r ) +void axc51base_cpu_device::djnz_r(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = m_program.read_byte(m_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; + m_pc = m_pc + rel_addr; } } //INC A /* 1: 0000 0100 */ -OPHANDLER( inc_a ) +void axc51base_cpu_device::inc_a(uint8_t r) { SET_ACC(ACC+1); } //INC data addr /* 1: 0000 0101 */ -OPHANDLER( inc_mem ) +void axc51base_cpu_device::inc_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); - IRAM_W(addr,data+1); + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); + iram_write(addr,data+1); } //INC @R0/@R1 /* 1: 0000 011i */ -OPHANDLER( inc_ir ) +void axc51base_cpu_device::inc_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); - IRAM_IW(R_REG(r),data+1); + uint8_t data = iram_indirect_read(R_REG(r)); + iram_indirect_write(R_REG(r),data+1); } //INC R0 to R7 /* 1: 0000 1rrr */ -OPHANDLER( inc_r ) +void axc51base_cpu_device::inc_r(uint8_t r) { uint8_t data = R_REG(r); SET_REG(r, data + 1); } //INC DPTR /* 1: 1010 0011 */ -OPHANDLER( inc_dptr ) +void axc51base_cpu_device::inc_dptr(uint8_t r) { - uint16_t dptr = (DPTR)+1; - SET_DPTR(dptr); + //if (m_sfr_regs[SFR_DPCON] & 0x08) // auto-increment enabled (not used here) + //{ + // fatalerror("inc_dptr with auto-inc"); + //} + + if (m_sfr_regs[SFR_DPCON] & 0x04) // auto-toggle enabled + { + fatalerror("inc_dptr with auto-toggle"); + } + + if (m_sfr_regs[SFR_DPCON] & 0x01) // DPTR1 enabled + { + uint16_t dptr = (DPTR1)+1; + SET_DPTR1(dptr); + } + else + { + uint16_t dptr = (DPTR0)+1; + SET_DPTR0(dptr); + } + } //JB bit addr, code addr /* 1: 0010 0000 */ -OPHANDLER( jb ) +void axc51base_cpu_device::jb(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab bit address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + if(bit_address_r(addr)) //If bit set at specified bit address, jump { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } } //JBC bit addr, code addr /* 1: 0001 0000 */ -OPHANDLER( jbc ) +void axc51base_cpu_device::jbc(uint8_t r) { - 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + if(bit_address_r(addr)) { //If bit set at specified bit address, jump + m_pc = m_pc + rel_addr; + bit_address_w(addr,0); //Clear Bit also } } //JC code addr /* 1: 0100 0000 */ -OPHANDLER( jc ) +void axc51base_cpu_device::jc(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address if(GET_CY) //Jump if Carry Flag Set { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } } //JMP @A+DPTR /* 1: 0111 0011 */ -OPHANDLER( jmp_iadptr ) +void axc51base_cpu_device::jmp_iadptr(uint8_t r) { - PC = ACC + DPTR; + // not listed as being affected by auto-inc or auto-toggle? + if (m_sfr_regs[SFR_DPCON] & 0x08) // auto-increment enabled + { + fatalerror("jmp_iadptr with auto-inc"); + } + + if (m_sfr_regs[SFR_DPCON] & 0x04) // auto-toggle enabled + { + fatalerror("jmp_iadptr with auto-toggle"); + } + + if (m_sfr_regs[SFR_DPCON] & 0x01) // DPTR0 enabled + { + fatalerror("jmp_iadptr with DPTR1"); + } + + m_pc = ACC + DPTR0; } //JNB bit addr, code addr /* 1: 0011 0000 */ -OPHANDLER( jnb ) +void axc51base_cpu_device::jnb(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab bit address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + if(!bit_address_r(addr)) //If bit NOT set at specified bit address, jump { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } } //JNC code addr /* 1: 0101 0000 */ -OPHANDLER( jnc ) +void axc51base_cpu_device::jnc(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address if(!GET_CY) //Jump if Carry Flag not set { - PC = PC + rel_addr; + m_pc = m_pc + rel_addr; } } //JNZ code addr /* 1: 0111 0000 */ -OPHANDLER( jnz ) +void axc51base_cpu_device::jnz(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address if(ACC != 0) //Branch if ACC is not 0 { - PC = PC+rel_addr; + m_pc = m_pc+rel_addr; } } //JZ code addr /* 1: 0110 0000 */ -OPHANDLER( jz ) +void axc51base_cpu_device::jz(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address if(ACC == 0) //Branch if ACC is 0 { - PC = PC+rel_addr; + m_pc = m_pc+rel_addr; } } //LCALL code addr /* 1: 0001 0010 */ -OPHANDLER( lcall ) +void axc51base_cpu_device::lcall(uint8_t r) { uint8_t addr_hi, addr_lo; - addr_hi = ROP_ARG(PC++); - addr_lo = ROP_ARG(PC++); - PUSH_PC(); - PC = (uint16_t)((addr_hi<<8) | addr_lo); + addr_hi = m_program.read_byte(m_pc++); + addr_lo = m_program.read_byte(m_pc++); + push_pc(); + m_pc = (uint16_t)((addr_hi<<8) | addr_lo); } //LJMP code addr /* 1: 0000 0010 */ -OPHANDLER( ljmp ) +void axc51base_cpu_device::ljmp(uint8_t r) { uint8_t addr_hi, addr_lo; - addr_hi = ROP_ARG(PC++); - addr_lo = ROP_ARG(PC++); - PC = (uint16_t)((addr_hi<<8) | addr_lo); + addr_hi = m_program.read_byte(m_pc++); + addr_lo = m_program.read_byte(m_pc++); + m_pc = (uint16_t)((addr_hi<<8) | addr_lo); } //MOV A, #data /* 1: 0111 0100 */ -OPHANDLER( mov_a_byte ) +void axc51base_cpu_device::mov_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_pc++); //Grab data SET_ACC(data); //Store data to ACC } //MOV A, data addr /* 1: 1110 0101 */ -OPHANDLER( mov_a_mem ) +void axc51base_cpu_device::mov_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + SET_ACC(iram_read(addr)); //Store contents of data address to ACC } //MOV A,@RO/@R1 /* 1: 1110 011i */ -OPHANDLER( mov_a_ir ) +void axc51base_cpu_device::mov_a_ir(uint8_t r) { - SET_ACC(IRAM_IR(R_REG(r))); //Store contents of address pointed by R0 or R1 to ACC + SET_ACC(iram_indirect_read(R_REG(r))); //Store contents of address pointed by R0 or R1 to ACC } //MOV A,R0 to R7 /* 1: 1110 1rrr */ -OPHANDLER( mov_a_r ) +void axc51base_cpu_device::mov_a_r(uint8_t r) { SET_ACC(R_REG(r)); //Store contents of R0 - R7 to ACC } //MOV data addr, #data /* 1: 0111 0101 */ -OPHANDLER( mov_mem_byte ) +void axc51base_cpu_device::mov_mem_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + iram_write(addr,data); //Store data to data address location } //MOV data addr, data addr /* 1: 1000 0101 */ -OPHANDLER( mov_mem_mem ) +void axc51base_cpu_device::mov_mem_mem(uint8_t r) { //1st address is src, 2nd is dst, but the mov command works as mov dst,src) 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 + src = m_program.read_byte(m_pc++); //Grab source data address + dst = m_program.read_byte(m_pc++); //Grab destination data address + iram_write(dst,iram_read(src)); //Read source address contents and store to destination address } //MOV @R0/@R1, #data /* 1: 0111 011i */ -OPHANDLER( mov_ir_byte ) +void axc51base_cpu_device::mov_ir_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data + iram_indirect_write(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 ) +void axc51base_cpu_device::mov_r_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_pc++); //Grab data SET_REG(r, data); //Store to R0 - R7 } //MOV data addr, @R0/@R1 /* 1: 1000 011i */ -OPHANDLER( mov_mem_ir ) +void axc51base_cpu_device::mov_mem_ir(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + iram_write(addr,iram_indirect_read(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 ) +void axc51base_cpu_device::mov_mem_r(uint8_t 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 = m_program.read_byte(m_pc++); //Grab data address + iram_write(addr,R_REG(r)); //Store contents of R0 - R7 to data address } //MOV DPTR, #data16 /* 1: 1001 0000 */ -OPHANDLER( mov_dptr_byte ) +void axc51base_cpu_device::mov_dptr_byte(uint8_t r) { + //if (m_sfr_regs[SFR_DPCON] & 0x08) // auto-increment enabled (not used here) + //{ + // fatalerror("mov_dptr_byte with auto-inc"); + //} + + if (m_sfr_regs[SFR_DPCON] & 0x04) // auto-toggle enabled + { + fatalerror("mov_dptr_byte with auto-toggle"); + } + 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 + data_hi = m_program.read_byte(m_pc++); //Grab hi byte + data_lo = m_program.read_byte(m_pc++); //Grab lo byte + + if (m_sfr_regs[SFR_DPCON] & 0x01) // DPTR1 enabled + { + SET_DPTR1((uint16_t)((data_hi << 8) | data_lo)); //Store to DPTR1 + } + else + { + SET_DPTR0((uint16_t)((data_hi << 8) | data_lo)); //Store to DPTR0 + } } //MOV bit addr, C /* 1: 1001 0010 */ -OPHANDLER( mov_bitaddr_c ) +void axc51base_cpu_device::mov_bitaddr_c(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,GET_CY); //Store Carry Flag to Bit Address + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + bit_address_w(addr,GET_CY); //Store Carry Flag to Bit Address } //MOV @R0/@R1, data addr /* 1: 1010 011i */ -OPHANDLER( mov_ir_mem ) +void axc51base_cpu_device::mov_ir_mem(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + iram_indirect_write(R_REG(r),iram_read(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 ) +void axc51base_cpu_device::mov_r_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - SET_REG(r, IRAM_R(addr)); //Store to R0 - R7 + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + SET_REG(r, iram_read(addr)); //Store to R0 - R7 } //MOV data addr, A /* 1: 1111 0101 */ -OPHANDLER( mov_mem_a ) +void axc51base_cpu_device::mov_mem_a(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - IRAM_W(addr,ACC); //Store A to data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + iram_write(addr,ACC); //Store A to data address } //MOV @R0/@R1, A /* 1: 1111 011i */ -OPHANDLER( mov_ir_a ) +void axc51base_cpu_device::mov_ir_a(uint8_t r) { - IRAM_IW(R_REG(r),ACC); //Store A to location pointed to by R0 or R1 + iram_indirect_write(R_REG(r),ACC); //Store A to location pointed to by R0 or R1 } //MOV R0 to R7, A /* 1: 1111 1rrr */ -OPHANDLER( mov_r_a ) +void axc51base_cpu_device::mov_r_a(uint8_t r) { SET_REG(r, ACC); //Store A to R0-R7 } -//MOVC A, @A + PC /* 1: 1000 0011 */ -OPHANDLER( movc_a_iapc ) +//MOVC A, @A + m_pc /* 1: 1000 0011 */ +void axc51base_cpu_device::movc_a_iapc(uint8_t r) { uint8_t data; - data = CODEMEM_R(ACC+PC); //Move a byte from CODE(Program) Memory and store to ACC + data = (uint8_t)m_program.read_byte(ACC+m_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 ) +void axc51base_cpu_device::mov_c_bitaddr(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab bit address + SET_CY( (bit_address_r(addr)) ); //Store Bit from Bit Address to Carry Flag } //MOVC A, @A + DPTR /* 1: 1001 0011 */ -OPHANDLER( movc_a_iadptr ) +void axc51base_cpu_device::movc_a_iadptr(uint8_t r) { + if (m_sfr_regs[SFR_DPCON] & 0x08) // auto-increment enabled + { + fatalerror("movc_a_iadptr with auto-inc"); + } + + if (m_sfr_regs[SFR_DPCON] & 0x04) // auto-toggle enabled + { + fatalerror("movc_a_iadptr with auto-toggle"); + } + + if (m_sfr_regs[SFR_DPCON] & 0x01) // DPTR1 enabled + { + fatalerror("movc_a_iadptr with DPTR1"); + } + uint8_t data; - data = CODEMEM_R(ACC + DPTR); //Move a byte from CODE(Program) Memory and store to ACC + data = (uint8_t)m_program.read_byte(ACC + DPTR0); //Move a byte from CODE(Program) Memory and store to ACC SET_ACC(data); } //MOVX A,@DPTR /* 1: 1110 0000 */ //(Move External Ram 16 bit address to A) -OPHANDLER( movx_a_idptr ) +void axc51base_cpu_device::movx_a_idptr(uint8_t r) { -// 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 + uint32_t addr = process_dptr_access(); + + uint8_t byte = (uint8_t)m_io.read_byte(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 ) +void axc51base_cpu_device::movx_a_ir(uint8_t r) { - 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 + uint32_t addr = external_ram_iaddr(R_REG(r),0xff); //Grab address by reading location pointed to by R0 or R1 + uint8_t byte = (uint8_t)m_io.read_byte(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 ) +void axc51base_cpu_device::movx_idptr_a(uint8_t r) { -// 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 + uint32_t addr = process_dptr_access(); + m_io.write_byte(addr, ACC); //Store ACC to External DATA memory address pointed to by DPTR0 } //MOVX @R0/@R1,A /* 1: 1111 001i */ //(Move A to External Ram 8 bit address) -OPHANDLER( movx_ir_a ) +void axc51base_cpu_device::movx_ir_a(uint8_t r) { - 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 + uint32_t addr = external_ram_iaddr(R_REG(r),0xff); //Grab address by reading location pointed to by R0 or R1 + m_io.write_byte(addr, ACC); //Store ACC to External DATA memory address } //MUL AB /* 1: 1010 0100 */ -OPHANDLER( mul_ab ) +void axc51base_cpu_device::mul_ab(uint8_t r) { 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_CY(0); //Carry Flag always cleared } //NOP /* 1: 0000 0000 */ -OPHANDLER( nop ) +void axc51base_cpu_device::nop(uint8_t r) { } //ORL data addr, A /* 1: 0100 0010 */ -OPHANDLER( orl_mem_a ) +void axc51base_cpu_device::orl_mem_a(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::orl_mem_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + uint8_t srcdata = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::orl_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_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 ) +void axc51base_cpu_device::orl_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 ) +void axc51base_cpu_device::orl_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + uint8_t data = iram_indirect_read(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 ) +void axc51base_cpu_device::orl_a_r(uint8_t 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 } //ORL C, bit addr /* 1: 0111 0010 */ -OPHANDLER( orl_c_bitaddr ) +void axc51base_cpu_device::orl_c_bitaddr(uint8_t r) { 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + uint8_t bit = bit_address_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 ) +void axc51base_cpu_device::orl_c_nbitaddr(uint8_t r) { 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + uint8_t bit = bit_address_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 ) +void axc51base_cpu_device::pop(uint8_t r) { - 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 + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + iram_write(addr, iram_indirect_read(SP)); //Store to contents of data addr, data pointed to by Stack - iram_indirect_read needed to access upper 128 bytes of stack + //iram_indirect_write(addr, iram_indirect_read(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 } //PUSH data addr /* 1: 1100 0000 */ -OPHANDLER( push ) +void axc51base_cpu_device::push(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address + uint8_t addr = m_program.read_byte(m_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 + iram_indirect_write(tmpSP, iram_read(addr)); //Store to stack contents of data address - iram_indirect_write needed to store to upper 128 bytes of stack, however, can't use iram_indirect_read because that won't store the sfrs and it's not an indirect access anyway } //RET /* 1: 0010 0010 */ -OPHANDLER( ret ) +void axc51base_cpu_device::ret(uint8_t r) { - POP_PC(); + pop_pc(); } //RETI /* 1: 0011 0010 */ -OPHANDLER( reti ) +void axc51base_cpu_device::reti(uint8_t r) { - POP_PC(); - CLEAR_CURRENT_IRQ(); + pop_pc(); + clear_current_irq(); } //RL A /* 1: 0010 0011 */ -OPHANDLER( rl_a ) +void axc51base_cpu_device::rl_a(uint8_t r) { //Left Shift A, Bit 7 carries to Bit 0 int carry = ((ACC & 0x80) >> 7); @@ -796,7 +864,7 @@ OPHANDLER( rl_a ) } //RLC A /* 1: 0011 0011 */ -OPHANDLER( rlc_a ) +void axc51base_cpu_device::rlc_a(uint8_t r) { //Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC int carry = ((ACC & 0x80) >> 7); @@ -806,7 +874,7 @@ OPHANDLER( rlc_a ) } //RR A /* 1: 0000 0011 */ -OPHANDLER( rr_a ) +void axc51base_cpu_device::rr_a(uint8_t r) { //Right Shift A, Bit 0 carries to Bit 7 int carry = ((ACC & 1) << 7); @@ -815,7 +883,7 @@ OPHANDLER( rr_a ) } //RRC A /* 1: 0001 0011 */ -OPHANDLER( rrc_a ) +void axc51base_cpu_device::rrc_a(uint8_t r) { //Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag int carry = (ACC & 1); @@ -825,65 +893,65 @@ OPHANDLER( rrc_a ) } //SETB C /* 1: 1101 0011 */ -OPHANDLER( setb_c ) +void axc51base_cpu_device::setb_c(uint8_t r) { SET_CY(1); //Set Carry Flag } //SETB bit addr /* 1: 1101 0010 */ -OPHANDLER( setb_bitaddr ) +void axc51base_cpu_device::setb_bitaddr(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab bit address - BIT_W(addr,1); //Set Bit at Bit Address + uint8_t addr = m_program.read_byte(m_pc++); //Grab bit address + bit_address_w(addr,1); //Set Bit at Bit Address } //SJMP code addr /* 1: 1000 0000 */ -OPHANDLER( sjmp ) +void axc51base_cpu_device::sjmp(uint8_t r) { - int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address - PC = PC + rel_addr; //Update PC + int8_t rel_addr = m_program.read_byte(m_pc++); //Grab relative code address + m_pc = m_pc + rel_addr; //Update m_pc } //SUBB A, #data /* 1: 1001 0100 */ -OPHANDLER( subb_a_byte ) +void axc51base_cpu_device::subb_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_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 + do_sub_flags(ACC,data,GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //SUBB A, data addr /* 1: 1001 0101 */ -OPHANDLER( subb_a_mem ) +void axc51base_cpu_device::subb_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 + 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 ) +void axc51base_cpu_device::subb_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1 + uint8_t data = iram_indirect_read(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 + 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 ) +void axc51base_cpu_device::subb_a_r(uint8_t 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 + do_sub_flags(ACC,data,GET_CY); //Set Flags SET_ACC(result); //Store 8 bit result of addtion in ACC } //SWAP A /* 1: 1100 0100 */ -OPHANDLER( swap_a ) +void axc51base_cpu_device::swap_a(uint8_t r) { uint8_t a_nib_lo, a_nib_hi; a_nib_hi = (ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi @@ -892,26 +960,26 @@ OPHANDLER( swap_a ) } //XCH A, data addr /* 1: 1100 0101 */ -OPHANDLER( xch_a_mem ) +void axc51base_cpu_device::xch_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 + iram_write(addr,oldACC); //Sets data address to old value of ACC } //XCH A, @RO/@R1 /* 1: 1100 011i */ -OPHANDLER( xch_a_ir ) +void axc51base_cpu_device::xch_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 + uint8_t data = iram_indirect_read(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 + iram_indirect_write(R_REG(r),oldACC); //Sets data address to old value of ACC } //XCH A, RO to R7 /* 1: 1100 1rrr */ -OPHANDLER( xch_a_r ) +void axc51base_cpu_device::xch_a_r(uint8_t r) { uint8_t data = R_REG(r); //Grab data from R0-R7 uint8_t oldACC = ACC; //Hold value of ACC @@ -920,63 +988,63 @@ OPHANDLER( xch_a_r ) } //XCHD A, @R0/@R1 /* 1: 1101 011i */ -OPHANDLER( xchd_a_ir ) +void axc51base_cpu_device::xchd_a_ir(uint8_t r) { uint8_t acc, ir_data; - ir_data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1 + ir_data = iram_indirect_read(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 + iram_write(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 ) +void axc51base_cpu_device::xrl_mem_a(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::xrl_mem_byte(uint8_t r) { - 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 = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = m_program.read_byte(m_pc++); //Grab data + uint8_t srcdata = iram_read(addr); //Grab data from data address + iram_write(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 ) +void axc51base_cpu_device::xrl_a_byte(uint8_t r) { - uint8_t data = ROP_ARG(PC++); //Grab data + uint8_t data = m_program.read_byte(m_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 ) +void axc51base_cpu_device::xrl_a_mem(uint8_t r) { - uint8_t addr = ROP_ARG(PC++); //Grab data address - uint8_t data = IRAM_R(addr); //Grab data from data address + uint8_t addr = m_program.read_byte(m_pc++); //Grab data address + uint8_t data = iram_read(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 ) +void axc51base_cpu_device::xrl_a_ir(uint8_t r) { - uint8_t data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to + uint8_t data = iram_indirect_read(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 ) +void axc51base_cpu_device::xrl_a_r(uint8_t 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 } //illegal opcodes -OPHANDLER( illegal ) +void axc51base_cpu_device::illegal(uint8_t r) { - LOG(("i8051 '%s': illegal opcode at 0x%03x: %02x\n", tag(), PC-1, r)); + LOGMASKED(LOG_GENERAL,"i8051 '%s': illegal opcode at 0x%03x: %02x\n", tag(), m_pc-1, r); } diff --git a/src/devices/machine/generic_spi_flash.cpp b/src/devices/machine/generic_spi_flash.cpp new file mode 100644 index 00000000000..7c0f048eba7 --- /dev/null +++ b/src/devices/machine/generic_spi_flash.cpp @@ -0,0 +1,199 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#include "emu.h" +#include "generic_spi_flash.h" + +#define LOG_SPI (1U << 1) + +#define VERBOSE (0) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(GENERIC_SPI_FLASH, generic_spi_flash_device, "generic_spi_flash", "Generic SPI Flash handling") + +generic_spi_flash_device::generic_spi_flash_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, GENERIC_SPI_FLASH, tag, owner, clock) + , device_nvram_interface(mconfig, *this) +{ +} + +void generic_spi_flash_device::device_start() +{ + save_item(NAME(m_spiaddr)); + save_item(NAME(m_spi_state)); + save_item(NAME(m_spilatch)); + save_item(NAME(m_spidir)); +} + +void generic_spi_flash_device::device_reset() +{ + m_spiaddr = 0; + m_spi_state = 0; + m_spilatch = 0; + m_spidir = false; +} + +void generic_spi_flash_device::write(uint8_t data) +{ + if (!m_spidir) // Send to SPI + { + switch (m_spi_state) + { + case READY_FOR_COMMAND: + if (data == 0x03) + { + m_spi_state = READY_FOR_ADDRESS2; + } + else if (data == 0x05) + { + m_spi_state = READY_FOR_STATUS_READ; + } + else if (data == 0x0b) + { + m_spi_state = READY_FOR_HSADDRESS2; + } + else if (data == 0x06) + { + // write enable + m_spi_state = READY_FOR_COMMAND; + } + else if (data == 0x04) + { + // write disable + m_spi_state = READY_FOR_COMMAND; + } + else if (data == 0x02) + { + // page program + m_spi_state = READY_FOR_WRITEADDRESS2; + } + else if (data == 0x20) + { + // erase 4k sector + m_spi_state = READY_FOR_COMMAND; + } + else + { + fatalerror("SPI set to unknown mode %02x\n", data); + } + break; + + case READY_FOR_WRITEADDRESS2: + m_spiaddr = (m_spiaddr & 0x00ffff) | (data << 16); + m_spi_state = READY_FOR_WRITEADDRESS1; + break; + + case READY_FOR_WRITEADDRESS1: + m_spiaddr = (m_spiaddr & 0xff00ff) | (data << 8); + m_spi_state = READY_FOR_WRITEADDRESS0; + break; + + case READY_FOR_WRITEADDRESS0: + m_spiaddr = (m_spiaddr & 0xffff00) | (data); + m_spi_state = READY_FOR_WRITE; + LOGMASKED(LOG_SPI, "SPI set to page WRITE mode with address %08x\n", m_spiaddr); + break; + + case READY_FOR_WRITE: + LOGMASKED(LOG_SPI, "Write SPI data %02x\n", data); + + m_spiptr[(m_spiaddr++) & (m_length-1)] = data; + + break; + + + case READY_FOR_ADDRESS2: + m_spiaddr = (m_spiaddr & 0x00ffff) | (data << 16); + m_spi_state = READY_FOR_ADDRESS1; + break; + + case READY_FOR_ADDRESS1: + m_spiaddr = (m_spiaddr & 0xff00ff) | (data << 8); + m_spi_state = READY_FOR_ADDRESS0; + break; + + case READY_FOR_ADDRESS0: + m_spiaddr = (m_spiaddr & 0xffff00) | (data); + m_spi_state = READY_FOR_READ; + m_spidir = 1; + LOGMASKED(LOG_SPI, "SPI set to READ mode with address %08x\n", m_spiaddr); + break; + + case READY_FOR_HSADDRESS2: + m_spiaddr = (m_spiaddr & 0x00ffff) | (data << 16); + m_spi_state = READY_FOR_HSADDRESS1; + break; + + case READY_FOR_HSADDRESS1: + m_spiaddr = (m_spiaddr & 0xff00ff) | (data << 8); + m_spi_state = READY_FOR_HSADDRESS0; + break; + + case READY_FOR_HSADDRESS0: + m_spiaddr = (m_spiaddr & 0xffff00) | (data); + m_spi_state = READY_FOR_HSDUMMY; + break; + + case READY_FOR_HSDUMMY: + m_spi_state = READY_FOR_READ; + m_spidir = 1; + LOGMASKED(LOG_SPI, "SPI set to High Speed READ mode with address %08x\n", m_spiaddr); + break; + + case READY_FOR_SECTORERASEADDRESS2: + m_spiaddr = (m_spiaddr & 0x00ffff) | (data << 16); + m_spi_state = READY_FOR_SECTORERASEADDRESS1; + break; + + case READY_FOR_SECTORERASEADDRESS1: + m_spiaddr = (m_spiaddr & 0xff00ff) | (data << 8); + m_spi_state = READY_FOR_SECTORERASEADDRESS0; + break; + + case READY_FOR_SECTORERASEADDRESS0: + m_spiaddr = (m_spiaddr & 0xffff00) | (data); + LOGMASKED(LOG_SPI, "SPI set to Erase Sector with address %08x\n", m_spiaddr); + break; + + } + } + else + { + if (m_spi_state == READY_FOR_READ) + { + m_spilatch = m_spiptr[(m_spiaddr++) & (m_length-1)]; + } + else if (m_spi_state == READY_FOR_STATUS_READ) + { + m_spilatch = 0x00; + } + else + { + m_spilatch = 0x00; + } + } +} + + + +void generic_spi_flash_device::nvram_default() +{ +} + +bool generic_spi_flash_device::nvram_read(util::read_stream &file) +{ + if (m_spiptr == nullptr) + { + return false; + } + + size_t actual; + return !file.read(m_spiptr, m_length, actual) && actual == m_length; +} + +bool generic_spi_flash_device::nvram_write(util::write_stream &file) +{ + size_t actual; + return !file.write(m_spiptr, m_length, actual) && actual == m_length; +} + diff --git a/src/devices/machine/generic_spi_flash.h b/src/devices/machine/generic_spi_flash.h new file mode 100644 index 00000000000..6e13120819b --- /dev/null +++ b/src/devices/machine/generic_spi_flash.h @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_MACHINE_GENERIC_SPI_FLASH_H +#define MAME_MACHINE_GENERIC_SPI_FLASH_H + +#pragma once + +class generic_spi_flash_device : public device_t, + public device_nvram_interface +{ +public: + generic_spi_flash_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + + void set_rom_ptr(uint8_t* rom) { m_spiptr = rom; } + void set_rom_size(size_t size) { m_length = size; } + + uint8_t read() + { + return m_spilatch; + } + + void set_ready() + { + m_spi_state = READY_FOR_COMMAND; + } + + DECLARE_WRITE_LINE_MEMBER(dir_w) + { + m_spidir = state; + } + + void write(uint8_t data); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_nvram_interface overrides + virtual void nvram_default() override; + virtual bool nvram_read(util::read_stream &file) override; + virtual bool nvram_write(util::write_stream &file) override; + +private: + enum + { + READY_FOR_COMMAND = 0x00, + + READY_FOR_ADDRESS2 = 0x01, + READY_FOR_ADDRESS1 = 0x02, + READY_FOR_ADDRESS0 = 0x03, + + READY_FOR_HSADDRESS2 = 0x04, + READY_FOR_HSADDRESS1 = 0x05, + READY_FOR_HSADDRESS0 = 0x06, + READY_FOR_HSDUMMY = 0x07, + + READY_FOR_WRITEADDRESS2 = 0x08, + READY_FOR_WRITEADDRESS1 = 0x09, + READY_FOR_WRITEADDRESS0 = 0x0a, + + READY_FOR_SECTORERASEADDRESS2 = 0x0b, + READY_FOR_SECTORERASEADDRESS1 = 0x0c, + READY_FOR_SECTORERASEADDRESS0 = 0x0d, + + READY_FOR_WRITE = 0x0e, + + READY_FOR_READ = 0x0f, + READY_FOR_STATUS_READ = 0x10, + }; + + uint32_t m_spiaddr; + uint8_t m_spi_state; + uint8_t m_spilatch; + bool m_spidir; + + uint8_t* m_spiptr; + size_t m_length; +}; + +DECLARE_DEVICE_TYPE(GENERIC_SPI_FLASH, generic_spi_flash_device) + +#endif // MAME_MACHINE_GENERIC_SPI_FLASH_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 391829b7edb..809dc0a0d01 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -24328,7 +24328,7 @@ monacogpa // (c) 1980 Sega @source:tvgames/monkey_king_3b.cpp rs70_648 // -@source:skeleton/monon_color.cpp +@source:misc/monon_color.cpp mononcol // (c) 2011 M&D @source:handheld/monty.cpp diff --git a/src/mame/mess.flt b/src/mame/mess.flt index f6ec54c465d..70a23036483 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -474,6 +474,7 @@ miltonbradley/vectrex.cpp mips/mips.cpp misc/3do.cpp misc/eva.cpp +misc/monon_color.cpp mit/tx0.cpp mits/altair.cpp mits/mits680b.cpp @@ -887,7 +888,6 @@ skeleton/mmd2.cpp skeleton/mod8.cpp skeleton/modellot.cpp skeleton/molecular.cpp -skeleton/monon_color.cpp skeleton/ms9540.cpp skeleton/mstation.cpp skeleton/mt735.cpp diff --git a/src/mame/misc/monon_color.cpp b/src/mame/misc/monon_color.cpp new file mode 100644 index 00000000000..e985114111f --- /dev/null +++ b/src/mame/misc/monon_color.cpp @@ -0,0 +1,951 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/*************************************************************************** + Monon Color - Chinese handheld + + see + https://gbatemp.net/threads/the-monon-color-a-new-video-game-console-from-china.467788/ + https://twitter.com/Splatoon2weird/status/1072182093206052864 + + uses AX208 CPU (custom 8051 @ 96Mhz with single cycle instructions, extended '16 bit' opcodes + integrated video, jpeg decoder etc.) + https://docplayer.net/52724058-Ax208-product-specification.html + + Emulation Notes: + + The Monon makes very little use of many of the AX208 features, for example + + - Encryption is only enabled once, for a throw-away transfer that is never + checked. + - JPEG RAM is simply used for extra RAM. + - USB support not used + - SD card support not used + - Most IRQ levels not used + - Onboard LCDC not used + + While the SFX used by each game are done through the AX208 DAC the music + is not. + + Instead the music is supplied by a glob in each cartridge, which differs + for each game. This glob is assumed to be a self-contained MCU, responding + to music requests. Swapping the game ROM onto a different cartridge + results in incorrect music, or silence, and in some cases hangs if you go + into the volume adjustment menu. + + There is currently no way of reading the music data from this glob, nor + has the exact die underneath it been identified. + + Games save data directly to the SPI ROM in the 0x50000-0x5ffff region + + Some games made use of either a card reader, or a badge reader on the + cartridge, this is not yet emulated. The card reader was based on + barcode-like patterns, the badge reader looks to also be based on barcodes + + AXC51_TMR1PWML / AXC51_TMR1PWMH (Timer 1 Duty Registers) in the AX208 + core are responsible for screen brightness (can be adjusted in the pause + menu) There's no Timer 1 IRQ Handler in the code, but presumably the LCD + is driven directly off the timer pins. + + Some games can be linked via the Infared support provided by the AX208, + this is not currently supported. + +***************************************************************************/ + +#include "emu.h" + +#include "emupal.h" +#include "screen.h" +#include "softlist_dev.h" +#include "speaker.h" + +#include "bus/mononcol/slot.h" +#include "bus/mononcol/carts.h" + +#include "cpu/axc51/axc51.h" +#include "sound/dac.h" + +#define LOG_VDP (1U << 1) +#define LOG_SOUNDMCUCOMMS (1U << 2) + +//#define VERBOSE (LOG_VDP) +#define VERBOSE (0) + +#include "logmacro.h" + +class monon_color_state : public driver_device +{ +public: + monon_color_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_cart(*this, "cartslot"), + m_maincpu(*this, "maincpu"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_dac(*this, "dac"), + m_debugin(*this, "DEBUG%u", 0U), + m_controls(*this, "CONTROLS%u", 0U) + { } + + void monon_color(machine_config &config); +protected: + // driver_device overrides + virtual void machine_start() override; + virtual void machine_reset() override; + + // screen updates + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); +private: + + + required_device m_cart; + required_device m_maincpu; + required_device m_screen; + required_device m_palette; + required_device m_dac; + required_ioport_array<4> m_debugin; + required_ioport_array<4> m_controls; + + uint8_t in0_r(); + uint8_t in1_r(); + uint8_t in2_r(); + uint8_t in3_r(); + uint8_t in4_r(); + void out0_w(uint8_t data); + void out1_w(uint8_t data); + void out2_w(uint8_t data); + void out3_w(uint8_t data); + void out4_w(uint8_t data); + + uint8_t read_current_inputs(); + + uint8_t read_from_video_device(); + void write_to_video_device(uint8_t data); + + void dacout0_w(uint8_t data); + void dacout1_w(uint8_t data); + + uint8_t spibuf_r() + { + return m_cart->read(); + } + + uint8_t spibuf_direct_r() + { + m_lastspi = m_cart->read(); + return m_lastspi; + } + + DECLARE_WRITE_LINE_MEMBER(spidir_w) + { + m_cart->dir_w(state); + } + + void spibuf_w(uint8_t data) + { + m_cart->write(data); + } + + void get_sound_command_bit(uint8_t bit); + bool m_sound_direction_iswrite; + uint16_t m_sound_latch; + uint8_t m_sound_bitpos; + uint8_t m_sound_response_bit; + uint8_t m_sound_bits_in_needed; + + void do_draw_inner(int pal_to_use, int start, int step, int pixmask, int amount); + void do_draw(int amount, int pal_to_use); + void do_palette(int amount, int pal_to_use); + + rgb_t m_linebuf[240]; + rgb_t m_vidbuffer[320 * 240]; + int16_t m_bufpos_y; + uint32_t m_bufpos_x; + uint8_t m_storeregs[0x20]; + uint8_t m_dacbyte; + + uint8_t m_out4data; + uint8_t m_out3data; + uint8_t m_out2data; + uint8_t m_out1data; + uint8_t m_out0data; + + uint8_t m_lastspi; + + uint8_t m_curpal[0x800 * 3]; +}; + +void monon_color_state::machine_start() +{ + save_item(NAME(m_dacbyte)); + save_item(NAME(m_out4data)); + save_item(NAME(m_out3data)); + save_item(NAME(m_out2data)); + save_item(NAME(m_out1data)); + save_item(NAME(m_out0data)); + save_item(NAME(m_linebuf)); + save_item(NAME(m_vidbuffer)); + save_item(NAME(m_bufpos_x)); + save_item(NAME(m_bufpos_y)); + save_item(NAME(m_curpal)); + save_item(NAME(m_storeregs)); + + save_item(NAME(m_sound_direction_iswrite)); + save_item(NAME(m_sound_latch)); + save_item(NAME(m_sound_bitpos)); + save_item(NAME(m_sound_response_bit)); + save_item(NAME(m_sound_bits_in_needed)); +} + + +void monon_color_state::machine_reset() +{ + /* block starting at e000 in flash is not code? (or encrypted?) + no code to map at 0x9000 in address space (possible BIOS?) + no code in flash ROM past the first 64kb(?) which is basically the same on all games, must be some kind of script interpreter? J2ME maybe? + + there are 5 different 'versions' of the code in the dumped ROMs, where the code is the same the roms match up until 0x50000 after which the game specific data starts + + by game number: + + 103alt (earliest? doesn't have bank9) + 101,102,103,104,105 (1st revision) + 106,107 (2nd revision) + 201 (3rd revision) + 202,203,204,205,301,302,303,304 (4th revision) + */ + + m_dacbyte = 0; + m_out2data = 0; + + m_out4data = 0; + m_out3data = 0; + m_out1data = 0; + m_out0data = 0; + m_bufpos_x = 0; + m_bufpos_y = 239; + + std::fill(std::begin(m_storeregs), std::end(m_storeregs), 0); + std::fill(std::begin(m_linebuf), std::end(m_linebuf), 0); + std::fill(std::begin(m_vidbuffer), std::end(m_vidbuffer), 0); + + m_sound_direction_iswrite = true; + m_sound_latch = 0; + m_sound_bitpos = 0; + m_sound_response_bit = 0; + m_sound_bits_in_needed = 0; +} + + + +uint32_t monon_color_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + rgb_t* videoram = m_vidbuffer; + + for (int y = 0; y < 240; y++) + { + int count = (y * 320); + for(int x = 0; x < 320; x++) + { + rgb_t pixel = videoram[count++]; + bitmap.pix(y, x) = pixel; + } + } + + return 0; +} + +static INPUT_PORTS_START( monon_color ) + PORT_START("DEBUG0") // Port 0 + PORT_DIPNAME( 0x01, 0x01, "PORT0" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // input related (read bits here) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) // input related (read bits here) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START("DEBUG1") // Port 1 + PORT_DIPNAME( 0x01, 0x01, "PORT1" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // input related (mux select bits here) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // input related (mux select bits here) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START("DEBUG2") // Port 2 + PORT_DIPNAME( 0x01, 0x01, "PORT2" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) // input related (read bits here) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START("DEBUG3") // Port 4 + PORT_DIPNAME( 0x01, 0x01, "PORT4" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) // input related (enables reading?) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START("CONTROLS0") + PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_BUTTON2 ) + PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_BUTTON1 ) + + PORT_START("CONTROLS1") + PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Right Trigger") + + PORT_START("CONTROLS2") + PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) + PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Left Trigger") + + PORT_START("CONTROLS3") + PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu") + PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Pause") + PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_UNUSED ) + +INPUT_PORTS_END + +/* + muxselect = p1 & 0x18; + + 0x30 input bits in p0 + 0x04 input bits in p2 + + 0x04 in port 4 combine inputs? +*/ + +uint8_t monon_color_state::read_current_inputs() +{ + uint8_t iomux = (m_out1data & 0x18) >> 3; + + if ((m_out4data & 0x04) == 0x00) + { + if (iomux == 0x00) + { + uint8_t in = (m_controls[0]->read() | m_controls[1]->read() | m_controls[2]->read() | m_controls[3]->read()) ^ 0x7; + return in; + } + else if (iomux == 0x01) + { + return m_controls[0]->read() ^ 0x7; + } + else if (iomux == 0x02) + { + return m_controls[1]->read() ^ 0x7; + } + else if (iomux == 0x03) + { + return m_controls[2]->read() ^ 0x7; + } + } + else + { + return m_controls[3]->read() ^ 0x7; + } + + return 0x00; +} + +uint8_t monon_color_state::in0_r() +{ + uint8_t in = read_current_inputs(); + uint8_t ret = m_debugin[0]->read() & 0xcf; + if (in & 0x01) ret |= 0x10; + if (in & 0x02) ret |= 0x20; + + return ret; +} + +uint8_t monon_color_state::in1_r() +{ + uint8_t ret = m_debugin[1]->read() & 0xe7; + ret |= m_out1data & 0x18; + + return ret; +} + +uint8_t monon_color_state::in2_r() +{ + uint8_t in = read_current_inputs(); + uint8_t ret = m_out2data & 0x7b; + ret |= m_sound_response_bit << 7; + if (in & 0x04) ret |= 0x04; + + return ret; +} + +uint8_t monon_color_state::in3_r() +{ + return m_out3data; +} + +uint8_t monon_color_state::in4_r() +{ + uint8_t ret = m_debugin[3]->read() & 0xfb; + ret |= m_out4data & 0x04; + return ret; +} + +void monon_color_state::dacout0_w(uint8_t data) +{ + m_dacbyte ^= 1; + + if (m_dacbyte == 1) + m_dac->write(data); +} + +void monon_color_state::dacout1_w(uint8_t data) +{ + // mono sound, not used? +} + + + +void monon_color_state::out0_w(uint8_t data) +{ + m_out0data = data & 0x1f; +} + +void monon_color_state::out1_w(uint8_t data) +{ + // out1 goes e5, e5, e7, e7 when WRITING a byte to the video device + // or e3, e3, e7, e7 when READING a byte from the video device + // + // presumably this actually causes the data from P3 to be written to the + // device, or data from the device to be latched in P3 + + if ((m_out1data == 0xe5) && (data == 0xe7)) + { + write_to_video_device(m_out3data); + } + else if ((m_out1data == 0xe3) && (data == 0xe7)) + { + m_out3data = read_from_video_device(); + } + + m_out1data = data; + +} + +void monon_color_state::get_sound_command_bit(uint8_t bit) +{ + bit &= 1; + + if (m_sound_bitpos == 0) + { + // first bit isn't part of the data? but isn't 0/1 depending on if it's a read/write eiter? + //LOGMASKED(LOG_SOUNDMCUCOMMS, "%s: started read/write command\n", machine().describe_context()); + m_sound_bitpos++; + + if (!m_sound_direction_iswrite) + { + // There is a protection check involving the axxx commands + // The game expects to read a byte from the sound MCU and + // compares it with a byte in the SPI ROM from e000 - efff + // + // This data in the SPI ROM is 65ec02 code that maps at + // 0x2000, so the check is presumably checking a random byte + // from part of the internal sound MCU ROM against the table + // stored in ROM. Sadly the internal program is larger than + // the 0x1000 bytes of it that have been duplicated in the + // SPI ROM for this check. + // + // If it doesn't get this, it will loop until by chance it gets the same + // value, which results in random delays (eg. when moving the volume + // slider from 0 to any other value) + // + // mechcycla (the game with the earliest firmware) will jump to an infinite + // loop if this is wrong, this doesn't happen with mechcycl, which uses a + // later firmware. + + m_sound_latch = m_lastspi; + //logerror("m_sound_latch set to %02x\n", m_sound_latch); + + } + } + else + { + if (m_sound_direction_iswrite) + { + m_sound_latch = m_sound_latch << 1; + m_sound_latch |= bit; + + m_sound_bitpos++; + + if (m_sound_bitpos == 17) + { + //LOGMASKED(LOG_SOUNDMCUCOMMS, "%s: sent sound word %04x to MCU\n", machine().describe_context(), m_sound_latch); + m_sound_bitpos = 0; + + switch (m_sound_latch & 0xf000) + { + + case 0x0000: + LOGMASKED(LOG_SOUNDMCUCOMMS, "0-00x set volume to %04x\n", m_sound_latch & 0x0fff); + m_sound_latch = 0; + break; + + case 0x2000: + LOGMASKED(LOG_SOUNDMCUCOMMS, "2-00x play music %04x\n", m_sound_latch & 0x0fff); + m_sound_latch = 0; + break; + + case 0x3000: + LOGMASKED(LOG_SOUNDMCUCOMMS, "3-000 stop all %04x\n", m_sound_latch & 0x0fff); + m_sound_latch = 0; + break; + + case 0x4000: + LOGMASKED(LOG_SOUNDMCUCOMMS, "4-000 reset? %04x\n", m_sound_latch & 0x0fff); + m_sound_latch = 0; + break; + + case 0xa000: + // spams a variable amount of this between scenes + // This appears to be for copy protection purposes, see note above + LOGMASKED(LOG_SOUNDMCUCOMMS, "a-xxx status return wanted %04x\n", m_sound_latch & 0x0fff); + m_sound_direction_iswrite = false; + m_sound_bits_in_needed = 9; + break; + + default: + LOGMASKED(LOG_SOUNDMCUCOMMS, "x-xxx unknown MCU write %04x\n", m_sound_latch); + m_sound_latch = 0; + break; + + } + } + + } + else + { + m_sound_response_bit = (m_sound_latch & 0x80)>>7; + m_sound_latch <<= 1; + + m_sound_bitpos++; + + if (m_sound_bitpos == m_sound_bits_in_needed) + { + //LOGMASKED(LOG_SOUNDMCUCOMMS, "%s: finished clocking in MCU response to read?\n", machine().describe_context()); + m_sound_bitpos = 0; + m_sound_direction_iswrite = true; + } + } + } +} + +void monon_color_state::out2_w(uint8_t data) +{ + // on the cartridge PCB the connections to the sound MCU glob are marked P21, P25 and P27 + // This is where the signals go on the AX208 (Port 2 bit 1, Port 2 bit 5, Port 2 bit 7) + + // m-C- --Ms + + // m = from MCU serial data (in) + // C = clock MCU serial data (out) + // M = to MCU serial data (out) + // s = SPI Chip Enable / Reset? + + if ((data & 0x01) != (m_out2data & 0x01)) + { + if (data & 0x01) + { + // nothing? + } + else + { + m_cart->set_ready(); + } + } + + if ((data & 0x20) != (m_out2data & 0x20)) + { + if (data & 0x20) + { + // .. nothing + } + else + { + // sends m_out2data & 0x02 to external device / latches a read bit into m_out2data & 0x80 + //logerror("%s: send / recieve sound MCU, bit written %d\n", machine().describe_context(), (data & 0x02) >> 1); + get_sound_command_bit((data & 0x02) >> 1); + } + } + + m_out2data = data; +} + +uint8_t monon_color_state::read_from_video_device() +{ + LOGMASKED(LOG_VDP,"%s: read_from_video_device (m_out0data is %02x)\n", machine().describe_context(), m_out0data); + + if (m_out0data == 0x0c) + return 0xff ^ 0x02; + + if (m_out0data == 0x1b) + return 0x00; + + if (m_out0data == 0x17) + return 0x00; + + return 0x00; +} + +void monon_color_state::do_draw_inner(int pal_to_use, int start, int step, int pixmask, int amount) +{ + uint8_t blend; + + if (m_storeregs[0x1c] == 0x0a) // see drgnbma main character, doesn't set this, expects solid + blend = (m_storeregs[0x09] & 0x3f) << 2; + else + blend = 0; + + int yadjust = (m_storeregs[0x16] << 8) | m_storeregs[0x1a]; + yadjust >>= 7; + yadjust -= 8; + + for (int i = 0; i < amount; i++) + { + spibuf_w(0x00); // clock + uint8_t pix = spibuf_r(); + + for (int i = start; i >= 0; i -= step) + { + int real_ypos = m_bufpos_y; + real_ypos -= yadjust; + if ((real_ypos >= 0) && (real_ypos < 240)) + { + uint8_t pixx = (pix >> i) & pixmask; + uint8_t newr = m_curpal[((pixx + pal_to_use) * 3) + 2]; + uint8_t newg = m_curpal[((pixx + pal_to_use) * 3) + 1]; + uint8_t newb = m_curpal[((pixx + pal_to_use) * 3) + 0]; + rgb_t rgb = rgb_t(newr, newg, newb); + + if (rgb != rgb_t(0xdc, 0x32, 0xdc)) // magic transparency colour?! + { + + if (blend != 0x00) + { + rgb_t behind = m_linebuf[real_ypos]; + behind.scale8(0xff - blend); + rgb.scale8(blend); + + rgb += behind; + m_linebuf[real_ypos] = rgb; + } + else + { + m_linebuf[real_ypos] = rgb; + + } + } + } + m_bufpos_y--; + } + } +} +void monon_color_state::do_draw(int amount, int pal_to_use) +{ + if (m_storeregs[0x12] == 0x13) // 8bpp mode + { + do_draw_inner(pal_to_use, 0, 1, 0xff, amount); + } + else if (m_storeregs[0x12] == 0x12) // 4bpp mode + { + do_draw_inner(pal_to_use, 4, 4, 0xf, amount); + } + else if (m_storeregs[0x12] == 0x11) // 2bpp mode + { + do_draw_inner(pal_to_use, 6, 2, 0x3, amount); + } + else if (m_storeregs[0x12] == 0x10) // 1bpp mode + { + do_draw_inner(pal_to_use, 7, 1, 1, amount); + } + + m_bufpos_y = 239; +} + +void monon_color_state::do_palette(int amount, int pal_to_use) +{ + for (int i = 0; i < amount; i++) + { + spibuf_w(0x00); // clock + uint8_t romdat = spibuf_r(); + + int address = i + pal_to_use * 3; + m_curpal[address] = romdat; + int entry = address / 3; + + m_palette->set_pen_color(entry, rgb_t(m_curpal[(entry * 3) + 2], m_curpal[(entry * 3) + 1], m_curpal[(entry * 3) + 0])); + } +} + + + +void monon_color_state::write_to_video_device(uint8_t data) +{ + static const char* const names[] = + { + "(Direct Data)", // Direct Data port, after setting 0x8 / 0x04 ? writes basic 'maximum intensity' R/G/B palettes here on startup + "(Transfer Size MSB)", + "(Allow/Disallow SPI Access?)", + "(unknown 0x03)", + "(Direct VRAM Address Select MSB?)", + "(unknown 0x05)", + "(unknown 0x06)", + "(unknown 0x07)", + "(Direct VRAM Address Select LSB?)", + "(Blend level, when enabled)", + "(unknown 0x0a)", + "(unknown 0x0b)", + "(Trigger Transfer/Mode)", + "(unknown 0x0d)", + "(Transfer Size LSB)", + "(unknown 0x0f)", + "(Configure Magic Trans Pen B?)", // on startup + "(Palette Select)", + "(BPP Select)", + "(unknown 0x13)", + "(Configure Magic Trans Pen R?)", // on startup + "(unknown 0x15)", + "(Y Adjust MSB)", + "(used 0x17)", // some kind of command / data? (writes a 320x240 set of 00 here at startup, followed by a 0x1f 'clock' write every time?) + "(Configure Magic Trans Pen G?)", // on startup + "(unknown 0x19)", + "(Y Adjust LSB)", + "(Column Advance+More?)", + "(Draw Mode, alpha enable, trans pen disable?)", + "(unknown 0x1d)", + "(Extra Palette Select?)", // written when there is text on the screen some kind of extra base select (LSB?) in 1bpp mode? seems to be for palettes directly uploaded at startup + "(Clock for 0x17?)", // clock for 0x17? always writes after reading / writing 0x1f? + }; + + LOGMASKED(LOG_VDP, "%s: write_to_video_device (m_out0data is %02x) %s (data is %02x)\n", machine().describe_context(), m_out0data, names[m_out0data], data); + + if (m_out4data == 0x03) + { + if (m_out0data < 0x20) + { + if (m_out0data >= 0x10) // when out4data is 0x03 registers(?) used are also always >= 0x10? + m_storeregs[m_out0data] = data; + } + + // popmessage("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x | %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", m_storeregs[0x00], m_storeregs[0x01], m_storeregs[0x02], m_storeregs[0x03], m_storeregs[0x04], m_storeregs[0x05], m_storeregs[0x06], m_storeregs[0x07], m_storeregs[0x08], m_storeregs[0x09], m_storeregs[0x0a], m_storeregs[0x0b], m_storeregs[0x0c], m_storeregs[0x0d], m_storeregs[0x0e], m_storeregs[0x0f], + // m_storeregs[0x10], m_storeregs[0x11], m_storeregs[0x12], m_storeregs[0x13], m_storeregs[0x14], m_storeregs[0x15], m_storeregs[0x16], m_storeregs[0x17], m_storeregs[0x18], m_storeregs[0x19], m_storeregs[0x1a], m_storeregs[0x1b], m_storeregs[0x1c], m_storeregs[0x1d], m_storeregs[0x1e], m_storeregs[0x1f]); + + } + else if (m_out4data == 0x09) + { + if (m_out0data < 0x20) + { + if (m_out0data < 0x10) // when out4data is 0x09 registers(?) used are also always < 0x10? + { + m_storeregs[m_out0data] = data; + } + } + } + + // it uploads some colours at startup (and sometimes changes values using this during the game) + // it is unclear how the address of 0x8e relates to palette entries 0x400+ + // these seem to be used for the 1bpp text see purcfs name entry, lolfight stats + if (m_out0data == 0x00) + { + if (m_storeregs[0x04] == 0x8e) + { + int addressx = (m_storeregs[0x08]++); + int address = addressx + 0x400 * 3; + m_curpal[address] = data; + int entry = address / 3; + m_palette->set_pen_color(entry, rgb_t(m_curpal[(entry * 3) + 2], m_curpal[(entry * 3) + 1], m_curpal[(entry * 3) + 0])); + } + } + + if (m_out0data == 0x1b) + { + if (data == 0x81) + { + LOGMASKED(LOG_VDP, "Finished Column %d\n", m_bufpos_x); + m_bufpos_x++; + + if (m_bufpos_x == 320) + { + LOGMASKED(LOG_VDP, "------------------------------------------------------------------------------------------------\n"); + m_bufpos_x = 0; + } + + m_bufpos_y = 239; + } + } + + // (m_storeregs[0x1c] == 0x11) backgrounds (maybe no trans pen?) + // (m_storeregs[0x1c] == 0x01) most elements + // (m_storeregs[0x1c] == 0x00) some elements in purceb and zombhunt + // (m_storeregs[0x1c] == 0x0a) blended elements + + if (m_out0data == 0x0c) + { + if ((m_storeregs[0x1c] == 0x00) || (m_storeregs[0x1c] == 0x0a) || (m_storeregs[0x1c] == 0x01) || (m_storeregs[0x1c] == 0x11)) + { + uint16_t amount = m_storeregs[0x0e] | (m_storeregs[0x01] << 8); + + //if (amount != 0x00) + { + int pal_to_use = (m_storeregs[0x11] << 8) | m_storeregs[0x1e]; + + pal_to_use >>= 5; + pal_to_use &= 0x7ff; + + + // d4/d6 are odd-even columns + // d0/d2 are odd-even columns, after frame data? (writing them seems conditional on something else?) + // da/de are palettes? (maybe bit 0x04 is just ignored here, these aren't column specific) + + if ((data == 0xde) || (data == 0xda)) + { + if (m_storeregs[0x02] == 0x20) + do_palette(amount, pal_to_use); + } + else if ((data == 0xd2) || (data == 0xd6)) + { + if (m_storeregs[0x02] == 0x20) + do_draw(amount, pal_to_use); + + } + else if ((data == 0xd0) || (data == 0xd4)) + { + // assume there's some kind of line column buffer, the exact swap trigger is unknown + for (int i = 0; i < 240; i++) + m_vidbuffer[(i * 320) + m_bufpos_x] = m_linebuf[i]; + } + } + } + else + { + fatalerror("m_storeregs[0x1c] set to unknown value %02x while drawing\n", m_storeregs[0x1c]); + } + } +} + +void monon_color_state::out3_w(uint8_t data) +{ + m_out3data = data; +} + +void monon_color_state::out4_w(uint8_t data) +{ + m_out4data = data; +} + +void monon_color_state::monon_color(machine_config &config) +{ + /* basic machine hardware */ + AX208(config, m_maincpu, 96000000/2); // divider is not correct, need to check if this is configured to run at full speed + m_maincpu->port_in_cb<0>().set(FUNC(monon_color_state::in0_r)); + m_maincpu->port_in_cb<1>().set(FUNC(monon_color_state::in1_r)); + m_maincpu->port_in_cb<2>().set(FUNC(monon_color_state::in2_r)); + m_maincpu->port_in_cb<3>().set(FUNC(monon_color_state::in3_r)); + m_maincpu->port_in_cb<4>().set(FUNC(monon_color_state::in4_r)); + m_maincpu->port_out_cb<0>().set(FUNC(monon_color_state::out0_w)); + m_maincpu->port_out_cb<1>().set(FUNC(monon_color_state::out1_w)); + m_maincpu->port_out_cb<2>().set(FUNC(monon_color_state::out2_w)); + m_maincpu->port_out_cb<3>().set(FUNC(monon_color_state::out3_w)); + m_maincpu->port_out_cb<4>().set(FUNC(monon_color_state::out4_w)); + m_maincpu->spi_in_cb().set(FUNC(monon_color_state::spibuf_direct_r)); + m_maincpu->spi_out_cb().set(FUNC(monon_color_state::spibuf_w)); + m_maincpu->spi_out_dir_cb().set(FUNC(monon_color_state::spidir_w)); + m_maincpu->dac_out_cb<0>().set(FUNC(monon_color_state::dacout0_w)); + m_maincpu->dac_out_cb<1>().set(FUNC(monon_color_state::dacout1_w)); + + /* video hardware */ + + // is this a 3:4 (true vertical) 240x320 screen rotated on its side? + // the scan direction for drawing is highly unusual + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(120); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); + m_screen->set_screen_update(FUNC(monon_color_state::screen_update)); + m_screen->set_size(320, 240); + m_screen->set_visarea(0*8, 320-1, 0*8, 240-1); + + PALETTE(config, m_palette).set_entries(0x800); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + DAC_8BIT_R2R_TWOS_COMPLEMENT(config, m_dac, 0).add_route(ALL_OUTPUTS, "mono", 0.500); // should this be in the AX208 device? + + mononcol_cartslot_device &cartslot(MONONCOL_CARTSLOT(config, "cartslot", mononcol_plain_slot)); + cartslot.set_must_be_loaded(true); + + /* software lists */ + SOFTWARE_LIST(config, "cart_list").set_original("monon_color"); +} + +ROM_START( mononcol ) +ROM_END + +CONS( 2014, mononcol, 0, 0, monon_color, monon_color, monon_color_state, empty_init, "M&D", "Monon Color", MACHINE_IMPERFECT_TIMING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) diff --git a/src/mame/skeleton/monon_color.cpp b/src/mame/skeleton/monon_color.cpp deleted file mode 100644 index 45e14443eec..00000000000 --- a/src/mame/skeleton/monon_color.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/*************************************************************************** - Monon Color - Chinese handheld - - see - https://gbatemp.net/threads/the-monon-color-a-new-video-game-console-from-china.467788/ - https://twitter.com/Splatoon2weird/status/1072182093206052864 - - uses AX208 CPU (custom 8051 @ 96Mhz with single cycle instructions, extended '16 bit' opcodes + integrated video, jpeg decoder etc.) - https://docplayer.net/52724058-Ax208-product-specification.html - -***************************************************************************/ - -#include "emu.h" -#include "cpu/axc51/axc51.h" -#include "emupal.h" -#include "screen.h" -#include "softlist_dev.h" -#include "speaker.h" -#include "bus/generic/slot.h" -#include "bus/generic/carts.h" - -class monon_color_state : public driver_device -{ -public: - monon_color_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_cart(*this, "cartslot"), - m_maincpu(*this, "maincpu"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_mainram(*this, "mainram") - { } - - void monon_color(machine_config &config); -protected: - // driver_device overrides - virtual void machine_start() override; - virtual void machine_reset() override; - - virtual void video_start() override; - - // screen updates - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); -private: - required_device m_cart; - required_device m_maincpu; - required_device m_screen; - required_device m_palette; - required_shared_ptr m_mainram; - - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); - - void monon_color_map(address_map &map); - void monon_color_io_map(address_map &map); -}; - -void monon_color_state::machine_start() -{ -} - - - -void monon_color_state::machine_reset() -{ - m_maincpu->set_spi_ptr(memregion("flash")->base(), memregion("flash")->bytes() ); - - - /* block starting at e000 in flash is not code? (or encrypted?) - no code to map at 0x9000 in address space (possible BIOS?) - no code in flash ROM past the first 64kb(?) which is basically the same on all games, must be some kind of script interpreter? J2ME maybe? - - there are 5 different 'versions' of the code in the dumped ROMs, where the code is the same the roms match up until 0x50000 after which the game specific data starts - - by game number: - - 103alt (earliest? doesn't have bank9) - 101,102,103,104,105 (1st revision) - 106,107 (2nd revision) - 201 (3rd revision) - 202,203,204,205,301,302,303,304 (4th revision) - */ -} - -void monon_color_state::video_start() -{ -} - - -uint32_t monon_color_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - return 0; -} - -static INPUT_PORTS_START( monon_color ) -INPUT_PORTS_END - -void monon_color_state::monon_color_map(address_map &map) -{ - map(0x4000, 0x6fff).ram().share("mainram"); -// map(0x9000, 0x9fff).rom() // internal to CPU -} - - -void monon_color_state::monon_color_io_map(address_map& map) -{ - map(0x0000, 0x00ff).ram(); - - map(0x4000, 0x6fff).ram().share("mainram"); -} - -void monon_color_state::monon_color(machine_config &config) -{ - /* basic machine hardware */ - AX208(config, m_maincpu, 96000000); // (8051 / MCS51 derived) incomplete core! - m_maincpu->set_addrmap(AS_PROGRAM, &monon_color_state::monon_color_map); - m_maincpu->set_addrmap(AS_IO, &monon_color_state::monon_color_io_map); - - /* video hardware */ - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(60); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); - m_screen->set_screen_update(FUNC(monon_color_state::screen_update)); - m_screen->set_size(32*8, 32*8); - m_screen->set_visarea(0*8, 32*8-1, 2*8, 30*8-1); - m_screen->set_palette(m_palette); - - PALETTE(config, m_palette).set_entries(256); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "monon_color_cart", "bin")); - cartslot.set_width(GENERIC_ROM8_WIDTH); - cartslot.set_device_load(FUNC(monon_color_state::cart_load)); - cartslot.set_must_be_loaded(true); - - /* software lists */ - SOFTWARE_LIST(config, "cart_list").set_original("monon_color"); -} - -DEVICE_IMAGE_LOAD_MEMBER( monon_color_state::cart_load ) -{ - uint32_t size = m_cart->common_get_size("rom"); - std::vector temp; - temp.resize(size); - m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE); - m_cart->common_load_rom(&temp[0], size, "rom"); - - memcpy(memregion("flash")->base(), &temp[0], size); - - return image_init_result::PASS; -} - -ROM_START( mononcol ) - ROM_REGION( 0x1000000, "flash", ROMREGION_ERASE00 ) -ROM_END - -CONS( 2011, mononcol, 0, 0, monon_color, monon_color, monon_color_state, empty_init, "M&D", "Monon Color", MACHINE_IS_SKELETON ) diff --git a/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp b/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp index c7b03fbacba..6a78ff04068 100644 --- a/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp +++ b/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp @@ -18,6 +18,7 @@ (bkid218 cursor in test menu can't be moved in emulation, works on unit, why?) */ +// TODO: convert to use generic_spi_flash.cpp (but there seems to be some buffering of writes / reads?) #include "emu.h" diff --git a/src/mame/tvgames/st2302u_bbl_spi.cpp b/src/mame/tvgames/st2302u_bbl_spi.cpp index 7d73091f073..aa29a00c68b 100644 --- a/src/mame/tvgames/st2302u_bbl_spi.cpp +++ b/src/mame/tvgames/st2302u_bbl_spi.cpp @@ -25,6 +25,8 @@ supreme 0x243e */ +// TODO: convert to use generic_spi_flash.cpp (but there seems to be some buffering of writes / reads?) + #include "emu.h" #include "cpu/m6502/st2205u.h" -- cgit v1.2.3