diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/axc51/axc51.cpp | 1263 | ||||
-rw-r--r-- | src/devices/cpu/axc51/axc51.h | 479 | ||||
-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.hxx | 982 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core.cpp | 110 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/axc51-core.h | 65 | ||||
-rw-r--r-- | src/devices/cpu/mcs51/mcs51.h | 2 | ||||
-rw-r--r-- | src/mame/skeleton/monon_color.cpp | 50 | ||||
-rw-r--r-- | src/tools/unidasm.cpp | 2 |
10 files changed, 3795 insertions, 236 deletions
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 ¶ms, 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 ¶ms) +{ + 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 ¶ms) 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 ¶ms, 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" |