summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua22
-rw-r--r--src/devices/cpu/axc51/axc51.cpp1263
-rw-r--r--src/devices/cpu/axc51/axc51.h479
-rw-r--r--src/devices/cpu/axc51/axc51dasm.cpp (renamed from src/devices/cpu/mcs51/axc51-core_dasm.cpp)1019
-rw-r--r--src/devices/cpu/axc51/axc51dasm.h (renamed from src/devices/cpu/mcs51/axc51-core_dasm.h)59
-rw-r--r--src/devices/cpu/axc51/axc51ops.hxx982
-rw-r--r--src/devices/cpu/mcs51/axc51-core.cpp110
-rw-r--r--src/devices/cpu/mcs51/axc51-core.h65
-rw-r--r--src/devices/cpu/mcs51/mcs51.h2
-rw-r--r--src/mame/skeleton/monon_color.cpp50
-rw-r--r--src/tools/unidasm.cpp2
11 files changed, 3813 insertions, 240 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 03770359e82..fb357bb05b7 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -1091,16 +1091,30 @@ if CPUS["MCS51"] then
MAME_DIR .. "src/devices/cpu/mcs51/mcs51.cpp",
MAME_DIR .. "src/devices/cpu/mcs51/mcs51.h",
MAME_DIR .. "src/devices/cpu/mcs51/mcs51ops.hxx",
- MAME_DIR .. "src/devices/cpu/mcs51/axc51-core.cpp",
- MAME_DIR .. "src/devices/cpu/mcs51/axc51-core.h",
}
end
if opt_tool(CPUS, "MCS51") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mcs51/mcs51dasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mcs51/mcs51dasm.h")
- table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mcs51/axc51-core_dasm.cpp")
- table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mcs51/axc51-core_dasm.h")
+end
+
+--------------------------------------------------
+-- Appotech AXC-51 (extended Intel 8051)
+--@src/devices/cpu/axc51/axc51.h,CPUS["AXC51"] = true
+--------------------------------------------------
+
+if CPUS["AXC51"] then
+ files {
+ MAME_DIR .. "src/devices/cpu/axc51/axc51.cpp",
+ MAME_DIR .. "src/devices/cpu/axc51/axc51.h",
+ MAME_DIR .. "src/devices/cpu/axc51/axc51ops.hxx",
+ }
+end
+
+if opt_tool(CPUS, "AXC51") then
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/axc51/axc51dasm.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/acx51/axc51dasm.h")
end
--------------------------------------------------
diff --git a/src/devices/cpu/axc51/axc51.cpp b/src/devices/cpu/axc51/axc51.cpp
new file mode 100644
index 00000000000..b3dc2269075
--- /dev/null
+++ b/src/devices/cpu/axc51/axc51.cpp
@@ -0,0 +1,1263 @@
+// 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.
+
+*/
+
+/*****************************************************************************
+
+ AXC51-CORE / AX208 SoC (AppoTech Inc.)
+
+ AXC51CORE:
+ somes sources indicate that the extended opcode encoding may change
+ on some CPU models despite all being 'AXC51CORE' however we lack solid
+ information on this at present.
+
+ AX208:
+ The CPU has 0x2000 bytes of internal ROM mapped at 0x8000-0x9fff providing
+ bootcode, operating kernel and many standard library functions
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "axc51.h"
+#include "axc51dasm.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+
+DEFINE_DEVICE_TYPE(AX208, ax208_cpu_device, "ax208", "AppoTech AX208 (AXC51-CORE)")
+DEFINE_DEVICE_TYPE(AX208P, ax208p_cpu_device, "ax208p", "AppoTech AX208 (AXC51-CORE) (prototype?)")
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+void axc51base_cpu_device::program_internal(address_map &map)
+{
+}
+
+void axc51base_cpu_device::data_internal(address_map &map)
+{
+ map(0x0000, 0x00ff).ram().share("scratchpad");
+ map(0x0100, 0x01ff).ram().share("sfr_ram"); /* SFR */
+}
+
+void ax208_cpu_device::ax208_internal_program_mem(address_map &map)
+{
+ map(0x8000, 0x9fff).rom().region("rom", 0); // this can only be read from code running within the same region
+}
+
+
+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)
+ : 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_pc(0)
+ , m_features(features)
+ , m_rom_size(program_width > 0 ? 1 << program_width : 0)
+ , m_ram_mask( (data_width == 8) ? 0xFF : 0x7F )
+ , m_num_interrupts(5)
+ , m_sfr_ram(*this, "sfr_ram")
+ , m_scratchpad(*this, "scratchpad")
+ , m_port_in_cb(*this)
+ , m_port_out_cb(*this)
+ , m_serial_tx_cb(*this)
+ , m_serial_rx_cb(*this)
+ , m_rtemp(0)
+{
+ /* default to standard cmos interfacing */
+ for (auto & elem : m_forced_inputs)
+ elem = 0;
+}
+
+
+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)
+{
+}
+
+
+device_memory_interface::space_config_vector axc51base_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_data_config),
+ std::make_pair(AS_IO, &m_io_config)
+ };
+}
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* 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 (a <= m_ram_mask) ? m_data.read_byte(a) : 0xff; }
+void axc51base_cpu_device::iram_iwrite(offs_t a, uint8_t d) { if (a <= m_ram_mask) m_data.write_byte(a, d); }
+
+#define IRAM_IR(a) iram_iread(a)
+#define IRAM_IW(a, d) iram_iwrite(a, d)
+
+/* Form an Address to Read/Write to External RAM indirectly */
+/* (called from indirect addressing) */
+#define ERAM_ADDR(a,m) external_ram_iaddr(a,m)
+
+/* 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)
+
+
+/***************************************************************************
+ SHORTCUTS
+***************************************************************************/
+
+#define PPC m_ppc
+#define PC m_pc
+#define RWM m_rwm
+
+/* SFR Registers - These are accessed directly for speed on read */
+/* Read accessors */
+
+#define SFR_A(a) m_sfr_ram[(a)]
+#define SET_SFR_A(a,v) do { SFR_A(a) = (v); } while (0)
+
+#define ACC SFR_A(ADDR_ACC)
+#define PSW SFR_A(ADDR_PSW)
+
+#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 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 R_REG(r) m_scratchpad[(r) | (PSW & 0x18)]
+#define DPTR ((DPH<<8) | DPL)
+
+/* WRITE accessors */
+
+/* Shortcuts */
+
+#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)
+
+/* 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)
+
+
+
+/* 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)
+
+/* 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_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_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_RS GET_BIT(PSW, 3)
+#define GET_OV GET_BIT(PSW, 2)
+#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)
+
+
+
+/*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 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
+***************************************************************************/
+
+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));
+}
+
+uint8_t axc51base_cpu_device::r_acc() { return SFR_A(ADDR_ACC); }
+
+uint8_t axc51base_cpu_device::r_psw() { return SFR_A(ADDR_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;
+}
+
+/* Internal ram read/write */
+
+uint8_t axc51base_cpu_device::iram_read(size_t offset)
+{
+ return (((offset) < 0x80) ? m_data.read_byte(offset) : sfr_read(offset));
+}
+
+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);
+}
+
+/*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)
+ 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)
+}
+
+/*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)
+ SP = tmpSP; //Decrement Stack Pointer
+}
+
+//Set the PSW Parity Flag
+void axc51base_cpu_device::set_parity()
+{
+ //This flag will be set when the accumulator contains an odd # of bits set..
+ uint8_t p = 0;
+ int i;
+ uint8_t a = ACC;
+
+ for (i=0; i<8; i++) { //Test for each of the 8 bits in the ACC!
+ p ^= (a & 1);
+ a = (a >> 1);
+ }
+
+ SET_P(p & 1);
+}
+
+uint8_t axc51base_cpu_device::bit_address_r(uint8_t offset)
+{
+ uint8_t word;
+ uint8_t mask;
+ int bit_pos;
+ int distance; /* distance between bit addressable words */
+ /* 1 for normal bits, 8 for sfr bit addresses */
+
+ m_last_bit = offset;
+
+ //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
+ if (offset < 0x80) {
+ distance = 1;
+ word = ( (offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ mask = (0x1 << bit_pos);
+ return((IRAM_R(word) & mask) >> bit_pos);
+ }
+ //SFR bit addressable registers
+ else {
+ distance = 8;
+ word = ( (offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ mask = (0x1 << bit_pos);
+ return ((IRAM_R(word) & mask) >> bit_pos);
+ }
+}
+
+
+void axc51base_cpu_device::bit_address_w(uint8_t offset, uint8_t bit)
+{
+ int word;
+ uint8_t mask;
+ int bit_pos;
+ uint8_t result;
+ int distance;
+
+ /* User defined bit addresses 0x20-0x2f (values are 0x0-0x7f) */
+ if (offset < 0x80) {
+ distance = 1;
+ word = ((offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+ /* SFR bit addressable registers */
+ else {
+ distance = 8;
+ word = ((offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+}
+
+void axc51base_cpu_device::do_add_flags(uint8_t a, uint8_t data, uint8_t c)
+{
+ uint16_t result = a+data+c;
+ int16_t result1 = (int8_t)a+(int8_t)data+c;
+
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)+(data&0x0f)+c;
+ SET_AC((result & 0x10) >> 4);
+ SET_OV(result1 < -128 || result1 > 127);
+}
+
+void axc51base_cpu_device::do_sub_flags(uint8_t a, uint8_t data, uint8_t c)
+{
+ uint16_t result = a-(data+c);
+ int16_t result1 = (int8_t)a-(int8_t)(data+c);
+
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)-((data&0x0f)+c);
+ SET_AC((result & 0x10) >> 4);
+ 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)
+{
+}
+
+void axc51base_cpu_device::update_timers(int cycles)
+{
+ while (cycles--)
+ {
+ update_timer_t0(1);
+ update_timer_t1(1);
+ }
+}
+
+void axc51base_cpu_device::serial_transmit(uint8_t data)
+{
+}
+
+void axc51base_cpu_device::serial_receive()
+{
+}
+
+/* Check and update status of serial port */
+void axc51base_cpu_device::update_serial(int cycles)
+{
+ while (--cycles>=0)
+ transmit_receive(0);
+}
+
+/* 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);
+}
+
+
+/***************************************************************************
+ OPCODES
+***************************************************************************/
+
+#define OPHANDLER( _name ) void axc51base_cpu_device::_name (uint8_t r)
+
+#include "axc51ops.hxx"
+
+
+void axc51base_cpu_device::execute_op(uint8_t op)
+{
+ if (m_recalc_parity)
+ {
+ set_parity();
+ m_recalc_parity = 0;
+ }
+
+ m_last_op = op;
+
+ switch( op )
+ {
+ case 0x00: nop(op); break; //NOP
+ case 0x01: ajmp(op); break; //AJMP code addr
+ case 0x02: ljmp(op); break; //LJMP code addr
+ case 0x03: rr_a(op); break; //RR A
+ case 0x04: inc_a(op); break; //INC A
+ case 0x05: RWM=1; inc_mem(op); RWM=0; break; //INC data addr
+
+ case 0x06:
+ case 0x07: inc_ir(op&1); break; //INC @R0/@R1
+
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f: inc_r(op&7); break; //INC R0 to R7
+
+ case 0x10: RWM=1; jbc(op); RWM=0; break; //JBC bit addr, code addr
+ case 0x11: acall(op); break; //ACALL code addr
+ case 0x12: lcall(op); break; //LCALL code addr
+ case 0x13: rrc_a(op); break; //RRC A
+ case 0x14: dec_a(op); break; //DEC A
+ case 0x15: RWM=1; dec_mem(op); RWM=0; break; //DEC data addr
+
+ case 0x16:
+ case 0x17: dec_ir(op&1); break; //DEC @R0/@R1
+
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: dec_r(op&7); break; //DEC R0 to R7
+
+ case 0x20: jb(op); break; //JB bit addr, code addr
+ case 0x21: ajmp(op); break; //AJMP code addr
+ case 0x22: ret(op); break; //RET
+ case 0x23: rl_a(op); break; //RL A
+ case 0x24: add_a_byte(op); break; //ADD A, #data
+ case 0x25: add_a_mem(op); break; //ADD A, data addr
+
+ case 0x26:
+ case 0x27: add_a_ir(op&1); break; //ADD A, @R0/@R1
+
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f: add_a_r(op&7); break; //ADD A, R0 to R7
+
+ case 0x30: jnb(op); break; //JNB bit addr, code addr
+ case 0x31: acall(op); break; //ACALL code addr
+ case 0x32: reti(op); break; //RETI
+ case 0x33: rlc_a(op); break; //RLC A
+ case 0x34: addc_a_byte(op); break; //ADDC A, #data
+ case 0x35: addc_a_mem(op); break; //ADDC A, data addr
+
+ case 0x36:
+ case 0x37: addc_a_ir(op&1); break; //ADDC A, @R0/@R1
+
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: addc_a_r(op&7); break; //ADDC A, R0 to R7
+
+ case 0x40: jc(op); break; //JC code addr
+ case 0x41: ajmp(op); break; //AJMP code addr
+ case 0x42: RWM=1; orl_mem_a(op); RWM=0; break; //ORL data addr, A
+ case 0x43: RWM=1; orl_mem_byte(op); RWM=0; break; //ORL data addr, #data
+ case 0x44: orl_a_byte(op); break;
+ case 0x45: orl_a_mem(op); break; //ORL A, data addr
+
+ case 0x46:
+ case 0x47: orl_a_ir(op&1); break; //ORL A, @RO/@R1
+
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f: orl_a_r(op&7); break; //ORL A, RO to R7
+
+ case 0x50: jnc(op); break; //JNC code addr
+ case 0x51: acall(op); break; //ACALL code addr
+ case 0x52: RWM=1; anl_mem_a(op); RWM=0; break; //ANL data addr, A
+ case 0x53: RWM=1; anl_mem_byte(op); RWM=0; break; //ANL data addr, #data
+ case 0x54: anl_a_byte(op); break; //ANL A, #data
+ case 0x55: anl_a_mem(op); break; //ANL A, data addr
+
+ case 0x56:
+ case 0x57: anl_a_ir(op&1); break; //ANL A, @RO/@R1
+
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f: anl_a_r(op&7); break; //ANL A, RO to R7
+
+ case 0x60: jz(op); break; //JZ code addr
+ case 0x61: ajmp(op); break; //AJMP code addr
+ case 0x62: RWM=1; xrl_mem_a(op); RWM=0; break; //XRL data addr, A
+ case 0x63: RWM=1; xrl_mem_byte(op); RWM=0; break; //XRL data addr, #data
+ case 0x64: xrl_a_byte(op); break; //XRL A, #data
+ case 0x65: xrl_a_mem(op); break; //XRL A, data addr
+
+ case 0x66:
+ case 0x67: xrl_a_ir(op&1); break; //XRL A, @R0/@R1
+
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f: xrl_a_r(op&7); break; //XRL A, R0 to R7
+
+ case 0x70: jnz(op); break; //JNZ code addr
+ case 0x71: acall(op); break; //ACALL code addr
+ case 0x72: orl_c_bitaddr(op); break; //ORL C, bit addr
+ case 0x73: jmp_iadptr(op); break; //JMP @A+DPTR
+ case 0x74: mov_a_byte(op); break; //MOV A, #data
+ case 0x75: mov_mem_byte(op); break; //MOV data addr, #data
+
+ case 0x76:
+ case 0x77: mov_ir_byte(op&1); break; //MOV @R0/@R1, #data
+
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f: mov_r_byte(op&7); break; //MOV R0 to R7, #data
+
+ case 0x80: sjmp(op); break; //SJMP code addr
+ case 0x81: ajmp(op); break; //AJMP code addr
+ case 0x82: anl_c_bitaddr(op); break; //ANL C, bit addr
+ case 0x83: movc_a_iapc(op); break; //MOVC A, @A + PC
+ case 0x84: div_ab(op); break; //DIV AB
+ case 0x85: mov_mem_mem(op); break; //MOV data addr, data addr
+
+ case 0x86:
+ case 0x87: mov_mem_ir(op&1); break; //MOV data addr, @R0/@R1
+
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f: mov_mem_r(op&7); break; //MOV data addr,R0 to R7
+
+ case 0x90: mov_dptr_byte(op); break; //MOV DPTR, #data
+ case 0x91: acall(op); break; //ACALL code addr
+ case 0x92: RWM = 1; mov_bitaddr_c(op); RWM = 0; break; //MOV bit addr, C
+ case 0x93: movc_a_iadptr(op); break; //MOVC A, @A + DPTR
+ case 0x94: subb_a_byte(op); break; //SUBB A, #data
+ case 0x95: subb_a_mem(op); break; //SUBB A, data addr
+
+ case 0x96:
+ case 0x97: subb_a_ir(op&1); break; //SUBB A, @R0/@R1
+
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f: subb_a_r(op&7); break; //SUBB A, R0 to R7
+
+ case 0xa0: orl_c_nbitaddr(op); break; //ORL C, /bit addr
+ case 0xa1: ajmp(op); break; //AJMP code addr
+ 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 0xa6:
+ case 0xa7: mov_ir_mem(op&1); break; //MOV @R0/@R1, data addr
+
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf: mov_r_mem(op&7); break; //MOV R0 to R7, data addr
+
+ case 0xb0: anl_c_nbitaddr(op); break; //ANL C,/bit addr
+ case 0xb1: acall(op); break; //ACALL code addr
+ case 0xb2: RWM=1; cpl_bitaddr(op); RWM=0; break; //CPL bit addr
+ case 0xb3: cpl_c(op); break; //CPL C
+ case 0xb4: cjne_a_byte(op); break; //CJNE A, #data, code addr
+ case 0xb5: cjne_a_mem(op); break; //CJNE A, data addr, code addr
+
+ case 0xb6:
+ case 0xb7: cjne_ir_byte(op&1); break; //CJNE @R0/@R1, #data, code addr
+
+ case 0xb8:
+ case 0xb9:
+ case 0xba:
+ case 0xbb:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ case 0xbf: cjne_r_byte(op&7); break; //CJNE R0 to R7, #data, code addr
+
+ case 0xc0: push(op); break; //PUSH data addr
+ case 0xc1: ajmp(op); break; //AJMP code addr
+ case 0xc2: RWM=1; clr_bitaddr(op); RWM=0; break; //CLR bit addr
+ case 0xc3: clr_c(op); break; //CLR C
+ case 0xc4: swap_a(op); break; //SWAP A
+ case 0xc5: xch_a_mem(op); break; //XCH A, data addr
+
+ case 0xc6:
+ case 0xc7: xch_a_ir(op&1); break; //XCH A, @RO/@R1
+
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf: xch_a_r(op&7); break; //XCH A, RO to R7
+
+ case 0xd0: pop(op); break; //POP data addr
+ case 0xd1: acall(op); break; //ACALL code addr
+ case 0xd2: RWM=1; setb_bitaddr(op); RWM=0; break; //SETB bit addr
+ case 0xd3: setb_c(op); break; //SETB C
+ case 0xd4: da_a(op); break; //DA A
+ case 0xd5: RWM=1; djnz_mem(op); RWM=0; break; //DJNZ data addr, code addr
+
+ case 0xd6:
+ case 0xd7: xchd_a_ir(op&1); break; //XCHD A, @R0/@R1
+
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf: djnz_r(op&7); break; //DJNZ R0 to R7,code addr
+
+ case 0xe0: movx_a_idptr(op); break; //MOVX A,@DPTR
+ case 0xe1: ajmp(op); break; //AJMP code addr
+
+ case 0xe2:
+ case 0xe3: movx_a_ir(op&1); break; //MOVX A, @R0/@R1
+
+ case 0xe4: clr_a(op); break; //CLR A
+ case 0xe5: mov_a_mem(op); break; //MOV A, data addr
+ case 0xe6:
+ case 0xe7: mov_a_ir(op&1); break; //MOV A,@RO/@R1
+
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef: mov_a_r(op&7); break; //MOV A,R0 to R7
+
+ case 0xf0: movx_idptr_a(op); break; //MOVX @DPTR,A
+ case 0xf1: acall(op); break; //ACALL code addr
+
+ case 0xf2:
+ case 0xf3: movx_ir_a(op&1); break; //MOVX @R0/@R1,A
+
+ case 0xf4: cpl_a(op); break; //CPL A
+ case 0xf5: mov_mem_a(op); break; //MOV data addr, A
+
+ case 0xf6:
+ case 0xf7: mov_ir_a(op&1); break; //MOV @R0/@R1, A
+
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff: mov_r_a(op&7); break; //MOV R0 to R7, A
+ default:
+ illegal(op);
+ }
+}
+
+/***************************************************************************
+ OPCODE CYCLES
+***************************************************************************/
+
+/* # of oscilations each opcode requires*/
+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,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+
+void axc51base_cpu_device::check_irqs()
+{
+}
+
+void axc51base_cpu_device::burn_cycles(int cycles)
+{
+ /* Update Timer (if any timers are running) */
+ update_timers(cycles);
+
+ /* Update Serial (only for mode 0) */
+ update_serial(cycles);
+
+ /* check_irqs */
+ check_irqs();
+}
+
+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);
+ /* detect 0->1 transitions */
+ //uint32_t tr_state = (~m_last_line_state) & new_state;
+
+ // TODO
+
+ m_last_line_state = new_state;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+void axc51base_cpu_device::execute_run()
+{
+ uint8_t op;
+
+ /* external interrupts may have been set since we last checked */
+ m_inst_cycles = 0;
+ 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++);
+
+ /* process opcode and count cycles */
+ m_inst_cycles = axc51_cycles[op];
+ execute_op(op);
+
+ /* burn the cycles */
+ m_icount -= m_inst_cycles;
+
+ burn_cycles(m_inst_cycles);
+
+ } while( m_icount > 0 );
+}
+
+
+
+
+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;
+ }
+ m_data.write_byte((size_t)offset | 0x100, data);
+}
+
+uint8_t axc51base_cpu_device::sfr_read(size_t offset)
+{
+ assert(offset >= 0x80 && offset <= 0xff);
+
+ switch (offset)
+ {
+ /* Read/Write/Modify operations read the port latch ! */
+ /* Move to memory map */
+ case ADDR_P0: return RWM ? P0 : (P0 | m_forced_inputs[0]) & m_port_in_cb[0]();
+ case ADDR_P1: return RWM ? P1 : (P1 | m_forced_inputs[1]) & m_port_in_cb[1]();
+ case ADDR_P2: return RWM ? P2 : (P2 | m_forced_inputs[2]) & m_port_in_cb[2]();
+ case ADDR_P3: return RWM ? P3 : (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);
+ /* 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;
+ }
+}
+
+
+void axc51base_cpu_device::device_start()
+{
+ space(AS_PROGRAM).cache(m_program);
+ space(AS_DATA).specific(m_data);
+ space(AS_IO).specific(m_io);
+
+ 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();
+
+ /* 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_rwm) );
+ save_item(NAME(m_cur_irq_prio) );
+ save_item(NAME(m_last_line_state) );
+ save_item(NAME(m_t0_cnt) );
+ save_item(NAME(m_t1_cnt) );
+ save_item(NAME(m_t2_cnt) );
+ save_item(NAME(m_t2ex_cnt) );
+ 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<uint16_t>( 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");
+ if (m_rom_size > 0)
+ state_add<uint8_t>( AXC51_P0, "P0", [this](){ return P0; }, [this](uint8_t p){ SET_P0(p); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_P1, "P1", [this](){ return P1; }, [this](uint8_t p){ SET_P1(p); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_P2, "P2", [this](){ return P2; }, [this](uint8_t p){ SET_P2(p); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_P3, "P3", [this](){ return P3; }, [this](uint8_t p){ SET_P3(p); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R0, "R0", [this](){ return R_REG(0); }, [this](uint8_t r){ SET_REG(0, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R1, "R1", [this](){ return R_REG(1); }, [this](uint8_t r){ SET_REG(1, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R2, "R2", [this](){ return R_REG(2); }, [this](uint8_t r){ SET_REG(2, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R3, "R3", [this](){ return R_REG(3); }, [this](uint8_t r){ SET_REG(3, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R4, "R4", [this](){ return R_REG(4); }, [this](uint8_t r){ SET_REG(4, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R5, "R5", [this](){ return R_REG(5); }, [this](uint8_t r){ SET_REG(5, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R6, "R6", [this](){ return R_REG(6); }, [this](uint8_t r){ SET_REG(6, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_R7, "R7", [this](){ return R_REG(7); }, [this](uint8_t r){ SET_REG(7, r); }).formatstr("%02X");
+ state_add<uint8_t>( AXC51_RB, "RB", [this](){ return (PSW & 0x18)>>3; }, [this](uint8_t rb){ SET_RS(rb); }).mask(0x03).formatstr("%02X");
+
+
+ state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
+ state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow();
+ state_add( STATE_GENFLAGS, "GENFLAGS", m_rtemp).formatstr("%8s").noshow();
+
+ set_icountptr(m_icount);
+}
+
+void axc51base_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c%c%c%c%c%c%c",
+ PSW & 0x80 ? 'C':'.',
+ PSW & 0x40 ? 'A':'.',
+ PSW & 0x20 ? 'F':'.',
+ PSW & 0x10 ? '0':'.',
+ PSW & 0x08 ? '1':'.',
+ PSW & 0x04 ? 'V':'.',
+ PSW & 0x02 ? '?':'.',
+ PSW & 0x01 ? 'P':'.');
+ break;
+ }
+}
+
+/* Reset registers to the initial values */
+void axc51base_cpu_device::device_reset()
+{
+ m_last_line_state = 0;
+ m_t0_cnt = 0;
+ m_t1_cnt = 0;
+ m_t2_cnt = 0;
+ m_t2ex_cnt = 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 */
+ RWM = 0;
+ PPC = PC;
+ PC = 0;
+ SP = 0x7;
+ SET_PSW(0);
+ SET_ACC(0);
+ DPH = 0;
+ DPL = 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;
+}
+
+
+std::unique_ptr<util::disasm_interface> axc51base_cpu_device::create_disassembler()
+{
+ return std::make_unique<axc51core_disassembler>();
+}
+
+
+
+// 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)
+{
+}
+
+
+std::unique_ptr<util::disasm_interface> ax208_cpu_device::create_disassembler()
+{
+ return std::make_unique<ax208_disassembler>();
+}
+
+
+
+
+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 ax208_cpu_device::spicon_r()
+{
+ logerror("%s: sfr_read AXC51_SPICON\n", machine().describe_context());
+ return axc51base_cpu_device::sfr_read(AXC51_SPICON);
+}
+
+uint8_t ax208_cpu_device::dpcon_r()
+{
+ logerror("%s: sfr_read AXC51_DPCON\n", machine().describe_context());
+ return axc51base_cpu_device::sfr_read(AXC51_DPCON);
+}
+
+uint8_t ax208_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);
+
+ return m_spiptr[m_spiaddr++];
+ }
+
+ logerror("%s: sfr_read AXC51_SPIBUF\n", machine().describe_context());
+
+ return machine().rand();
+ //return axc51base_cpu_device::sfr_read(AXC51_SPIBUF);
+}
+
+uint8_t ax208_cpu_device::sfr_read(size_t offset)
+{
+ switch (offset)
+ {
+ case 0x82:
+ case 0x83:
+ case 0xe0: // ACC
+ return axc51base_cpu_device::sfr_read(offset);
+
+ case AXC51_DPCON: // 0x86
+ return dpcon_r();
+
+ case AXC51_IRTCON: // 0x9f
+ return machine().rand();
+
+ case AXC51_SPICON: // 0xd8
+ return spicon_r();
+
+ case AXC51_SPIBUF: // 0xd9
+ return spibuf_r();
+
+ }
+ 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);
+}
+
+
+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)
+{
+ logerror("%s: sfr_write AXC51_DPCON %02x\n", machine().describe_context(), data);
+ axc51base_cpu_device::sfr_write(AXC51_DPCON, 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)
+{
+ logerror("%s: sfr_write AXC51_SPIDMACNT %02x\n", machine().describe_context(), data);
+ axc51base_cpu_device::sfr_write(AXC51_SPIDMACNT, data);
+}
+
+void ax208_cpu_device::sfr_write(size_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ 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
+
+ }
+
+ 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
+ ROM_REGION( 0x2000, "rom", 0 )
+ ROM_LOAD("ax208.bin", 0x0000, 0x2000, CRC(b85f954a) SHA1(0dc7ab9bdaf73231d4d6627fe6308fe8103e1bbc) )
+ROM_END
+
+const tiny_rom_entry *ax208_cpu_device::device_rom_region() const
+{
+ return ROM_NAME( ax208 );
+}
+
+void ax208_cpu_device::device_reset()
+{
+ axc51base_cpu_device::device_reset();
+ set_state_int(AXC51_PC, 0x8000);
+
+ m_spiaddr = 0;
+}
+
+
+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)
+{
+}
+
+ROM_START( ax208p ) // this is an early revision of the internal AX208 code, some functions are moved around so it isn't entirely compatible
+ ROM_REGION( 0x2000, "rom", 0 )
+ ROM_LOAD("mask208.bin", 0x0000, 0x2000, CRC(52396183) SHA1(b119000f93251894a352ecf675ee42f2e5c347bd) )
+ROM_END
+
+const tiny_rom_entry *ax208p_cpu_device::device_rom_region() const
+{
+ return ROM_NAME( ax208p );
+}
+
+
diff --git a/src/devices/cpu/axc51/axc51.h b/src/devices/cpu/axc51/axc51.h
new file mode 100644
index 00000000000..7791d37a8e0
--- /dev/null
+++ b/src/devices/cpu/axc51/axc51.h
@@ -0,0 +1,479 @@
+// license:BSD-3-Clause
+// copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud
+
+#ifndef MAME_CPU_AXC51_AXC51_H
+#define MAME_CPU_AXC51_AXC51_H
+
+#pragma once
+
+
+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,
+};
+
+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 */
+};
+
+
+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 <unsigned N> auto port_in_cb() { return m_port_in_cb[N].bind(); }
+ template <unsigned N> auto port_out_cb() { return m_port_out_cb[N].bind(); }
+ auto serial_rx_cb() { return m_serial_rx_cb.bind(); }
+ auto serial_tx_cb() { return m_serial_tx_cb.bind(); }
+
+ void program_internal(address_map &map);
+ void data_internal(address_map &map);
+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);
+
+ // 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; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+protected:
+ address_space_config m_program_config;
+ address_space_config m_data_config;
+ address_space_config m_io_config;
+
+ //Internal stuff
+ uint16_t m_ppc; //previous pc
+ uint16_t m_pc; //current pc
+ uint16_t m_features; //features of this cpu
+ uint8_t m_rwm; //Signals that the current instruction is a read/write/modify instruction
+
+ int m_inst_cycles; /* cycles for the current instruction */
+ const uint32_t m_rom_size; /* size (in bytes) of internal program ROM/EPROM */
+ int m_ram_mask; /* second ram bank for indirect access available ? */
+ int m_num_interrupts; /* number of interrupts supported */
+ int m_recalc_parity; /* recalculate parity before next instruction */
+ uint32_t m_last_line_state; /* last state of input lines line */
+ int m_t0_cnt; /* number of 0->1 transitions on T0 line */
+ int m_t1_cnt; /* number of 0->1 transitions on T1 line */
+ int m_t2_cnt; /* number of 0->1 transitions on T2 line */
+ int m_t2ex_cnt; /* number of 0->1 transitions on T2EX line */
+ int m_cur_irq_prio; /* Holds value of the current IRQ Priority Level; -1 if no irq */
+ uint8_t m_irq_active; /* mask which irq levels are serviced */
+ uint8_t m_irq_prio[8]; /* interrupt priority */
+
+ uint8_t m_forced_inputs[4]; /* allow read even if configured as output */
+
+ // JB-related hacks
+ uint8_t m_last_op;
+ uint8_t m_last_bit;
+
+ 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<uint8_t> m_sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
+ required_shared_ptr<uint8_t> m_scratchpad; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */
+
+ /* SFR Callbacks */
+ virtual void sfr_write(size_t offset, uint8_t data);
+ virtual uint8_t sfr_read(size_t offset);
+
+ /* Memory spaces */
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program;
+ memory_access< 9, 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;
+
+ /* 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);
+ 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);
+ uint8_t iram_read(size_t offset);
+ void iram_write(size_t offset, uint8_t data);
+ void push_pc();
+ void pop_pc();
+ void set_parity();
+ uint8_t bit_address_r(uint8_t offset);
+ 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);
+ void acall(uint8_t r);
+ void add_a_byte(uint8_t r);
+ void add_a_mem(uint8_t r);
+ void add_a_ir(uint8_t r);
+ void add_a_r(uint8_t r);
+ void addc_a_byte(uint8_t r);
+ void addc_a_mem(uint8_t r);
+ void addc_a_ir(uint8_t r);
+ void addc_a_r(uint8_t r);
+ void ajmp(uint8_t r);
+ void anl_mem_a(uint8_t r);
+ void anl_mem_byte(uint8_t r);
+ void anl_a_byte(uint8_t r);
+ void anl_a_mem(uint8_t r);
+ void anl_a_ir(uint8_t r);
+ void anl_a_r(uint8_t r);
+ void anl_c_bitaddr(uint8_t r);
+ void anl_c_nbitaddr(uint8_t r);
+ void cjne_a_byte(uint8_t r);
+ void cjne_a_mem(uint8_t r);
+ void cjne_ir_byte(uint8_t r);
+ void cjne_r_byte(uint8_t r);
+ void clr_bitaddr(uint8_t r);
+ void clr_c(uint8_t r);
+ void clr_a(uint8_t r);
+ void cpl_bitaddr(uint8_t r);
+ void cpl_c(uint8_t r);
+ void cpl_a(uint8_t r);
+ void da_a(uint8_t r);
+ void dec_a(uint8_t r);
+ void dec_mem(uint8_t r);
+ void dec_ir(uint8_t r);
+ void dec_r(uint8_t r);
+ void div_ab(uint8_t r);
+ void djnz_mem(uint8_t r);
+ void djnz_r(uint8_t r);
+ void inc_a(uint8_t r);
+ void inc_mem(uint8_t r);
+ void inc_ir(uint8_t r);
+ void inc_r(uint8_t r);
+ void inc_dptr(uint8_t r);
+ void jb(uint8_t r);
+ void jbc(uint8_t r);
+ void jc(uint8_t r);
+ void jmp_iadptr(uint8_t r);
+ void jnb(uint8_t r);
+ void jnc(uint8_t r);
+ void jnz(uint8_t r);
+ void jz(uint8_t r);
+ void lcall(uint8_t r);
+ void ljmp(uint8_t r);
+ void mov_a_byte(uint8_t r);
+ void mov_a_mem(uint8_t r);
+ void mov_a_ir(uint8_t r);
+ void mov_a_r(uint8_t r);
+ void mov_mem_byte(uint8_t r);
+ void mov_mem_mem(uint8_t r);
+ void mov_ir_byte(uint8_t r);
+ void mov_r_byte(uint8_t r);
+ void mov_mem_ir(uint8_t r);
+ void mov_mem_r(uint8_t r);
+ void mov_dptr_byte(uint8_t r);
+ void mov_bitaddr_c(uint8_t r);
+ void mov_ir_mem(uint8_t r);
+ void mov_r_mem(uint8_t r);
+ void mov_mem_a(uint8_t r);
+ void mov_ir_a(uint8_t r);
+ void mov_r_a(uint8_t r);
+ void movc_a_iapc(uint8_t r);
+ void mov_c_bitaddr(uint8_t r);
+ void movc_a_iadptr(uint8_t r);
+ void movx_a_idptr(uint8_t r);
+ void movx_a_ir(uint8_t r);
+ void movx_idptr_a(uint8_t r);
+ void movx_ir_a(uint8_t r);
+ void mul_ab(uint8_t r);
+ void nop(uint8_t r);
+ void orl_mem_a(uint8_t r);
+ void orl_mem_byte(uint8_t r);
+ void orl_a_byte(uint8_t r);
+ void orl_a_mem(uint8_t r);
+ void orl_a_ir(uint8_t r);
+ void orl_a_r(uint8_t r);
+ void orl_c_bitaddr(uint8_t r);
+ void orl_c_nbitaddr(uint8_t r);
+ void pop(uint8_t r);
+ void push(uint8_t r);
+ void ret(uint8_t r);
+ void reti(uint8_t r);
+ void rl_a(uint8_t r);
+ void rlc_a(uint8_t r);
+ void rr_a(uint8_t r);
+ void rrc_a(uint8_t r);
+ void setb_c(uint8_t r);
+ void setb_bitaddr(uint8_t r);
+ void sjmp(uint8_t r);
+ void subb_a_byte(uint8_t r);
+ void subb_a_mem(uint8_t r);
+ void subb_a_ir(uint8_t r);
+ void subb_a_r(uint8_t r);
+ void swap_a(uint8_t r);
+ void xch_a_mem(uint8_t r);
+ void xch_a_ir(uint8_t r);
+ void xch_a_r(uint8_t r);
+ void xchd_a_ir(uint8_t r);
+ void xrl_mem_a(uint8_t r);
+ void xrl_mem_byte(uint8_t r);
+ void xrl_a_byte(uint8_t r);
+ void xrl_a_mem(uint8_t r);
+ void xrl_a_ir(uint8_t r);
+ void xrl_a_r(uint8_t r);
+ void illegal(uint8_t r);
+
+
+ /* Internal address in SFR of registers */
+ 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,
+ };
+
+ enum
+ {
+ V_RESET = 0x000, /* power on address */
+ V_IE0 = 0x003, /* External Interrupt 0 */
+ };
+
+};
+
+
+
+DECLARE_DEVICE_TYPE(AX208, ax208_cpu_device)
+DECLARE_DEVICE_TYPE(AX208P, ax208p_cpu_device)
+
+class ax208_cpu_device : public axc51base_cpu_device
+{
+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);
+
+ virtual void device_reset() override;
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+ 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
+{
+public:
+ // construction/destruction
+ ax208p_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+
+#endif // MAME_CPU_AXC51_AXC51_H
diff --git a/src/devices/cpu/mcs51/axc51-core_dasm.cpp b/src/devices/cpu/axc51/axc51dasm.cpp
index be500543505..c30166f7a2a 100644
--- a/src/devices/cpu/mcs51/axc51-core_dasm.cpp
+++ b/src/devices/cpu/axc51/axc51dasm.cpp
@@ -1,17 +1,1015 @@
// license:BSD-3-Clause
-// copyright-holders:David Haywood
-/*****************************************************************************
+// copyright-holders:Steve Ellenoff
- AXC51-CORE (AppoTech Inc.)
+#include "emu.h"
+#include "axc51dasm.h"
+
+// Note: addresses >= 0x100 are bit addresses
+
+const axc51_disassembler::mem_info axc51_disassembler::default_names[] = {
+ { 0x00, "rb0r0" },
+ { 0x01, "rb0r1" },
+ { 0x02, "rb0r2" },
+ { 0x03, "rb0r3" },
+ { 0x04, "rb0r4" },
+ { 0x05, "rb0r5" },
+ { 0x06, "rb0r6" },
+ { 0x07, "rb0r7" },
+ { 0x08, "rb1r0" },
+ { 0x09, "rb1r1" },
+ { 0x0a, "rb1r2" },
+ { 0x0b, "rb1r3" },
+ { 0x0c, "rb1r4" },
+ { 0x0d, "rb1r5" },
+ { 0x0e, "rb1r6" },
+ { 0x0f, "rb1r7" },
+ { 0x10, "rb2r0" },
+ { 0x11, "rb2r1" },
+ { 0x12, "rb2r2" },
+ { 0x13, "rb2r3" },
+ { 0x14, "rb2r4" },
+ { 0x15, "rb2r5" },
+ { 0x16, "rb2r6" },
+ { 0x17, "rb2r7" },
+ { 0x18, "rb3r0" },
+ { 0x19, "rb3r1" },
+ { 0x1a, "rb3r2" },
+ { 0x1b, "rb3r3" },
+ { 0x1c, "rb3r4" },
+ { 0x1d, "rb3r5" },
+ { 0x1e, "rb3r6" },
+ { 0x1f, "rb3r7" },
+
+ { 0x80, "p0" },
+ { 0x81, "sp" },
+ { 0x82, "dpl" },
+ { 0x83, "dph" },
+ { 0x87, "pcon" },
+ { 0x88, "tcon" },
+ { 0x89, "tmod" },
+ { 0x8a, "tl0" },
+ { 0x8b, "tl1" },
+ { 0x8c, "th0" },
+ { 0x8d, "th1" },
+ { 0x90, "p1" },
+ { 0x98, "scon" },
+ { 0x99, "sbuf" },
+ { 0xa0, "p2" },
+ { 0xa8, "ie" },
+ { 0xb0, "p3" },
+ { 0xb8, "ip" },
+ { 0xd0, "psw" },
+ { 0xe0, "acc" },
+ { 0xf0, "b" },
+
+ { 0x188, "it0" },
+ { 0x189, "ie0" },
+ { 0x18a, "it1" },
+ { 0x18b, "ie1" },
+ { 0x18c, "tr0" },
+ { 0x18d, "tf0" },
+ { 0x18e, "tr1" },
+ { 0x18f, "tf1" },
+
+ { 0x198, "ri" },
+ { 0x199, "ti" },
+ { 0x19a, "rb8" },
+ { 0x19b, "tb8" },
+ { 0x19c, "ren" },
+ { 0x19d, "sm2" },
+ { 0x19e, "sm1" },
+ { 0x19f, "sm0" },
+
+ { 0x1a8, "ex0" },
+ { 0x1a9, "et0" },
+ { 0x1aa, "ex1" },
+ { 0x1ab, "et1" },
+ { 0x1ac, "es" },
+ { 0x1ad, "ie.5" },
+ { 0x1ae, "ie.6" },
+ { 0x1af, "ea" },
+
+ /* FIXME: port 3 - depends on external circuits and not really
+ * implemented in the core. TBD */
+ { 0x1b0, "rxd" },
+ { 0x1b1, "txd" },
+ { 0x1b2, "int0" },
+ { 0x1b3, "int1" },
+ { 0x1b4, "t0" },
+ { 0x1b5, "t1" },
+ { 0x1b6, "wr" },
+ { 0x1b7, "rd" },
+
+ { 0x1b8, "px0" },
+ { 0x1b9, "pt0" },
+ { 0x1ba, "px1" },
+ { 0x1bb, "pt1" },
+ { 0x1bc, "ps" },
+ { 0x1bd, "ip.5" },
+ { 0x1be, "ip.6" },
+ { 0x1bf, "ip.7" },
+
+ { 0x1d0, "p" },
+ { 0x1d1, "psw.1" },
+ { 0x1d2, "ov" },
+ { 0x1d3, "rs0" },
+ { 0x1d4, "rs1" },
+ { 0x1d5, "f0" },
+ { 0x1d6, "ac" },
+ { 0x1d7, "cy" },
+
+ { -1 }
+};
+
+axc51_disassembler::axc51_disassembler()
+{
+}
- used in
+void axc51_disassembler::add_names(const mem_info *info)
+{
+ for(unsigned int i=0; info[i].addr >= 0; i++)
+ m_names[info[i].addr] = info[i].name;
+}
- AX208 SoC
+u32 axc51_disassembler::opcode_alignment() const
+{
+ return 1;
+}
- *****************************************************************************/
-#include "emu.h"
-#include "axc51-core_dasm.h"
+std::string axc51_disassembler::get_data_address( uint8_t arg ) const
+{
+ auto i = m_names.find(arg);
+ if (i == m_names.end())
+ return util::string_format("$%02X", arg);
+ else
+ return i->second;
+}
+
+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
+ return util::string_format("$%02X.%d", (arg >> 3) | 0x20, arg & 0x07);
+ }
+ else
+ {
+ auto i = m_names.find(arg | 0x100);
+ if (i == m_names.end())
+ {
+ i = m_names.find(arg & 0xf8);
+ if (i == m_names.end())
+ return util::string_format("$%02X.%d", arg & 0xf8, arg & 0x07);
+ else
+ return util::string_format("%s.%d", i->second, arg & 0x07);
+ }
+ else
+ return i->second;
+ }
+}
+
+void axc51_disassembler::disassemble_op_ljmp(std::ostream& stream, unsigned &PC, const data_buffer& params)
+{
+ uint16_t addr = (params.r8(PC++)<<8) & 0xff00;
+ addr|= params.r8(PC++);
+ util::stream_format(stream, "ljmp $%04X", addr);
+}
+
+void axc51_disassembler::disassemble_op_lcall(std::ostream& stream, unsigned &PC, const data_buffer& params)
+{
+ uint16_t addr = (params.r8(PC++)<<8) & 0xff00;
+ addr|= params.r8(PC++);
+ util::stream_format(stream, "lcall $%04X", addr);
+}
+
+offs_t axc51_disassembler::disassemble_op(std::ostream &stream, unsigned PC, offs_t pc, const data_buffer &opcodes, const data_buffer &params, uint8_t op)
+{
+ uint32_t flags = 0;
+ std::string sym, sym2;
+ uint8_t data;
+ uint16_t addr;
+ int8_t rel;
+
+ switch( op )
+ {
+ //NOP
+ case 0x00: /* 1: 0000 0000 */
+ util::stream_format(stream, "nop");
+ break;
+
+ //AJMP code addr /* 1: aaa0 0001 */
+ case 0x01:
+ case 0x21:
+ case 0x41:
+ case 0x61:
+ case 0x81:
+ case 0xa1:
+ case 0xc1:
+ case 0xe1:
+ addr = params.r8(PC++);
+ addr|= (PC & 0xf800) | ((op & 0xe0) << 3);
+ util::stream_format(stream, "ajmp $%04X", addr);
+ break;
+
+ //LJMP code addr
+ case 0x02: /* 1: 0000 0010 */
+ disassemble_op_ljmp(stream, PC, params);
+ break;
+
+ //RR A
+ case 0x03: /* 1: 0000 0011 */
+ util::stream_format(stream, "rr a");
+ break;
+
+ //INC A
+ case 0x04: /* 1: 0000 0100 */
+ util::stream_format(stream, "inc a");
+ break;
+
+ //INC data addr
+ case 0x05: /* 1: 0000 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "inc %s", sym);
+ break;
+
+ //INC @R0/@R1 /* 1: 0000 011i */
+ case 0x06:
+ case 0x07:
+ util::stream_format(stream, "inc @r%d", op&1);
+ break;
+
+ //INC R0 to R7 /* 1: 0000 1rrr */
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ util::stream_format(stream, "inc r%d", op&7);
+ break;
+
+ //JBC bit addr, code addr
+ case 0x10: /* 1: 0001 0000 */
+ sym = get_bit_address(params.r8(PC++));
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jbc %s,$%04X", sym, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //ACALL code addr /* 1: aaa1 0001 */
+ case 0x11:
+ case 0x31:
+ case 0x51:
+ case 0x71:
+ case 0x91:
+ case 0xb1:
+ case 0xd1:
+ case 0xf1:
+ util::stream_format(stream, "acall $%04X", (PC & 0xf800) | ((op & 0xe0) << 3) | params.r8(PC));
+ PC++;
+ flags = STEP_OVER;
+ break;
+
+ //LCALL code addr
+ case 0x12: /* 1: 0001 0010 */
+ disassemble_op_lcall(stream, PC, params);
+ flags = STEP_OVER;
+ break;
+
+ //RRC A
+ case 0x13: /* 1: 0001 0011 */
+ util::stream_format(stream, "rrc a");
+ break;
+
+ //DEC A
+ case 0x14: /* 1: 0001 0100 */
+ util::stream_format(stream, "dec a");
+ break;
+
+ //DEC data addr
+ case 0x15: /* 1: 0001 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "dec %s", sym);
+ break;
+
+ //Unable to test
+ //DEC @R0/@R1 /* 1: 0001 011i */
+ case 0x16:
+ case 0x17:
+ util::stream_format(stream, "dec @r%d", op&1);
+ break;
+
+ //DEC R0 to R7 /* 1: 0001 1rrr */
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ util::stream_format(stream, "dec r%d", op&7);
+ break;
+
+ //JB bit addr, code addr
+ case 0x20: /* 1: 0010 0000 */
+ sym = get_bit_address(params.r8(PC++));
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jb %s,$%04X", sym, (PC + rel));
+ flags = STEP_COND;
+ break;
+
+ //RET
+ case 0x22: /* 1: 0010 0010 */
+ util::stream_format(stream, "ret");
+ flags = STEP_OUT;
+ break;
+
+ //RL A
+ case 0x23: /* 1: 0010 0011 */
+ util::stream_format(stream, "rl a");
+ break;
+
+ //ADD A, #data
+ case 0x24: /* 1: 0010 0100 */
+ util::stream_format(stream, "add a,#$%02X", params.r8(PC++));
+ break;
+
+ //ADD A, data addr
+ case 0x25: /* 1: 0010 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "add a,%s", sym);
+ break;
+
+ //Unable to Test
+ //ADD A, @R0/@R1 /* 1: 0010 011i */
+ case 0x26:
+ case 0x27:
+ util::stream_format(stream, "add a,@r%d", op&1);
+ break;
+
+ //ADD A, R0 to R7 /* 1: 0010 1rrr */
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ util::stream_format(stream, "add a,r%d", op&7);
+ break;
+
+ //JNB bit addr, code addr
+ case 0x30: /* 1: 0011 0000 */
+ sym = get_bit_address(params.r8(PC++));
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jnb %s,$%04X", sym, (PC + rel));
+ flags = STEP_COND;
+ break;
+
+ //RETI
+ case 0x32: /* 1: 0011 0010 */
+ util::stream_format(stream, "reti");
+ flags = STEP_OUT;
+ break;
+
+ //RLC A
+ case 0x33: /* 1: 0011 0011 */
+ util::stream_format(stream, "rlc a");
+ break;
+
+ //ADDC A, #data
+ case 0x34: /* 1: 0011 0100 */
+ util::stream_format(stream, "addc a,#$%02X", params.r8(PC++));
+ break;
+
+ //ADDC A, data addr
+ case 0x35: /* 1: 0011 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "addc a,%s", sym);
+ break;
+
+ //ADDC A, @R0/@R1 /* 1: 0011 011i */
+ case 0x36:
+ case 0x37:
+ util::stream_format(stream, "addc a,@r%d", op&1);
+ break;
+
+ //ADDC A, R0 to R7 /* 1: 0011 1rrr */
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f:
+ util::stream_format(stream, "addc a,r%d", op&7);
+ break;
+
+ //JC code addr
+ case 0x40: /* 1: 0100 0000 */
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jc $%04X", PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //ORL data addr, A
+ case 0x42: /* 1: 0100 0010 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "orl %s,a", sym);
+ break;
+
+ //ORL data addr, #data
+ case 0x43: /* 1: 0100 0011 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "orl %s,#$%02X", sym, params.r8(PC++));
+ break;
+
+ //Unable to Test
+ //ORL A, #data
+ case 0x44: /* 1: 0100 0100 */
+ util::stream_format(stream, "orl a,#$%02X", params.r8(PC++));
+ break;
+
+ //ORL A, data addr
+ case 0x45: /* 1: 0100 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "orl a,%s", sym);
+ break;
+
+ //ORL A, @RO/@R1 /* 1: 0100 011i */
+ case 0x46:
+ case 0x47:
+ util::stream_format(stream, "orl a,@r%d", op&1);
+ break;
+
+ //ORL A, RO to R7 /* 1: 0100 1rrr */
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ util::stream_format(stream, "orl a,r%d", op&7);
+ break;
+
+ //JNC code addr
+ case 0x50: /* 1: 0101 0000 */
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jnc $%04X", PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //Unable to test
+ //ANL data addr, A
+ case 0x52: /* 1: 0101 0010 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "anl %s,a", sym);
+ break;
+
+ //Unable to test
+ //ANL data addr, #data
+ case 0x53: /* 1: 0101 0011 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "anl %s,#$%02X", sym, params.r8(PC++));
+ break;
+
+ //ANL A, #data
+ case 0x54: /* 1: 0101 0100 */
+ util::stream_format(stream, "anl a,#$%02X", params.r8(PC++));
+ break;
+
+ //ANL A, data addr
+ case 0x55: /* 1: 0101 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "anl a,%s", sym);
+ break;
+
+ //Unable to test
+ //ANL A, @RO/@R1 /* 1: 0101 011i */
+ case 0x56:
+ case 0x57:
+ util::stream_format(stream, "anl a,@r%d", op&1);
+ break;
+
+ //ANL A, RO to R7 /* 1: 0101 1rrr */
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ util::stream_format(stream, "anl a,r%d", op&7);
+ break;
+
+ //JZ code addr
+ case 0x60: /* 1: 0110 0000 */
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jz $%04X", PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //Unable to test
+ //XRL data addr, A
+ case 0x62: /* 1: 0110 0010 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "xrl %s,a", sym);
+ break;
+
+ //XRL data addr, #data
+ case 0x63: /* 1: 0110 0011 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "xrl %s,#$%02X", sym, params.r8(PC++));
+ break;
+
+ //XRL A, #data
+ case 0x64: /* 1: 0110 0100 */
+ util::stream_format(stream, "xrl a,#$%02X", params.r8(PC++));
+ break;
+
+ //XRL A, data addr
+ case 0x65: /* 1: 0110 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "xrl a,%s", sym);
+ break;
+
+ //Unable to test
+ //XRL A, @R0/@R1 /* 1: 0110 011i */
+ case 0x66:
+ case 0x67:
+ util::stream_format(stream, "xrl a,@r%d", op&1);
+ break;
+
+ //XRL A, R0 to R7 /* 1: 0110 1rrr */
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f:
+ util::stream_format(stream, "xrl a,r%d", op&7);
+ break;
+
+ //JNZ code addr
+ case 0x70: /* 1: 0111 0000 */
+ rel = params.r8(PC++);
+ util::stream_format(stream, "jnz $%04X", PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //Unable to test
+ //ORL C, bit addr
+ case 0x72: /* 1: 0111 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "orl c,%s", sym);
+ break;
+
+ //Unable to test
+ //JMP @A+DPTR
+ case 0x73: /* 1: 0111 0011 */
+ util::stream_format(stream, "jmp @a+dptr");
+ break;
+
+ //MOV A, #data
+ case 0x74: /* 1: 0111 0100 */
+ util::stream_format(stream, "mov a,#$%02X", params.r8(PC++));
+ break;
+
+ //MOV data addr, #data
+ case 0x75: /* 1: 0111 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,#$%02X", sym, params.r8(PC++));
+ break;
+
+ //Unable to test
+ //MOV @R0/@R1, #data /* 1: 0111 011i */
+ case 0x76:
+ case 0x77:
+ util::stream_format(stream, "mov @r%d,#$%02X", op&1, params.r8(PC++));
+ break;
+
+ //MOV R0 to R7, #data /* 1: 0111 1rrr */
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f:
+ util::stream_format(stream, "mov r%d,#$%02X", (op & 7), params.r8(PC++));
+ break;
+
+ //SJMP code addr
+ case 0x80: /* 1: 1000 0000 */
+ rel = params.r8(PC++);
+ util::stream_format(stream, "sjmp $%04X", PC + rel);
+ break;
+
+ //ANL C, bit addr
+ case 0x82: /* 1: 1000 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "anl c,%s", sym);
+ break;
+
+ //MOVC A, @A + PC
+ case 0x83: /* 1: 1000 0011 */
+ util::stream_format(stream, "movc a,@a+pc");
+ break;
+
+ //DIV AB
+ case 0x84: /* 1: 1000 0100 */
+ util::stream_format(stream, "div ab");
+ break;
+
+ //MOV data addr, data addr (Note: 1st address is src, 2nd is dst, but the mov command works as mov dst,src)
+ case 0x85: /* 1: 1000 0101 */
+ sym = get_data_address(params.r8(PC++));
+ sym2 = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,%s", sym2, sym);
+ break;
+
+ //Unable to test
+ //MOV data addr, @R0/@R1/* 1: 1000 011i */
+ case 0x86:
+ case 0x87:
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,@r%d", sym, op&1);
+ break;
+
+ //MOV data addr,R0 to R7/* 1: 1000 1rrr */
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f:
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,r%d", sym, op&7);
+ break;
+
+ //MOV DPTR, #data16
+ case 0x90: /* 1: 1001 0000 */
+ addr = (params.r8(PC++)<<8) & 0xff00;
+ addr|= params.r8(PC++);
+ util::stream_format(stream, "mov dptr,#$%04X", addr);
+ break;
+
+ //MOV bit addr, C
+ case 0x92: /* 1: 1001 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,c", sym);
+ break;
+
+ //MOVC A, @A + DPTR
+ case 0x93: /* 1: 1001 0011 */
+ util::stream_format(stream, "movc a,@a+dptr");
+ break;
+
+ //SUBB A, #data
+ case 0x94: /* 1: 1001 0100 */
+ util::stream_format(stream, "subb a,#$%02X", params.r8(PC++));
+ break;
+
+ //SUBB A, data addr
+ case 0x95: /* 1: 1001 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "subb a,%s", sym);
+ break;
+
+ //Unable to test
+ //SUBB A, @R0/@R1 /* 1: 1001 011i */
+ case 0x96:
+ case 0x97:
+ util::stream_format(stream, "subb a,@r%d", op&1);
+ break;
+
+ //SUBB A, R0 to R7 /* 1: 1001 1rrr */
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f:
+ util::stream_format(stream, "subb a,r%d", op&7);
+ break;
+
+ //Unable to test
+ //ORL C, /bit addr
+ case 0xa0: /* 1: 1010 0000 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "orl c,/%s", sym);
+ break;
+
+ //MOV C, bit addr
+ case 0xa2: /* 1: 1010 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "mov c,%s", sym);
+ break;
+
+ //INC DPTR
+ case 0xa3: /* 1: 1010 0011 */
+ util::stream_format(stream, "inc dptr");
+ break;
+
+ //MUL AB
+ case 0xa4: /* 1: 1010 0100 */
+ util::stream_format(stream, "mul ab");
+ break;
+
+ //reserved
+ case 0xa5: /* 1: 1010 0101 */
+ util::stream_format(stream, "ill/rsv");
+ break;
+
+ //Unable to test
+ //MOV @R0/@R1, data addr /* 1: 1010 011i */
+ case 0xa6:
+ case 0xa7:
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov @r%d,%s", op&1, sym);
+ break;
+
+ //MOV R0 to R7, data addr /* 1: 1010 1rrr */
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf:
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov r%d,%s", op&7, sym);
+ break;
+
+ //ANL C,/bit addr
+ case 0xb0: /* 1: 1011 0000 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "anl c,/%s", sym);
+ break;
+
+ //CPL bit addr
+ case 0xb2: /* 1: 1011 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "cpl %s", sym);
+ break;
+
+ //Unable to test
+ //CPL C
+ case 0xb3: /* 1: 1011 0011 */
+ util::stream_format(stream, "cpl c");
+ break;
+
+ //CJNE A, #data, code addr
+ case 0xb4: /* 1: 1011 0100 */
+ data = params.r8(PC++);
+ rel = params.r8(PC++);
+ util::stream_format(stream, "cjne a,#$%02X,$%04X", data, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //CJNE A, data addr, code addr
+ case 0xb5: /* 1: 1011 0101 */
+ sym = get_data_address(params.r8(PC++));
+ rel = params.r8(PC++);
+ util::stream_format(stream, "cjne a,%s,$%04X", sym, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //Unable to test
+ //CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
+ case 0xb6:
+ case 0xb7:
+ data = params.r8(PC++);
+ rel = params.r8(PC++);
+ util::stream_format(stream, "cjne @r%d,#$%02X,$%04X", op&1, data, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //CJNE R0 to R7, #data, code addr/* 1: 1011 1rrr */
+ case 0xb8:
+ case 0xb9:
+ case 0xba:
+ case 0xbb:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ case 0xbf:
+ data = params.r8(PC++);
+ rel = params.r8(PC++);
+ util::stream_format(stream, "cjne r%d,#$%02X,$%04X", op&7, data, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //PUSH data addr
+ case 0xc0: /* 1: 1100 0000 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "push %s", sym);
+ break;
+
+ //CLR bit addr
+ case 0xc2: /* 1: 1100 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "clr %s", sym);
+ break;
+
+ //CLR C
+ case 0xc3: /* 1: 1100 0011 */
+ util::stream_format(stream, "clr c");
+ break;
+
+ //SWAP A
+ case 0xc4: /* 1: 1100 0100 */
+ util::stream_format(stream, "swap a");
+ break;
+
+ //XCH A, data addr
+ case 0xc5: /* 1: 1100 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "xch a,%s", sym);
+ break;
+
+ //XCH A, @RO/@R1 /* 1: 1100 011i */
+ case 0xc6:
+ case 0xc7:
+ util::stream_format(stream, "xch a,@r%d", op&1);
+ break;
+
+ //XCH A, RO to R7 /* 1: 1100 1rrr */
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ util::stream_format(stream, "xch a,r%d", op&7);
+ break;
+
+ //POP data addr
+ case 0xd0: /* 1: 1101 0000 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "pop %s", sym);
+ break;
+
+ //SETB bit addr
+ case 0xd2: /* 1: 1101 0010 */
+ sym = get_bit_address(params.r8(PC++));
+ util::stream_format(stream, "setb %s", sym);
+ break;
+
+ //SETB C
+ case 0xd3: /* 1: 1101 0011 */
+ util::stream_format(stream, "setb c");
+ break;
+
+ //Unable to test
+ //DA A
+ case 0xd4: /* 1: 1101 0100 */
+ util::stream_format(stream, "da a");
+ break;
+
+ //DJNZ data addr, code addr
+ case 0xd5: /* 1: 1101 0101 */
+ sym = get_data_address(params.r8(PC++));
+ rel = params.r8(PC++);
+ util::stream_format(stream, "djnz %s,$%04X", sym, PC + rel);
+ flags = STEP_COND;
+ break;
+
+ //XCHD A, @R0/@R1 /* 1: 1101 011i */
+ case 0xd6:
+ case 0xd7:
+ util::stream_format(stream, "xchd a,@r%d", op&1);
+ break;
+
+ //DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf:
+ rel = params.r8(PC++);
+ util::stream_format(stream, "djnz r%d,$%04X", op&7, (PC + rel));
+ flags = STEP_COND;
+ break;
+
+ //MOVX A,@DPTR
+ case 0xe0: /* 1: 1110 0000 */
+ util::stream_format(stream, "movx a,@dptr");
+ break;
+
+ //Unable to test
+ //MOVX A, @R0/@R1 /* 1: 1110 001i */
+ case 0xe2:
+ case 0xe3:
+ util::stream_format(stream, "movx a,@r%d", op&1);
+ break;
+
+ //CLR A
+ case 0xe4: /* 1: 1110 0100 */
+ util::stream_format(stream, "clr a");
+ break;
+
+ //MOV A, data addr
+ case 0xe5: /* 1: 1110 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov a,%s", sym);
+ break;
+
+ //Unable to test
+ //MOV A,@RO/@R1 /* 1: 1110 011i */
+ case 0xe6:
+ case 0xe7:
+ util::stream_format(stream, "mov a,@r%d", op&1);
+ break;
+
+ //MOV A,R0 to R7 /* 1: 1110 1rrr */
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef:
+ util::stream_format(stream, "mov a,r%d", op&7);
+ break;
+
+ //MOVX @DPTR,A
+ case 0xf0: /* 1: 1111 0000 */
+ util::stream_format(stream, "movx @dptr,a");
+ break;
+
+ //Unable to test
+ //MOVX @R0/@R1,A /* 1: 1111 001i */
+ case 0xf2:
+ case 0xf3:
+ util::stream_format(stream, "movx @r%d,a", op&1);
+ break;
+
+ //CPL A
+ case 0xf4: /* 1: 1111 0100 */
+ util::stream_format(stream, "cpl a");
+ break;
+
+ //MOV data addr, A
+ case 0xf5: /* 1: 1111 0101 */
+ sym = get_data_address(params.r8(PC++));
+ util::stream_format(stream, "mov %s,a", sym);
+ break;
+
+ //MOV @R0/@R1, A /* 1: 1111 011i */
+ case 0xf6:
+ case 0xf7:
+ util::stream_format(stream, "mov @r%d,a", op&1);
+ break;
+
+ //MOV R0 to R7, A /* 1: 1111 1rrr */
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff:
+ util::stream_format(stream, "mov r%d,a", op&7);
+ break;
+
+ default:
+ util::stream_format(stream, "illegal");
+ }
+
+ return (PC - pc) | flags | SUPPORTED;
+}
+
+offs_t axc51_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ unsigned PC = pc;
+ uint8_t op = opcodes.r8(PC++);
+ return disassemble_op(stream, PC, pc, opcodes, params, op);
+}
// SOME of these might be AX208 specific, we do not currently hvae enough information to split it into AXC51 / AX208 however
const axc51core_disassembler::mem_info axc51core_disassembler::axc51core_names[] = {
@@ -342,7 +1340,7 @@ const ax208_disassembler::ax208_bios_info ax208_disassembler::bios_call_names[]
{ -1, "unknown" }
};
-axc51core_disassembler::axc51core_disassembler() : mcs51_disassembler(axc51core_names)
+axc51core_disassembler::axc51core_disassembler() : axc51_disassembler(axc51core_names)
{
}
/* Extended 16-bit Opcodes
@@ -971,7 +1969,7 @@ offs_t axc51core_disassembler::disassemble_op(std::ostream& stream, unsigned PC,
return disassemble_extended_a5(stream, PC, pc, opcodes, params);
default:
- return mcs51_disassembler::disassemble_op(stream, PC, pc, opcodes, params, op);
+ return axc51_disassembler::disassemble_op(stream, PC, pc, opcodes, params, op);
}
return (PC - pc) | flags | SUPPORTED;
@@ -1037,3 +2035,4 @@ void ax208_disassembler::disassemble_op_lcall(std::ostream& stream, unsigned &PC
util::stream_format(stream, "lcall $%04X", addr);
}
}
+
diff --git a/src/devices/cpu/mcs51/axc51-core_dasm.h b/src/devices/cpu/axc51/axc51dasm.h
index 575e3f8270e..95521f6e9f1 100644
--- a/src/devices/cpu/mcs51/axc51-core_dasm.h
+++ b/src/devices/cpu/axc51/axc51dasm.h
@@ -1,28 +1,60 @@
// license:BSD-3-Clause
-// copyright-holders:David Haywood
-/*****************************************************************************
+// copyright-holders:Steve Ellenoff
- AXC51-CORE (AppoTech Inc.)
+#ifndef MAME_CPU_AXC51_AXC51DASM_H
+#define MAME_CPU_AXC51_AXC51DASM_H
- used in
+#pragma once
- AX208 SoC
+#include <unordered_map>
- *****************************************************************************/
-#ifndef MAME_CPU_MCS51_AXC51_CORE_DASM_H
-#define MAME_CPU_MCS51_AXC51_CORE_DASM_H
+class axc51_disassembler : public util::disasm_interface
+{
+public:
+ struct mem_info {
+ int addr;
+ const char *name;
+ };
-#pragma once
+ static const mem_info default_names[];
+
+ template<typename ...Names> axc51_disassembler(Names &&... names) : axc51_disassembler() {
+ add_names(names...);
+ }
+
+ axc51_disassembler();
+ virtual ~axc51_disassembler() = default;
-#include "mcs51dasm.h"
+ template<typename ...Names> void add_names(const mem_info *info, Names &&... names)
+ {
+ add_names(names...);
+ add_names(info);
+ }
-class axc51core_disassembler : public mcs51_disassembler
+ void add_names(const mem_info *info);
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+protected:
+ virtual void disassemble_op_ljmp(std::ostream& stream, unsigned& PC, const data_buffer& params);
+ virtual void disassemble_op_lcall(std::ostream& stream, unsigned& PC, const data_buffer& params);
+ virtual offs_t disassemble_op(std::ostream &stream, unsigned PC, offs_t pc, const data_buffer &opcodes, const data_buffer &params, uint8_t op);
+
+ std::string get_data_address( uint8_t arg ) const;
+ std::string get_bit_address( uint8_t arg ) const;
+private:
+ std::unordered_map<offs_t, const char *> m_names;
+
+};
+
+class axc51core_disassembler : public axc51_disassembler
{
public:
axc51core_disassembler();
- axc51core_disassembler(const mem_info* names) : mcs51_disassembler(names) {}
+ axc51core_disassembler(const mem_info* names) : axc51_disassembler(names) {}
virtual ~axc51core_disassembler() = default;
@@ -59,5 +91,4 @@ protected:
};
-
-#endif // MAME_CPU_MCS51_AXC51_CORE_DASM_H
+#endif
diff --git a/src/devices/cpu/axc51/axc51ops.hxx b/src/devices/cpu/axc51/axc51ops.hxx
new file mode 100644
index 00000000000..99917328232
--- /dev/null
+++ b/src/devices/cpu/axc51/axc51ops.hxx
@@ -0,0 +1,982 @@
+// license:BSD-3-Clause
+// copyright-holders:Steve Ellenoff
+/*******************************************************************************************
+ 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
+********************************************************************************************/
+
+//ACALL code addr /* 1: aaa1 0001 */
+OPHANDLER( acall )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab code address byte
+ PUSH_PC(); //Save PC to the stack
+ //Thanks Gerrit for help with this! :)
+ PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
+}
+
+//ADD A, #data /* 1: 0010 0100 */
+OPHANDLER( add_a_byte )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ uint8_t result = ACC + data; //Add data to accumulator
+ 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 )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(addr); //Grab data from data address
+ uint8_t result = ACC + data; //Add data to accumulator
+ 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 )
+{
+ uint8_t data = IRAM_IR(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADD A, R0 to R7 /* 1: 0010 1rrr */
+OPHANDLER( add_a_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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, #data /* 1: 0011 0100 */
+OPHANDLER( addc_a_byte )
+{
+ uint8_t data = ROP_ARG(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, data addr /* 1: 0011 0101 */
+OPHANDLER( addc_a_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, @R0/@R1 /* 1: 0011 011i */
+OPHANDLER( addc_a_ir )
+{
+ uint8_t data = IRAM_IR(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, R0 to R7 /* 1: 0011 1rrr */
+OPHANDLER( addc_a_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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//AJMP code addr /* 1: aaa0 0001 */
+OPHANDLER( ajmp )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab code address byte
+ //Thanks Gerrit for help with this! :)
+ PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
+}
+
+//ANL data addr, A /* 1: 0101 0010 */
+OPHANDLER( anl_mem_a )
+{
+ 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
+}
+
+//ANL data addr, #data /* 1: 0101 0011 */
+OPHANDLER( anl_mem_byte )
+{
+ 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
+}
+
+//ANL A, #data /* 1: 0101 0100 */
+OPHANDLER( anl_a_byte )
+{
+ uint8_t data = ROP_ARG(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 )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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 )
+{
+ uint8_t data = IRAM_IR(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 )
+{
+ 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 )
+{
+ 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
+ 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 )
+{
+ 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
+ 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 )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+
+ if(ACC != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (ACC < data) );
+}
+
+//CJNE A, data addr, code addr /* 1: 1011 0101 */
+OPHANDLER( cjne_a_mem )
+{
+ 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
+
+ if(ACC != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (ACC < data) );
+}
+
+//CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
+OPHANDLER( cjne_ir_byte )
+{
+ 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
+
+ if(srcdata != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (srcdata < data) );
+}
+
+//CJNE R0 to R7, #data, code addr /* 1: 1011 1rrr */
+OPHANDLER( cjne_r_byte )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ int8_t rel_addr = ROP_ARG(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;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (srcdata < data) );
+}
+
+//CLR bit addr /* 1: 1100 0010 */
+OPHANDLER( clr_bitaddr )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,0); //Clear bit at specified bit address
+}
+
+//CLR C /* 1: 1100 0011 */
+OPHANDLER( clr_c )
+{
+ SET_CY(0); //Clear Carry Flag
+}
+
+//CLR A /* 1: 1110 0100 */
+OPHANDLER( clr_a )
+{
+ SET_ACC(0); //Clear Accumulator
+}
+
+//CPL bit addr /* 1: 1011 0010 */
+OPHANDLER( cpl_bitaddr )
+{
+ 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
+}
+
+//CPL C /* 1: 1011 0011 */
+OPHANDLER( cpl_c )
+{
+ uint8_t bit = (~GET_CY)&1; //Complement Carry Flag
+ SET_CY(bit);
+}
+
+//CPL A /* 1: 1111 0100 */
+OPHANDLER( cpl_a )
+{
+ uint8_t data = ((~ACC)&0xff);
+ SET_ACC(data); //Complement Accumulator
+}
+
+//DA A /* 1: 1101 0100 */
+OPHANDLER( da_a )
+{
+/*From several sources, since none said the same thing:
+ The decimal adjust instruction is associated with the use of the ADD and ADDC instructions.
+ The eight-bit value in the accumulator is adjusted to form two BCD digits of four bits each.
+ If the accumulator contents bits 0-3 are greater than 9, OR the AC flag is set, then six is added to
+ produce a proper BCD digit.
+ If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits.
+ The carry flag will be set if the result is > 0x99, but not cleared otherwise */
+
+ uint16_t new_acc = ACC & 0xff;
+ if(GET_AC || (new_acc & 0x0f) > 0x09)
+ new_acc += 0x06;
+ if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff))
+ new_acc += 0x60;
+ SET_ACC(new_acc&0xff);
+ if(new_acc & ~0xff)
+ SET_CY(1);
+}
+
+//DEC A /* 1: 0001 0100 */
+OPHANDLER( dec_a )
+{
+ SET_ACC(ACC-1);
+}
+
+//DEC data addr /* 1: 0001 0101 */
+OPHANDLER( dec_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(addr);
+ IRAM_W(addr,data-1);
+}
+
+//DEC @R0/@R1 /* 1: 0001 011i */
+OPHANDLER( dec_ir )
+{
+ uint8_t data = IRAM_IR(R_REG(r));
+ IRAM_IW(R_REG(r),data-1);
+}
+
+//DEC R0 to R7 /* 1: 0001 1rrr */
+OPHANDLER( dec_r )
+{
+ SET_REG(r, R_REG(r) - 1);
+}
+
+//DIV AB /* 1: 1000 0100 */
+OPHANDLER( div_ab )
+{
+ if( B == 0 ) {
+ //Overflow flag is set!
+ SET_OV(1);
+ //Really the values are undefined according to the manual, but we'll just leave them as is..
+ //SET_ACC(0xff);
+ //SFR_W(B,0xff);
+ }
+ else {
+ int a = (int)ACC / B;
+ int b = (int)ACC % B;
+ //A gets quotient byte, B gets remainder byte
+ SET_ACC(a);
+ B = b;
+ //Overflow flag is cleared
+ SET_OV(0);
+ }
+ //Carry Flag is always cleared
+ SET_CY(0);
+}
+
+//DJNZ data addr, code addr /* 1: 1101 0101 */
+OPHANDLER( djnz_mem )
+{
+ 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
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
+OPHANDLER( djnz_r )
+{
+ int8_t rel_addr = ROP_ARG(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;
+ }
+}
+
+//INC A /* 1: 0000 0100 */
+OPHANDLER( inc_a )
+{
+ SET_ACC(ACC+1);
+}
+
+//INC data addr /* 1: 0000 0101 */
+OPHANDLER( inc_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(addr);
+ IRAM_W(addr,data+1);
+}
+
+//INC @R0/@R1 /* 1: 0000 011i */
+OPHANDLER( inc_ir )
+{
+ uint8_t data = IRAM_IR(R_REG(r));
+ IRAM_IW(R_REG(r),data+1);
+}
+
+//INC R0 to R7 /* 1: 0000 1rrr */
+OPHANDLER( inc_r )
+{
+ uint8_t data = R_REG(r);
+ SET_REG(r, data + 1);
+}
+
+//INC DPTR /* 1: 1010 0011 */
+OPHANDLER( inc_dptr )
+{
+ uint16_t dptr = (DPTR)+1;
+ SET_DPTR(dptr);
+}
+
+//JB bit addr, code addr /* 1: 0010 0000 */
+OPHANDLER( jb )
+{
+ 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;
+ }
+}
+
+//JBC bit addr, code addr /* 1: 0001 0000 */
+OPHANDLER( jbc )
+{
+ 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
+ }
+}
+
+//JC code addr /* 1: 0100 0000 */
+OPHANDLER( jc )
+{
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(GET_CY) //Jump if Carry Flag Set
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JMP @A+DPTR /* 1: 0111 0011 */
+OPHANDLER( jmp_iadptr )
+{
+ PC = ACC + DPTR;
+}
+
+//JNB bit addr, code addr /* 1: 0011 0000 */
+OPHANDLER( jnb )
+{
+ 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
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JNC code addr /* 1: 0101 0000 */
+OPHANDLER( jnc )
+{
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(!GET_CY) //Jump if Carry Flag not set
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JNZ code addr /* 1: 0111 0000 */
+OPHANDLER( jnz )
+{
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(ACC != 0) //Branch if ACC is not 0
+ {
+ PC = PC+rel_addr;
+ }
+}
+
+//JZ code addr /* 1: 0110 0000 */
+OPHANDLER( jz )
+{
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(ACC == 0) //Branch if ACC is 0
+ {
+ PC = PC+rel_addr;
+ }
+}
+
+//LCALL code addr /* 1: 0001 0010 */
+OPHANDLER( lcall )
+{
+ 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);
+}
+
+//LJMP code addr /* 1: 0000 0010 */
+OPHANDLER( ljmp )
+{
+ uint8_t addr_hi, addr_lo;
+ addr_hi = ROP_ARG(PC++);
+ addr_lo = ROP_ARG(PC++);
+ PC = (uint16_t)((addr_hi<<8) | addr_lo);
+}
+
+//MOV A, #data /* 1: 0111 0100 */
+OPHANDLER( mov_a_byte )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ SET_ACC(data); //Store data to ACC
+}
+
+//MOV A, data addr /* 1: 1110 0101 */
+OPHANDLER( mov_a_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC
+}
+
+//MOV A,@RO/@R1 /* 1: 1110 011i */
+OPHANDLER( mov_a_ir )
+{
+ SET_ACC(IRAM_IR(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 )
+{
+ SET_ACC(R_REG(r)); //Store contents of R0 - R7 to ACC
+}
+
+//MOV data addr, #data /* 1: 0111 0101 */
+OPHANDLER( mov_mem_byte )
+{
+ 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
+}
+
+//MOV data addr, data addr /* 1: 1000 0101 */
+OPHANDLER( mov_mem_mem )
+{
+ //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
+}
+
+//MOV @R0/@R1, #data /* 1: 0111 011i */
+OPHANDLER( mov_ir_byte )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ IRAM_IW(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 )
+{
+ uint8_t data = ROP_ARG(PC++); //Grab data
+ SET_REG(r, data); //Store to R0 - R7
+}
+
+//MOV data addr, @R0/@R1 /* 1: 1000 011i */
+OPHANDLER( mov_mem_ir )
+{
+ 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
+}
+
+//MOV data addr,R0 to R7 /* 1: 1000 1rrr */
+OPHANDLER( mov_mem_r )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr,R_REG(r)); //Store contents of R0 - R7 to data address
+}
+
+//MOV DPTR, #data16 /* 1: 1001 0000 */
+OPHANDLER( mov_dptr_byte )
+{
+ 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
+}
+
+//MOV bit addr, C /* 1: 1001 0010 */
+OPHANDLER( mov_bitaddr_c )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,GET_CY); //Store Carry Flag to Bit Address
+}
+
+//MOV @R0/@R1, data addr /* 1: 1010 011i */
+OPHANDLER( mov_ir_mem )
+{
+ 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
+}
+
+//MOV R0 to R7, data addr /* 1: 1010 1rrr */
+OPHANDLER( mov_r_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ SET_REG(r, IRAM_R(addr)); //Store to R0 - R7
+}
+
+//MOV data addr, A /* 1: 1111 0101 */
+OPHANDLER( mov_mem_a )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr,ACC); //Store A to data address
+}
+
+//MOV @R0/@R1, A /* 1: 1111 011i */
+OPHANDLER( mov_ir_a )
+{
+ IRAM_IW(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 )
+{
+ SET_REG(r, ACC); //Store A to R0-R7
+}
+
+//MOVC A, @A + PC /* 1: 1000 0011 */
+OPHANDLER( movc_a_iapc )
+{
+ uint8_t data;
+ data = CODEMEM_R(ACC+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 )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab bit address
+ SET_CY( (BIT_R(addr)) ); //Store Bit from Bit Address to Carry Flag
+}
+
+//MOVC A, @A + DPTR /* 1: 1001 0011 */
+OPHANDLER( movc_a_iadptr )
+{
+ uint8_t data;
+ data = CODEMEM_R(ACC + DPTR); //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 )
+{
+// 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
+ 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 )
+{
+ 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
+ SET_ACC(byte); //Store to ACC
+}
+
+//MOVX @DPTR,A /* 1: 1111 0000 */
+//(Move A to External Ram 16 bit address)
+OPHANDLER( movx_idptr_a )
+{
+// 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
+}
+
+//MOVX @R0/@R1,A /* 1: 1111 001i */
+//(Move A to External Ram 8 bit address)
+OPHANDLER( movx_ir_a )
+{
+ 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
+}
+
+//MUL AB /* 1: 1010 0100 */
+OPHANDLER( mul_ab )
+{
+ 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));
+ //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 )
+{
+}
+
+//ORL data addr, A /* 1: 0100 0010 */
+OPHANDLER( orl_mem_a )
+{
+ 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
+}
+
+//ORL data addr, #data /* 1: 0100 0011 */
+OPHANDLER( orl_mem_byte )
+{
+ 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
+}
+
+//ORL A, #data /* 1: 0100 0100 */
+OPHANDLER( orl_a_byte )
+{
+ uint8_t data = ROP_ARG(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 )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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 )
+{
+ uint8_t data = IRAM_IR(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 )
+{
+ 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 )
+{
+ 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
+ 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 )
+{
+ 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
+ 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 )
+{
+ 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
+ SP = SP-1; //Decrement SP
+}
+
+//PUSH data addr /* 1: 1100 0000 */
+OPHANDLER( push )
+{
+ uint8_t addr = ROP_ARG(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
+}
+
+//RET /* 1: 0010 0010 */
+OPHANDLER( ret )
+{
+ POP_PC();
+}
+
+//RETI /* 1: 0011 0010 */
+OPHANDLER( reti )
+{
+ POP_PC();
+ CLEAR_CURRENT_IRQ();
+}
+
+//RL A /* 1: 0010 0011 */
+OPHANDLER( rl_a )
+{
+ //Left Shift A, Bit 7 carries to Bit 0
+ int carry = ((ACC & 0x80) >> 7);
+ int data = (ACC<<1) & 0xfe;
+ SET_ACC( data | carry);
+}
+
+//RLC A /* 1: 0011 0011 */
+OPHANDLER( rlc_a )
+{
+ //Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC
+ int carry = ((ACC & 0x80) >> 7);
+ int data = ((ACC<<1) & 0xfe) | GET_CY;
+ SET_ACC( data);
+ SET_CY(carry);
+}
+
+//RR A /* 1: 0000 0011 */
+OPHANDLER( rr_a )
+{
+ //Right Shift A, Bit 0 carries to Bit 7
+ int carry = ((ACC & 1) << 7);
+ int data = (ACC>>1) & 0x7f;
+ SET_ACC( data | carry);
+}
+
+//RRC A /* 1: 0001 0011 */
+OPHANDLER( rrc_a )
+{
+ //Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag
+ int carry = (ACC & 1);
+ int data = ((ACC>>1) & 0x7f) | (GET_CY<<7);
+ SET_ACC( data);
+ SET_CY(carry);
+}
+
+//SETB C /* 1: 1101 0011 */
+OPHANDLER( setb_c )
+{
+ SET_CY(1); //Set Carry Flag
+}
+
+//SETB bit addr /* 1: 1101 0010 */
+OPHANDLER( setb_bitaddr )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,1); //Set Bit at Bit Address
+}
+
+//SJMP code addr /* 1: 1000 0000 */
+OPHANDLER( sjmp )
+{
+ int8_t rel_addr = ROP_ARG(PC++); //Grab relative code address
+ PC = PC + rel_addr; //Update PC
+}
+
+//SUBB A, #data /* 1: 1001 0100 */
+OPHANDLER( subb_a_byte )
+{
+ uint8_t data = ROP_ARG(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+
+}
+
+//SUBB A, data addr /* 1: 1001 0101 */
+OPHANDLER( subb_a_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SUBB A, @R0/@R1 /* 1: 1001 011i */
+OPHANDLER( subb_a_ir )
+{
+ uint8_t data = IRAM_IR(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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SUBB A, R0 to R7 /* 1: 1001 1rrr */
+OPHANDLER( subb_a_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
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SWAP A /* 1: 1100 0100 */
+OPHANDLER( swap_a )
+{
+ uint8_t a_nib_lo, a_nib_hi;
+ a_nib_hi = (ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi
+ a_nib_lo = (ACC & 0xf0) >> 4; //Grab hi byte of ACC and move to lo
+ SET_ACC( a_nib_hi | a_nib_lo);
+}
+
+//XCH A, data addr /* 1: 1100 0101 */
+OPHANDLER( xch_a_mem )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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
+}
+
+//XCH A, @RO/@R1 /* 1: 1100 011i */
+OPHANDLER( xch_a_ir )
+{
+ uint8_t data = IRAM_IR(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
+}
+
+//XCH A, RO to R7 /* 1: 1100 1rrr */
+OPHANDLER( xch_a_r )
+{
+ uint8_t data = R_REG(r); //Grab data from R0-R7
+ uint8_t oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ SET_REG(r, oldACC); //Sets data address to old value of ACC
+}
+
+//XCHD A, @R0/@R1 /* 1: 1101 011i */
+OPHANDLER( xchd_a_ir )
+{
+ uint8_t acc, ir_data;
+ ir_data = IRAM_IR(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
+}
+
+//XRL data addr, A /* 1: 0110 0010 */
+OPHANDLER( xrl_mem_a )
+{
+ 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
+}
+
+//XRL data addr, #data /* 1: 0110 0011 */
+OPHANDLER( xrl_mem_byte )
+{
+ 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
+}
+
+//XRL A, #data /* 1: 0110 0100 */
+OPHANDLER( xrl_a_byte )
+{
+ uint8_t data = ROP_ARG(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 )
+{
+ uint8_t addr = ROP_ARG(PC++); //Grab data address
+ uint8_t data = IRAM_R(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 )
+{
+ uint8_t data = IRAM_IR(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 )
+{
+ 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 )
+{
+ LOG(("i8051 '%s': illegal opcode at 0x%03x: %02x\n", tag(), PC-1, r));
+}
diff --git a/src/devices/cpu/mcs51/axc51-core.cpp b/src/devices/cpu/mcs51/axc51-core.cpp
deleted file mode 100644
index 16739ee7419..00000000000
--- a/src/devices/cpu/mcs51/axc51-core.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:David Haywood
-/*****************************************************************************
-
- AXC51-CORE (AppoTech Inc.)
-
- used in
-
- AX208 SoC
-
- Notes:
-
- AXC51CORE:
- somes sources indicate that the extended opcode encoding may change
- on some CPU models despite all being 'AXC51CORE' however we lack solid
- information on this at present.
-
- AX208:
- The CPU has 0x2000 bytes of internal ROM mapped at 0x8000-0x9fff providing
- bootcode, operating kernel and many standard library functions
-
- *****************************************************************************/
-
-#include "emu.h"
-#include "axc51-core.h"
-#include "axc51-core_dasm.h"
-
-DEFINE_DEVICE_TYPE(AXC51CORE, axc51core_cpu_device, "axc51core", "AppoTech AXC51-CORE")
-DEFINE_DEVICE_TYPE(AX208, ax208_cpu_device, "ax208", "AppoTech AX208 (AXC51-CORE)")
-DEFINE_DEVICE_TYPE(AX208P, ax208p_cpu_device, "ax208p", "AppoTech AX208 (AXC51-CORE) (prototype?)")
-
-// AXC51CORE (base device)
-
-axc51core_cpu_device::axc51core_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)
- : mcs51_cpu_device(mconfig, type, tag, owner, clock, program_map, data_map, program_width, data_width, features)
-{
-}
-
-axc51core_cpu_device::axc51core_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : axc51core_cpu_device(mconfig, AXC51CORE, tag, owner, clock, address_map_constructor(FUNC(axc51core_cpu_device::program_internal), this), address_map_constructor(FUNC(axc51core_cpu_device::data_internal), this), 0, 8)
-{
-}
-
-std::unique_ptr<util::disasm_interface> axc51core_cpu_device::create_disassembler()
-{
- return std::make_unique<axc51core_disassembler>();
-}
-
-// 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)
- : axc51core_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::ax208_internal_data_mem), 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<util::disasm_interface> ax208_cpu_device::create_disassembler()
-{
- return std::make_unique<ax208_disassembler>();
-}
-
-void ax208_cpu_device::ax208_internal_program_mem(address_map &map)
-{
- map(0x8000, 0x9fff).rom().region("rom", 0); // this can only be read from code running within the same region
-}
-
-void ax208_cpu_device::ax208_internal_data_mem(address_map &map)
-{
- map(0x0000, 0x00ff).ram().share("scratchpad");
- map(0x0100, 0x01ff).ram().share("sfr_ram"); /* SFR */
-}
-
-
-ROM_START( ax208 ) // assume all production ax208 chips use this internal ROM
- ROM_REGION( 0x2000, "rom", 0 )
- ROM_LOAD("ax208.bin", 0x0000, 0x2000, CRC(b85f954a) SHA1(0dc7ab9bdaf73231d4d6627fe6308fe8103e1bbc) )
-ROM_END
-
-const tiny_rom_entry *ax208_cpu_device::device_rom_region() const
-{
- return ROM_NAME( ax208 );
-}
-
-void ax208_cpu_device::device_reset()
-{
- axc51core_cpu_device::device_reset();
- set_state_int(MCS51_PC, 0x8000);
-}
-
-
-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)
-{
-}
-
-ROM_START( ax208p ) // this is an early revision of the internal AX208 code, some functions are moved around so it isn't entirely compatible
- ROM_REGION( 0x2000, "rom", 0 )
- ROM_LOAD("mask208.bin", 0x0000, 0x2000, CRC(52396183) SHA1(b119000f93251894a352ecf675ee42f2e5c347bd) )
-ROM_END
-
-const tiny_rom_entry *ax208p_cpu_device::device_rom_region() const
-{
- return ROM_NAME( ax208p );
-}
-
diff --git a/src/devices/cpu/mcs51/axc51-core.h b/src/devices/cpu/mcs51/axc51-core.h
deleted file mode 100644
index 2198acae356..00000000000
--- a/src/devices/cpu/mcs51/axc51-core.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:David Haywood
-/*****************************************************************************
-
- AXC51-CORE (AppoTech Inc.)
-
- used in
-
- AX208 SoC
-
- *****************************************************************************/
-
-#ifndef MAME_CPU_MCS51_AXC51_CORE_H
-#define MAME_CPU_MCS51_AXC51_CORE_H
-
-#pragma once
-
-#include "mcs51.h"
-
-DECLARE_DEVICE_TYPE(AXC51CORE, axc51core_cpu_device)
-DECLARE_DEVICE_TYPE(AX208, ax208_cpu_device)
-DECLARE_DEVICE_TYPE(AX208P, ax208p_cpu_device)
-
-class axc51core_cpu_device : public mcs51_cpu_device
-{
-public:
- // construction/destruction
- axc51core_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- axc51core_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);
-
-protected:
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-};
-
-
-class ax208_cpu_device : public axc51core_cpu_device
-{
-public:
- // construction/destruction
- ax208_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- ax208_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_reset() override;
-
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- void ax208_internal_program_mem(address_map &map);
- void ax208_internal_data_mem(address_map &map);
-};
-
-class ax208p_cpu_device : public ax208_cpu_device
-{
-public:
- // construction/destruction
- ax208p_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
-
-
-#endif // MAME_CPU_MCS51_AXC51_CORE_H
diff --git a/src/devices/cpu/mcs51/mcs51.h b/src/devices/cpu/mcs51/mcs51.h
index 14d55792f38..32925c23de8 100644
--- a/src/devices/cpu/mcs51/mcs51.h
+++ b/src/devices/cpu/mcs51/mcs51.h
@@ -182,7 +182,7 @@ protected:
void clear_current_irq();
uint8_t r_acc();
uint8_t r_psw();
- offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask);
+ virtual offs_t external_ram_iaddr(offs_t offset, offs_t mem_mask);
uint8_t iram_read(size_t offset);
void iram_write(size_t offset, uint8_t data);
void push_pc();
diff --git a/src/mame/skeleton/monon_color.cpp b/src/mame/skeleton/monon_color.cpp
index d9555cb3e88..45e14443eec 100644
--- a/src/mame/skeleton/monon_color.cpp
+++ b/src/mame/skeleton/monon_color.cpp
@@ -13,7 +13,7 @@
***************************************************************************/
#include "emu.h"
-#include "cpu/mcs51/axc51-core.h"
+#include "cpu/axc51/axc51.h"
#include "emupal.h"
#include "screen.h"
#include "softlist_dev.h"
@@ -30,9 +30,7 @@ public:
m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
- m_mainram(*this, "mainram"),
- //m_otherram(*this, "otherram"),
- m_bootcopy(0)
+ m_mainram(*this, "mainram")
{ }
void monon_color(machine_config &config);
@@ -47,54 +45,27 @@ protected:
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
private:
required_device<generic_slot_device> m_cart;
- required_device<cpu_device> m_maincpu;
+ required_device<ax208_cpu_device> m_maincpu;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_shared_ptr<uint8_t> m_mainram;
- //required_shared_ptr<uint8_t> m_otherram;
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
void monon_color_map(address_map &map);
- int m_bootcopy;
+ void monon_color_io_map(address_map &map);
};
void monon_color_state::machine_start()
{
- uint8_t* flash = memregion("flash")->base();
- uint8_t* maincpu = &m_mainram[0];
-
- memcpy(maincpu, flash+0x200, 0x1e00); // 0x4000-0x5dff fixed code?
-
-
}
void monon_color_state::machine_reset()
{
- uint8_t* flash = memregion("flash")->base();
- uint8_t* maincpu = &m_mainram[0];
-
- memset(maincpu + 0x1e00, 0x00, 0x1000);
-
- switch (m_bootcopy)
- {
- // there are a whole bunch of blocks that map at 0x5e00 (boot code jumps straight to 0x5e00)
- case 0x0: memcpy(maincpu + 0x1e00, flash + 0x2000, 0x1000); break; // BANK0 - clears RAM, sets up stack etc. but then jumps to 0x9xxx where we have nothing (probably the correct initial block tho)
- case 0x1: memcpy(maincpu + 0x1e00, flash + 0x4200, 0x0a00); break; // BANK1 - just set register + a jump (to function that writes to UART)
- case 0x2: memcpy(maincpu + 0x1e00, flash + 0x4c00, 0x0a00); break; // BANK2
- case 0x3: memcpy(maincpu + 0x1e00, flash + 0x5600, 0x0a00); break; // BANK3
- case 0x4: memcpy(maincpu + 0x1e00, flash + 0x6000, 0x0a00); break; // BANK4 - ends up reting with nothing on the stack
- case 0x5: memcpy(maincpu + 0x1e00, flash + 0x6a00, 0x0a00); break; // BANK5
- case 0x6: memcpy(maincpu + 0x1e00, flash + 0x7400, 0x0a00); break; // BANK6
- case 0x7: memcpy(maincpu + 0x1e00, flash + 0x7e00, 0x0a00); break; // BANK7
- case 0x8: memcpy(maincpu + 0x1e00, flash + 0x8800, 0x0a00); break; // BANK8
- case 0x9: memcpy(maincpu + 0x1e00, flash + 0x9200, 0x0a00); break; // BANK9
- }
-
- m_bootcopy++;
- if (m_bootcopy == 0xa) m_bootcopy = 0x0;
+ 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?)
@@ -131,11 +102,20 @@ void monon_color_state::monon_color_map(address_map &map)
// 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);
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 46c835417e5..25a468475d9 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -109,7 +109,7 @@ using util::BIT;
#include "cpu/mcs40/mcs40dasm.h"
#include "cpu/mcs48/mcs48dsm.h"
#include "cpu/mcs51/mcs51dasm.h"
-#include "cpu/mcs51/axc51-core_dasm.h"
+#include "cpu/axc51/axc51dasm.h"
#include "cpu/mcs96/i8x9xd.h"
#include "cpu/mcs96/i8xc196d.h"
#include "cpu/melps4/melps4d.h"