From 9d36a1040a0693e0af11de681de67f02369e374c Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 20 Feb 2024 22:42:59 -0500 Subject: pic16c5x: Register file cleanup - Use member variables for core special registers, eliminating unsafe abuse of get_write_ptr and permitting watchpoints to trigger on accesses to these - Use arrays for TRIS registers and port read/write callbacks - Narrow the width of some variables and function parameters --- src/devices/cpu/pic16c5x/pic16c5x.cpp | 623 ++++++++++++++++++---------------- src/devices/cpu/pic16c5x/pic16c5x.h | 92 ++--- 2 files changed, 390 insertions(+), 325 deletions(-) diff --git a/src/devices/cpu/pic16c5x/pic16c5x.cpp b/src/devices/cpu/pic16c5x/pic16c5x.cpp index 5f2a02a23b6..0eb0e7a893a 100644 --- a/src/devices/cpu/pic16c5x/pic16c5x.cpp +++ b/src/devices/cpu/pic16c5x/pic16c5x.cpp @@ -131,14 +131,76 @@ void pic16c5x_device::rom_11(address_map &map) map(0x000, 0x7ff).rom(); } -void pic16c5x_device::ram_5(address_map &map) +void pic16c5x_device::core_regs(address_map &map, u8 mirror) { - map(0x00, 0x1f).ram(); + map(0x00, 0x00).noprw().mirror(mirror); // Not an actual register, reading indirectly (FSR=0) returns 0 + map(0x01, 0x01).rw(FUNC(pic16c5x_device::tmr0_r), FUNC(pic16c5x_device::tmr0_w)).mirror(mirror); + map(0x02, 0x02).rw(FUNC(pic16c5x_device::pcl_r), FUNC(pic16c5x_device::pcl_w)).mirror(mirror); + map(0x03, 0x03).rw(FUNC(pic16c5x_device::status_r), FUNC(pic16c5x_device::status_w)).mirror(mirror); + map(0x04, 0x04).rw(FUNC(pic16c5x_device::fsr_r), FUNC(pic16c5x_device::fsr_w)).mirror(mirror); } -void pic16c5x_device::ram_7(address_map &map) +// PIC16C54, PIC16C56: 2 ports (12 pins) + 25 bytes of RAM +void pic16c5x_device::ram_5_2ports(address_map &map) { - map(0x00, 0x0f).ram().mirror(0x60); + core_regs(map); + map(0x05, 0x05).rw(FUNC(pic16c5x_device::porta_r), FUNC(pic16c5x_device::porta_w)); + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)); + map(0x07, 0x1f).ram(); +} + +// PIC16C55: 3 ports (20 pins) + 24 bytes of RAM +void pic16c5x_device::ram_5_3ports(address_map &map) +{ + core_regs(map); + map(0x05, 0x05).rw(FUNC(pic16c5x_device::porta_r), FUNC(pic16c5x_device::porta_w)); + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)); + map(0x07, 0x07).rw(FUNC(pic16c5x_device::portc_r), FUNC(pic16c5x_device::portc_w)); + map(0x08, 0x1f).ram(); +} + +// PIC1655: 3 ports + 24 bytes of RAM +void pic16c5x_device::ram_1655_3ports(address_map &map) +{ + core_regs(map); + map(0x05, 0x05).r(FUNC(pic16c5x_device::porta_r)).nopw(); // A is input-only on 1655 + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)); + map(0x07, 0x07).rw(FUNC(pic16c5x_device::portc_r), FUNC(pic16c5x_device::portc_w)); + map(0x08, 0x1f).ram(); +} + +// PIC1650: 4 ports + 23 bytes of RAM +void pic16c5x_device::ram_5_4ports(address_map &map) +{ + core_regs(map); + map(0x05, 0x05).rw(FUNC(pic16c5x_device::porta_r), FUNC(pic16c5x_device::porta_w)); + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)); + map(0x07, 0x07).rw(FUNC(pic16c5x_device::portc_r), FUNC(pic16c5x_device::portc_w)); + map(0x08, 0x08).rw(FUNC(pic16c5x_device::portd_r), FUNC(pic16c5x_device::portd_w)); + map(0x09, 0x1f).ram(); +} + +// PIC16C58: 2 ports (12 pins) + 73 bytes of RAM +void pic16c5x_device::ram_7_2ports(address_map &map) +{ + core_regs(map, 0x60); + map(0x05, 0x05).rw(FUNC(pic16c5x_device::porta_r), FUNC(pic16c5x_device::porta_w)).mirror(0x60); + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)).mirror(0x60); + map(0x07, 0x0f).ram().mirror(0x60); + map(0x10, 0x1f).ram(); + map(0x30, 0x3f).ram(); + map(0x50, 0x5f).ram(); + map(0x70, 0x7f).ram(); +} + +// PIC16C57: 3 ports (20 pins) + 72 bytes of RAM +void pic16c5x_device::ram_7_3ports(address_map &map) +{ + core_regs(map, 0x60); + map(0x05, 0x05).rw(FUNC(pic16c5x_device::porta_r), FUNC(pic16c5x_device::porta_w)).mirror(0x60); + map(0x06, 0x06).rw(FUNC(pic16c5x_device::portb_r), FUNC(pic16c5x_device::portb_w)).mirror(0x60); + map(0x07, 0x07).rw(FUNC(pic16c5x_device::portc_r), FUNC(pic16c5x_device::portc_w)).mirror(0x60); + map(0x08, 0x0f).ram().mirror(0x60); map(0x10, 0x1f).ram(); map(0x30, 0x3f).ram(); map(0x50, 0x5f).ram(); @@ -146,69 +208,60 @@ void pic16c5x_device::ram_7(address_map &map) } -pic16c5x_device::pic16c5x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int program_width, int data_width, int picmodel) +pic16c5x_device::pic16c5x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int program_width, int data_width, int picmodel, address_map_constructor data_map) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_LITTLE, 16, program_width, -1, ((program_width == 9) ? address_map_constructor(FUNC(pic16c5x_device::rom_9), this) : ((program_width == 10) ? address_map_constructor(FUNC(pic16c5x_device::rom_10), this) : address_map_constructor(FUNC(pic16c5x_device::rom_11), this)))) - , m_data_config("data", ENDIANNESS_LITTLE, 8, data_width, 0, - ((data_width == 5) ? address_map_constructor(FUNC(pic16c5x_device::ram_5), this) : - address_map_constructor(FUNC(pic16c5x_device::ram_7), this))) - , m_internalram(nullptr) + , m_data_config("data", ENDIANNESS_LITTLE, 8, data_width, 0, data_map) , m_picmodel(picmodel) , m_data_width(data_width) , m_program_width(program_width) , m_temp_config(0) - , m_read_a(*this, 0) - , m_read_b(*this, 0) - , m_read_c(*this, 0) - , m_read_d(*this, 0) - , m_write_a(*this) - , m_write_b(*this) - , m_write_c(*this) - , m_write_d(*this) + , m_read_port(*this, 0) + , m_write_port(*this) { } pic16c54_device::pic16c54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC16C54, tag, owner, clock, 9, 5, 0x16C54) + : pic16c5x_device(mconfig, PIC16C54, tag, owner, clock, 9, 5, 0x16C54, address_map_constructor(FUNC(pic16c54_device::ram_5_2ports), this)) { } pic16c55_device::pic16c55_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC16C55, tag, owner, clock, 9, 5, 0x16C55) + : pic16c5x_device(mconfig, PIC16C55, tag, owner, clock, 9, 5, 0x16C55, address_map_constructor(FUNC(pic16c55_device::ram_5_3ports), this)) { } pic16c56_device::pic16c56_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC16C56, tag, owner, clock, 10, 5, 0x16C56) + : pic16c5x_device(mconfig, PIC16C56, tag, owner, clock, 10, 5, 0x16C56, address_map_constructor(FUNC(pic16c56_device::ram_5_2ports), this)) { } pic16c57_device::pic16c57_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC16C57, tag, owner, clock, 11, 7, 0x16C57) + : pic16c5x_device(mconfig, PIC16C57, tag, owner, clock, 11, 7, 0x16C57, address_map_constructor(FUNC(pic16c57_device::ram_7_3ports), this)) { } pic16c58_device::pic16c58_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC16C58, tag, owner, clock, 11, 7, 0x16C58) + : pic16c5x_device(mconfig, PIC16C58, tag, owner, clock, 11, 7, 0x16C58, address_map_constructor(FUNC(pic16c58_device::ram_7_2ports), this)) { } pic1650_device::pic1650_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC1650, tag, owner, clock, 9, 5, 0x1650) + : pic16c5x_device(mconfig, PIC1650, tag, owner, clock, 9, 5, 0x1650, address_map_constructor(FUNC(pic1650_device::ram_5_4ports), this)) { } pic1654s_device::pic1654s_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC1654S, tag, owner, clock, 9, 5, 0x1654) + : pic16c5x_device(mconfig, PIC1654S, tag, owner, clock, 9, 5, 0x1654, address_map_constructor(FUNC(pic1654s_device::ram_5_2ports), this)) { } pic1655_device::pic1655_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : pic16c5x_device(mconfig, PIC1655, tag, owner, clock, 9, 5, 0x1655) + : pic16c5x_device(mconfig, PIC1655, tag, owner, clock, 9, 5, 0x1655, address_map_constructor(FUNC(pic1655_device::ram_1655_3ports), this)) { } @@ -226,22 +279,6 @@ std::unique_ptr pic16c5x_device::create_disassembler() } -void pic16c5x_device::update_internalram_ptr() -{ - m_internalram = (u8 *)space(AS_DATA).get_write_ptr(0x00); -} - - - -#define TMR0 m_internalram[1] -#define PCL m_internalram[2] -#define STATUS m_internalram[3] -#define FSR m_internalram[4] -#define PORTA m_internalram[5] -#define PORTB m_internalram[6] -#define PORTC m_internalram[7] -#define PORTD m_internalram[8] - // ******** The following is the Status Flag register definition. ******** // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | @@ -253,12 +290,12 @@ void pic16c5x_device::update_internalram_ptr() #define DC_FLAG 0x02 // DC Digit Carry/Borrow flag (Nibble) #define C_FLAG 0x01 // C Carry/Borrow Flag (Byte) -#define PA (STATUS & PA_REG) -#define TO (STATUS & TO_FLAG) -#define PD (STATUS & PD_FLAG) -#define ZERO (STATUS & Z_FLAG) -#define DC (STATUS & DC_FLAG) -#define CARRY (STATUS & C_FLAG) +#define PA (m_STATUS & PA_REG) +#define TO (m_STATUS & TO_FLAG) +#define PD (m_STATUS & PD_FLAG) +#define ZERO (m_STATUS & Z_FLAG) +#define DC (m_STATUS & DC_FLAG) +#define CARRY (m_STATUS & C_FLAG) // ******** The following is the Option Flag register definition. ******** @@ -290,9 +327,6 @@ void pic16c5x_device::update_internalram_ptr() * Shortcuts ************************************************************************/ -#define M_RDRAM(A) (((A) < 9) ? m_internalram[A] : m_data.read_byte(A)) -#define M_WRTRAM(A,V) do { if ((A) < 9) m_internalram[A] = (V); else m_data.write_byte(A,V); } while (0) - #define CLR(flagreg, flag) (flagreg &= u8(~flag)) #define SET(flagreg, flag) (flagreg |= (flag)) @@ -304,9 +338,9 @@ void pic16c5x_device::update_internalram_ptr() void pic16c5x_device::calc_zero_flag() { if (m_ALU == 0) - SET(STATUS, Z_FLAG); + SET(m_STATUS, Z_FLAG); else - CLR(STATUS, Z_FLAG); + CLR(m_STATUS, Z_FLAG); } void pic16c5x_device::calc_add_flags(u8 augend) @@ -314,14 +348,14 @@ void pic16c5x_device::calc_add_flags(u8 augend) calc_zero_flag(); if (augend > m_ALU) - SET(STATUS, C_FLAG); + SET(m_STATUS, C_FLAG); else - CLR(STATUS, C_FLAG); + CLR(m_STATUS, C_FLAG); if ((augend & 0x0f) > (m_ALU & 0x0f)) - SET(STATUS, DC_FLAG); + SET(m_STATUS, DC_FLAG); else - CLR(STATUS, DC_FLAG); + CLR(m_STATUS, DC_FLAG); } void pic16c5x_device::calc_sub_flags(u8 minuend) @@ -329,22 +363,21 @@ void pic16c5x_device::calc_sub_flags(u8 minuend) calc_zero_flag(); if (minuend < m_ALU) - CLR(STATUS, C_FLAG); + CLR(m_STATUS, C_FLAG); else - SET(STATUS, C_FLAG); + SET(m_STATUS, C_FLAG); if ((minuend & 0x0f) < (m_ALU & 0x0f)) - CLR(STATUS, DC_FLAG); + CLR(m_STATUS, DC_FLAG); else - SET(STATUS, DC_FLAG); + SET(m_STATUS, DC_FLAG); } -void pic16c5x_device::set_pc(offs_t addr) +void pic16c5x_device::set_pc(u16 addr) { m_PC = addr & m_program_mask; - PCL = m_PC & 0xff; } u16 pic16c5x_device::pop_stack() @@ -362,184 +395,188 @@ void pic16c5x_device::push_stack(u16 data) -u8 pic16c5x_device::get_regfile(offs_t addr) // Read from internal memory +u8 pic16c5x_device::get_regfile(u8 addr) // Read from internal memory { - u8 data = 0; - if (addr == 0) { // Indirect addressing - addr = FSR & m_data_mask; + addr = m_FSR & m_data_mask; + } else if (m_data_width != 5) { + addr |= (m_FSR & 0x60); // FSR bits 6-5 are used for banking in direct mode } - if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { - addr |= (FSR & 0x60); // FSR bits 6-5 are used for banking in direct mode - } + return m_data.read_byte(addr); +} - if ((addr & 0x10) == 0) addr &= 0x0f; +void pic16c5x_device::store_regfile(u8 addr, u8 data) // Write to internal memory +{ + if (addr == 0) { // Indirect addressing + addr = m_FSR & m_data_mask; + } else if (m_data_width != 5) { + addr |= (m_FSR & 0x60); // FSR bits 6-5 are used for banking in direct mode + } - switch (addr) - { - case 0: - // Not an actual register, reading indirectly (FSR=0) returns 0 - data = 0; - break; + m_data.write_byte(addr, data); +} - case 5: - // read port A - if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { - data = m_read_a(PIC16C5x_PORTA, 0xff) & PORTA; - } - else if (m_picmodel == 0x1655) { - data = m_read_a(PIC16C5x_PORTA, 0xff) & 0x0f; - } - else { - data = m_read_a(PIC16C5x_PORTA, 0xff); - data &= m_TRISA; - data |= (u8(~m_TRISA) & PORTA); - data &= 0x0f; // 4-bit port (only lower 4 bits used) - } - break; - case 6: - // read port B - if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { - data = m_read_b(PIC16C5x_PORTB, 0xff) & PORTB; - } - else if (m_picmodel != 0x1655) { // B is output-only on 1655 - data = m_read_b(PIC16C5x_PORTB, 0xff); - data &= m_TRISB; - data |= (u8(~m_TRISB) & PORTB); - } - break; +void pic16c5x_device::store_result(u8 addr, u8 data) +{ + if (m_opcode.b.l & 0x20) + store_regfile(addr, data); + else + m_W = data; +} - case 7: - // read port C - if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { - data = m_read_c(PIC16C5x_PORTC, 0xff) & PORTC; - } - else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - data = m_read_c(PIC16C5x_PORTC, 0xff); - data &= m_TRISC; - data |= (u8(~m_TRISC) & PORTC); - } - else { // PIC16C54, PIC16C56, PIC16C58 - data = M_RDRAM(addr); - } - break; - case 8: - // read port D - if (m_picmodel == 0x1650) { - data = m_read_d(PIC16C5x_PORTD, 0xff) & PORTD; - } - else { - data = M_RDRAM(addr); - } - break; - default: - data = M_RDRAM(addr); - break; - } - return data; +u8 pic16c5x_device::tmr0_r() +{ + return m_TMR0; } -void pic16c5x_device::store_regfile(offs_t addr, u8 data) // Write to internal memory +void pic16c5x_device::tmr0_w(u8 data) { - if (addr == 0) { // Indirect addressing - addr = FSR & m_data_mask; - } + m_delay_timer = 2; // Timer increment is inhibited for 2 cycles + if (PSA == 0) m_prescaler = 0; // Must clear the Prescaler + m_TMR0 = data; +} - if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { - addr |= (FSR & 0x60); // FSR bits 6-5 are used for banking in direct mode - } +u8 pic16c5x_device::pcl_r() +{ + return m_PC & 0x0ff; +} - if ((addr & 0x10) == 0) addr &= 0x0f; +void pic16c5x_device::pcl_w(u8 data) +{ + set_pc(((m_STATUS & PA_REG) << 4) | data); + if (!machine().side_effects_disabled()) + m_inst_cycles++; +} - switch (addr) - { - case 0: - // Not an actual register, nothing to save - break; +u8 pic16c5x_device::status_r() +{ + return m_STATUS; +} - case 1: - m_delay_timer = 2; // Timer increment is inhibited for 2 cycles - if (PSA == 0) m_prescaler = 0; // Must clear the Prescaler - TMR0 = data; - break; +void pic16c5x_device::status_w(u8 data) +{ + // on GI PIC165x, high bits are 1 + if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655) + m_STATUS = data | u8(~m_status_mask); + else + m_STATUS = (m_STATUS & (TO_FLAG | PD_FLAG)) | (data & u8(~(TO_FLAG | PD_FLAG))); +} - case 2: - set_pc(((STATUS & PA_REG) << 4) | data); - m_inst_cycles++; - break; +u8 pic16c5x_device::fsr_r() +{ + return m_FSR; +} - case 3: - // on GI PIC165x, high bits are 1 - if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655) - STATUS = data | u8(~m_status_mask); - else - STATUS = (STATUS & (TO_FLAG | PD_FLAG)) | (data & u8(~(TO_FLAG | PD_FLAG))); - break; +void pic16c5x_device::fsr_w(u8 data) +{ + // high bits are 1 + m_FSR = data | u8(~m_data_mask); +} - case 4: - // high bits are 1 - FSR = data | u8(~m_data_mask); - break; +u8 pic16c5x_device::porta_r() +{ + // read port A + if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { + return m_read_port[PORTA](PORTA, 0xff) & m_port_data[PORTA]; + } + else if (m_picmodel == 0x1655) { + return m_read_port[PORTA](PORTA, 0xff) & 0x0f; + } + else { + u8 data = m_read_port[PORTA](PORTA, 0xff); + data &= m_port_tris[PORTA]; + data |= (u8(~m_port_tris[PORTA]) & m_port_data[PORTA]); + return data & 0x0f; // 4-bit port (only lower 4 bits used) + } +} - case 5: - // write port A - if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { - m_write_a(PIC16C5x_PORTA, data, 0xff); - } - else if (m_picmodel != 0x1655) { // A is input-only on 1655 - data &= 0x0f; // 4-bit port (only lower 4 bits used) - m_write_a(PIC16C5x_PORTA, data & u8(~m_TRISA) & 0x0f, u8(~m_TRISA) & 0x0f); - } - PORTA = data; - break; +void pic16c5x_device::porta_w(u8 data) +{ + // write port A + if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { + m_write_port[PORTA](PORTA, data, 0xff); + } + else { + assert(m_picmodel != 0x1655); + data &= 0x0f; // 4-bit port (only lower 4 bits used) + m_write_port[PORTA](PORTA, data & u8(~m_port_tris[PORTA]) & 0x0f, u8(~m_port_tris[PORTA]) & 0x0f); + } + m_port_data[PORTA] = data; +} - case 6: - // write port B - if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655) { - m_write_b(PIC16C5x_PORTB, data, 0xff); - } - else { - m_write_b(PIC16C5x_PORTB, data & u8(~m_TRISB), u8(~m_TRISB)); - } - PORTB = data; - break; +u8 pic16c5x_device::portb_r() +{ + // read port B + if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) { + return m_read_port[PORTB](PORTB, 0xff) & m_port_data[PORTB]; + } + else if (m_picmodel != 0x1655) { // B is output-only on 1655 + u8 data = m_read_port[PORTB](PORTB, 0xff); + data &= m_port_tris[PORTB]; + data |= (u8(~m_port_tris[PORTB]) & m_port_data[PORTB]); + return data; + } + else + return m_port_data[PORTB]; +} - case 7: - // write port C - if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { - m_write_c(PIC16C5x_PORTC, data, 0xff); - } - else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - m_write_c(PIC16C5x_PORTC, data & u8(~m_TRISC), u8(~m_TRISC)); - } - PORTC = data; // also writes to RAM - break; +void pic16c5x_device::portb_w(u8 data) +{ + // write port B + if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655) { + m_write_port[PORTB](PORTB, data, 0xff); + } + else { + m_write_port[PORTB](PORTB, data & u8(~m_port_tris[PORTB]), u8(~m_port_tris[PORTB])); + } + m_port_data[PORTB] = data; +} - case 8: - // write port D - if (m_picmodel == 0x1650) { - m_write_d(PIC16C5x_PORTD, data, 0xff); - } - PORTD = data; // also writes to RAM - break; +u8 pic16c5x_device::portc_r() +{ + // read port C + if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { + return m_read_port[PORTC](PORTC, 0xff) & m_port_data[PORTC]; + } + else { + assert((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)); + u8 data = m_read_port[PORTC](PORTC, 0xff); + data &= m_port_tris[PORTC]; + data |= (u8(~m_port_tris[PORTC]) & m_port_data[PORTC]); + return data; + } +} - default: - M_WRTRAM(addr, data); - break; +void pic16c5x_device::portc_w(u8 data) +{ + // write port C + if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { + m_write_port[PORTC](PORTC, data, 0xff); } + else { + assert((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)); + m_write_port[PORTC](PORTC, data & u8(~m_port_tris[PORTC]), u8(~m_port_tris[PORTC])); + } + m_port_data[PORTC] = data; } +u8 pic16c5x_device::portd_r() +{ + // read port D + assert(m_picmodel == 0x1650); + return m_read_port[PORTD](PORTD, 0xff) & m_port_data[PORTD]; +} -void pic16c5x_device::store_result(offs_t addr, u8 data) +void pic16c5x_device::portd_w(u8 data) { - if (m_opcode.b.l & 0x20) - store_regfile(addr, data); - else - m_W = data; + // write port D + assert(m_picmodel == 0x1650); + m_write_port[PORTD](PORTD, data, 0xff); + m_port_data[PORTD] = data; } @@ -549,7 +586,7 @@ void pic16c5x_device::store_result(offs_t addr, u8 data) void pic16c5x_device::illegal() { - logerror("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", m_PREVPC, m_opcode.w.l); + logerror("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", m_PREVPC, m_opcode.w); } /* @@ -616,27 +653,27 @@ void pic16c5x_device::btfsc() void pic16c5x_device::call() { push_stack(m_PC); - set_pc((((STATUS & PA_REG) << 4) | m_opcode.b.l) & 0x6ff); + set_pc((((m_STATUS & PA_REG) << 4) | m_opcode.b.l) & 0x6ff); } void pic16c5x_device::clrw() { m_W = 0; - SET(STATUS, Z_FLAG); + SET(m_STATUS, Z_FLAG); } void pic16c5x_device::clrf() { store_regfile(ADDR, 0); - SET(STATUS, Z_FLAG); + SET(m_STATUS, Z_FLAG); } void pic16c5x_device::clrwdt() { m_WDT = 0; if (PSA) m_prescaler = 0; - SET(STATUS, TO_FLAG); - SET(STATUS, PD_FLAG); + SET(m_STATUS, TO_FLAG); + SET(m_STATUS, PD_FLAG); } void pic16c5x_device::comf() @@ -665,7 +702,7 @@ void pic16c5x_device::decfsz() void pic16c5x_device::goto_op() { - set_pc(((STATUS & PA_REG) << 4) | (m_opcode.w.l & 0x1ff)); + set_pc(((m_STATUS & PA_REG) << 4) | (m_opcode.w & 0x1ff)); } void pic16c5x_device::incf() @@ -737,13 +774,13 @@ void pic16c5x_device::rlf() m_ALU = get_regfile(ADDR); int carry = BIT(m_ALU, 7); m_ALU <<= 1; - if (STATUS & C_FLAG) m_ALU |= 1; + if (m_STATUS & C_FLAG) m_ALU |= 1; store_result(ADDR, m_ALU); if (carry) - SET(STATUS, C_FLAG); + SET(m_STATUS, C_FLAG); else - CLR(STATUS, C_FLAG); + CLR(m_STATUS, C_FLAG); } void pic16c5x_device::rrf() @@ -751,21 +788,21 @@ void pic16c5x_device::rrf() m_ALU = get_regfile(ADDR); int carry = BIT(m_ALU, 0); m_ALU >>= 1; - if (STATUS & C_FLAG) m_ALU |= 0x80; + if (m_STATUS & C_FLAG) m_ALU |= 0x80; store_result(ADDR, m_ALU); if (carry) - SET(STATUS, C_FLAG); + SET(m_STATUS, C_FLAG); else - CLR(STATUS, C_FLAG); + CLR(m_STATUS, C_FLAG); } void pic16c5x_device::sleepic() { if (WDTE) m_WDT = 0; if (PSA) m_prescaler = 0; - SET(STATUS, TO_FLAG); - CLR(STATUS, PD_FLAG); + SET(m_STATUS, TO_FLAG); + CLR(m_STATUS, PD_FLAG); } void pic16c5x_device::subwf() @@ -788,24 +825,24 @@ void pic16c5x_device::tris() switch (m_opcode.b.l & 0x7) { case 5: - if (m_TRISA != m_W) { - m_TRISA = m_W | 0xf0; - m_write_a(PIC16C5x_PORTA, PORTA & u8(~m_TRISA) & 0x0f, u8(~m_TRISA) & 0x0f); + if (m_port_tris[PORTA] != m_W) { + m_port_tris[PORTA] = m_W | 0xf0; + m_write_port[PORTA](PORTA, m_port_data[PORTA] & u8(~m_port_tris[PORTA]) & 0x0f, u8(~m_port_tris[PORTA]) & 0x0f); } break; case 6: - if (m_TRISB != m_W) { - m_TRISB = m_W; - m_write_b(PIC16C5x_PORTB, PORTB & u8(~m_TRISB), u8(~m_TRISB)); + if (m_port_tris[PORTB] != m_W) { + m_port_tris[PORTB] = m_W; + m_write_port[PORTB](PORTB, m_port_data[PORTB] & u8(~m_port_tris[PORTB]), u8(~m_port_tris[PORTB])); } break; case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - if (m_TRISC != m_W) { - m_TRISC = m_W; - m_write_c(PIC16C5x_PORTC, PORTC & u8(~m_TRISC), u8(~m_TRISC)); + if (m_port_tris[PORTC] != m_W) { + m_port_tris[PORTC] = m_W; + m_write_port[PORTC](PORTC, m_port_data[PORTC] & u8(~m_port_tris[PORTC]), u8(~m_port_tris[PORTC])); } } else { @@ -933,14 +970,14 @@ enum void pic16c5x_device::device_start() { + bool is_nmospic = (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655); + space(AS_PROGRAM).cache(m_program); space(AS_DATA).specific(m_data); m_program_mask = (1 << m_program_width) - 1; m_data_mask = (1 << m_data_width) - 1; - m_status_mask = (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655) ? 0x07 : 0xff; - - update_internalram_ptr(); + m_status_mask = is_nmospic ? 0x07 : 0xff; m_PC = 0; m_PREVPC = 0; @@ -949,9 +986,14 @@ void pic16c5x_device::device_start() m_CONFIG = 0; m_ALU = 0; m_WDT = 0; - memset(m_STACK, 0, sizeof(m_STACK)); + m_TMR0 = 0; + m_STATUS = ~m_status_mask; + m_FSR = 0; + std::fill(std::begin(m_port_data), std::end(m_port_data), 0); + std::fill(std::begin(m_port_tris), std::end(m_port_tris), 0); + std::fill(std::begin(m_STACK), std::end(m_STACK), 0); m_prescaler = 0; - m_opcode.d = 0; + m_opcode.w = 0; m_delay_timer = 0; m_rtcc = 0; @@ -967,12 +1009,15 @@ void pic16c5x_device::device_start() save_item(NAME(m_CONFIG)); save_item(NAME(m_ALU)); save_item(NAME(m_WDT)); - save_item(NAME(m_TRISA)); - save_item(NAME(m_TRISB)); - save_item(NAME(m_TRISC)); + save_item(NAME(m_TMR0)); + save_item(NAME(m_STATUS)); + save_item(NAME(m_FSR)); + save_item(NAME(m_port_data)); + if (!is_nmospic) + save_item(NAME(m_port_tris)); save_item(NAME(m_STACK)); save_item(NAME(m_prescaler)); - save_item(NAME(m_opcode.d)); + save_item(NAME(m_opcode.w)); save_item(NAME(m_delay_timer)); save_item(NAME(m_temp_config)); @@ -990,13 +1035,19 @@ void pic16c5x_device::device_start() state_add( PIC16C5x_OPT, "OPT", m_OPTION).formatstr("%02X"); state_add( PIC16C5x_STK0, "STK0", m_STACK[0]).mask(0xfff).formatstr("%03X"); state_add( PIC16C5x_STK1, "STK1", m_STACK[1]).mask(0xfff).formatstr("%03X"); - state_add( PIC16C5x_PRTA, "PRTA", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); + if (m_picmodel != 0x1655) + state_add( PIC16C5x_PRTA, "PRTA", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); state_add( PIC16C5x_PRTB, "PRTB", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); - state_add( PIC16C5x_PRTC, "PRTC", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); - state_add( PIC16C5x_PRTD, "PRTD", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); - state_add( PIC16C5x_TRSA, "TRSA", m_TRISA).mask(0xf).formatstr("%01X"); - state_add( PIC16C5x_TRSB, "TRSB", m_TRISB).formatstr("%02X"); - state_add( PIC16C5x_TRSC, "TRSC", m_TRISC).formatstr("%02X"); + if (m_picmodel != 0x1654 && m_picmodel != 0x16C54 && m_picmodel != 0x16C56 && m_picmodel != 0x16C58) + state_add( PIC16C5x_PRTC, "PRTC", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); + if (m_picmodel == 0x1650) + state_add( PIC16C5x_PRTD, "PRTD", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); + if (!is_nmospic) { + state_add( PIC16C5x_TRSA, "TRSA", m_port_tris[PORTA]).mask(0xf).formatstr("%01X"); + state_add( PIC16C5x_TRSB, "TRSB", m_port_tris[PORTB]).formatstr("%02X"); + if (m_picmodel != 0x16C54 && m_picmodel != 0x16C56 && m_picmodel != 0x16C58) + state_add( PIC16C5x_TRSC, "TRSC", m_port_tris[PORTC]).formatstr("%02X"); + } state_add( PIC16C5x_FSR, "FSR", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X"); state_add( PIC16C5x_PSCL, "PSCL", m_debugger_temp).callimport().formatstr("%3s"); @@ -1013,25 +1064,25 @@ void pic16c5x_device::state_import(const device_state_entry &entry) switch (entry.index()) { case PIC16C5x_STR: - STATUS = m_debugger_temp | u8(~m_status_mask); + m_STATUS = m_debugger_temp | u8(~m_status_mask); break; case PIC16C5x_TMR0: - TMR0 = m_debugger_temp; + m_TMR0 = m_debugger_temp; break; case PIC16C5x_PRTA: - PORTA = m_debugger_temp; + m_port_data[PORTA] = m_debugger_temp; break; case PIC16C5x_PRTB: - PORTB = m_debugger_temp; + m_port_data[PORTB] = m_debugger_temp; break; case PIC16C5x_PRTC: - PORTC = m_debugger_temp; + m_port_data[PORTC] = m_debugger_temp; break; case PIC16C5x_PRTD: - PORTD = m_debugger_temp; + m_port_data[PORTD] = m_debugger_temp; break; case PIC16C5x_FSR: - FSR = m_debugger_temp | u8(~m_data_mask); + m_FSR = m_debugger_temp | u8(~m_data_mask); break; case PIC16C5x_PSCL: m_prescaler = m_debugger_temp; @@ -1044,25 +1095,25 @@ void pic16c5x_device::state_export(const device_state_entry &entry) switch (entry.index()) { case PIC16C5x_STR: - m_debugger_temp = STATUS | u8(~m_status_mask); + m_debugger_temp = m_STATUS | u8(~m_status_mask); break; case PIC16C5x_TMR0: - m_debugger_temp = TMR0; + m_debugger_temp = m_TMR0; break; case PIC16C5x_PRTA: - m_debugger_temp = PORTA; + m_debugger_temp = m_port_data[PORTA]; break; case PIC16C5x_PRTB: - m_debugger_temp = PORTB; + m_debugger_temp = m_port_data[PORTB]; break; case PIC16C5x_PRTC: - m_debugger_temp = PORTC; + m_debugger_temp = m_port_data[PORTC]; break; case PIC16C5x_PRTD: - m_debugger_temp = PORTD; + m_debugger_temp = m_port_data[PORTD]; break; case PIC16C5x_FSR: - m_debugger_temp = FSR | u8(~m_data_mask); + m_debugger_temp = m_FSR | u8(~m_data_mask); break; } } @@ -1077,12 +1128,12 @@ void pic16c5x_device::state_string_export(const device_state_entry &entry, std:: case STATE_GENFLAGS: str = string_format("%01x%c%c%c%c%c %c%c%c%03x", - (STATUS & 0xe0) >> 5, - STATUS & 0x10 ? '.':'O', // WDT Overflow - STATUS & 0x08 ? 'P':'D', // Power/Down - STATUS & 0x04 ? 'Z':'.', // Zero - STATUS & 0x02 ? 'c':'b', // Nibble Carry/Borrow - STATUS & 0x01 ? 'C':'B', // Carry/Borrow + (m_STATUS & 0xe0) >> 5, + m_STATUS & 0x10 ? '.':'O', // WDT Overflow + m_STATUS & 0x08 ? 'P':'D', // Power/Down + m_STATUS & 0x04 ? 'Z':'.', // Zero + m_STATUS & 0x02 ? 'c':'b', // Nibble Carry/Borrow + m_STATUS & 0x01 ? 'C':'B', // Carry/Borrow m_OPTION & 0x20 ? 'C':'T', // Counter/Timer m_OPTION & 0x10 ? 'N':'P', // Negative/Positive @@ -1100,9 +1151,9 @@ void pic16c5x_device::state_string_export(const device_state_entry &entry, std:: void pic16c5x_device::reset_regs() { m_CONFIG = m_temp_config; - m_TRISA = 0xff; - m_TRISB = 0xff; - m_TRISC = 0xff; + m_port_tris[PORTA] = 0xff; + m_port_tris[PORTB] = 0xff; + m_port_tris[PORTC] = 0xff; m_OPTION = T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG; set_pc(m_program_mask); m_PREVPC = m_PC; @@ -1115,7 +1166,7 @@ void pic16c5x_device::reset_regs() void pic16c5x_device::watchdog_reset() { - SET(STATUS, TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG); + SET(m_STATUS, TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG); reset_regs(); } @@ -1129,10 +1180,10 @@ void pic16c5x_device::set_config(u16 data) void pic16c5x_device::device_reset() { reset_regs(); - CLR(STATUS, PA_REG); - SET(STATUS, TO_FLAG | PD_FLAG); - store_regfile(3, STATUS); - store_regfile(4, FSR); + CLR(m_STATUS, PA_REG); + SET(m_STATUS, TO_FLAG | PD_FLAG); + store_regfile(3, m_STATUS); + store_regfile(4, m_FSR); } @@ -1151,7 +1202,7 @@ void pic16c5x_device::update_watchdog(int counts) If the current instruction is CLRWDT or SLEEP, don't update the WDT */ - if ((m_opcode.w.l != 3) && (m_opcode.w.l != 4)) { + if ((m_opcode.w != 3) && (m_opcode.w != 4)) { u16 old_WDT = m_WDT; m_WDT -= counts; @@ -1165,12 +1216,12 @@ void pic16c5x_device::update_watchdog(int counts) m_prescaler++; if (m_prescaler >= (1 << PS)) { // Prescale values from 1 to 128 m_prescaler = 0; - CLR(STATUS, TO_FLAG); + CLR(m_STATUS, TO_FLAG); watchdog_reset(); } } else { - CLR(STATUS, TO_FLAG); + CLR(m_STATUS, TO_FLAG); watchdog_reset(); } } @@ -1196,12 +1247,12 @@ void pic16c5x_device::update_timer(int counts) if (PSA == 0) { m_prescaler += counts; if (m_prescaler >= (2 << PS)) { // Prescale values from 2 to 256 - TMR0 += (m_prescaler / (2 << PS)); + m_TMR0 += (m_prescaler / (2 << PS)); m_prescaler %= (2 << PS); // Overflow prescaler } } else { - TMR0 += counts; + m_TMR0 += counts; } } @@ -1230,8 +1281,6 @@ void pic16c5x_device::execute_set_input(int line, int state) void pic16c5x_device::execute_run() { - update_internalram_ptr(); - do { if (PD == 0) { // Sleep Mode m_count_cycles = 0; @@ -1243,12 +1292,12 @@ void pic16c5x_device::execute_run() debugger_instruction_hook(m_PC); - m_opcode.d = m_program.read_word(m_PC); + m_opcode.w = m_program.read_word(m_PC); set_pc(m_PC + 1); - if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655 || (m_opcode.w.l & 0xff0) != 0x000) { // Do all opcodes except the 00? ones - m_inst_cycles = s_opcode_main[((m_opcode.w.l >> 4) & 0xff)].cycles; - (this->*s_opcode_main[((m_opcode.w.l >> 4) & 0xff)].function)(); + if (m_picmodel == 0x1650 || m_picmodel == 0x1654 || m_picmodel == 0x1655 || (m_opcode.w & 0xff0) != 0x000) { // Do all opcodes except the 00? ones + m_inst_cycles = s_opcode_main[((m_opcode.w >> 4) & 0xff)].cycles; + (this->*s_opcode_main[((m_opcode.w >> 4) & 0xff)].function)(); } else { // Opcode 0x00? has many opcodes in its minor nibble m_inst_cycles = s_opcode_00x[(m_opcode.b.l & 0x1f)].cycles; diff --git a/src/devices/cpu/pic16c5x/pic16c5x.h b/src/devices/cpu/pic16c5x/pic16c5x.h index e4d25f6211f..e7a294df593 100644 --- a/src/devices/cpu/pic16c5x/pic16c5x.h +++ b/src/devices/cpu/pic16c5x/pic16c5x.h @@ -24,15 +24,6 @@ enum #define PIC16C5x_T0CKI PIC16C5x_RTCC -// i/o ports -enum -{ - PIC16C5x_PORTA = 0, - PIC16C5x_PORTB, - PIC16C5x_PORTC, - PIC16C5x_PORTD -}; - DECLARE_DEVICE_TYPE(PIC16C54, pic16c54_device) DECLARE_DEVICE_TYPE(PIC16C55, pic16c55_device) DECLARE_DEVICE_TYPE(PIC16C56, pic16c56_device) @@ -46,22 +37,31 @@ DECLARE_DEVICE_TYPE(PIC1655, pic1655_device) class pic16c5x_device : public cpu_device { + // i/o ports + enum + { + PORTA = 0, + PORTB, + PORTC, + PORTD + }; + public: // port a, 4 or 8 bits, 2-way - auto read_a() { return m_read_a.bind(); } - auto write_a() { return m_write_a.bind(); } + auto read_a() { return m_read_port[PORTA].bind(); } + auto write_a() { return m_write_port[PORTA].bind(); } // port b, 8 bits, 2-way - auto read_b() { return m_read_b.bind(); } - auto write_b() { return m_write_b.bind(); } + auto read_b() { return m_read_port[PORTB].bind(); } + auto write_b() { return m_write_port[PORTB].bind(); } // port c, 8 bits, 2-way - auto read_c() { return m_read_c.bind(); } - auto write_c() { return m_write_c.bind(); } + auto read_c() { return m_read_port[PORTC].bind(); } + auto write_c() { return m_write_port[PORTC].bind(); } // port d, 8 bits, 2-way - auto read_d() { return m_read_d.bind(); } - auto write_d() { return m_write_d.bind(); } + auto read_d() { return m_read_port[PORTD].bind(); } + auto write_d() { return m_write_port[PORTD].bind(); } /**************************************************************************** * Function to configure the CONFIG register. This is actually hard-wired @@ -70,15 +70,20 @@ public: */ void set_config(u16 data); - void ram_5(address_map &map); - void ram_7(address_map &map); + void core_regs(address_map &map, u8 mirror = 0); + void ram_5_2ports(address_map &map); + void ram_5_3ports(address_map &map); + void ram_1655_3ports(address_map &map); + void ram_5_4ports(address_map &map); + void ram_7_2ports(address_map &map); + void ram_7_3ports(address_map &map); void rom_10(address_map &map); void rom_11(address_map &map); void rom_9(address_map &map); protected: // construction/destruction - pic16c5x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int program_width, int data_width, int picmodel); + pic16c5x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int program_width, int data_width, int picmodel, address_map_constructor data_map); // device-level overrides virtual void device_start() override; @@ -124,13 +129,14 @@ private: u16 m_CONFIG; u8 m_ALU; u16 m_WDT; - u8 m_TRISA; - u8 m_TRISB; - u8 m_TRISC; + u8 m_TMR0; + u8 m_STATUS; + u8 m_FSR; + u8 m_port_data[4]; + u8 m_port_tris[3]; u16 m_STACK[2]; u16 m_prescaler; // Note: this is really an 8-bit register - PAIR m_opcode; - u8 *m_internalram; + PAIR16 m_opcode; int m_icount; int m_picmodel; @@ -149,14 +155,8 @@ private: memory_access< 7, 0, 0, ENDIANNESS_LITTLE>::specific m_data; // i/o handlers - devcb_read8 m_read_a; - devcb_read8 m_read_b; - devcb_read8 m_read_c; - devcb_read8 m_read_d; - devcb_write8 m_write_a; - devcb_write8 m_write_b; - devcb_write8 m_write_c; - devcb_write8 m_write_d; + devcb_read8::array<4> m_read_port; + devcb_write8::array<4> m_write_port; // For debugger int m_debugger_temp; @@ -171,16 +171,32 @@ private: static const pic16c5x_opcode s_opcode_main[256]; static const pic16c5x_opcode s_opcode_00x[16]; - void update_internalram_ptr(); void calc_zero_flag(); void calc_add_flags(u8 augend); void calc_sub_flags(u8 minuend); u16 pop_stack(); void push_stack(u16 data); - void set_pc(offs_t addr); - u8 get_regfile(offs_t addr); - void store_regfile(offs_t addr, u8 data); - void store_result(offs_t addr, u8 data); + void set_pc(u16 addr); + u8 get_regfile(u8 addr); + void store_regfile(u8 addr, u8 data); + void store_result(u8 addr, u8 data); + + u8 tmr0_r(); + void tmr0_w(u8 data); + u8 pcl_r(); + void pcl_w(u8 data); + u8 status_r(); + void status_w(u8 data); + u8 fsr_r(); + void fsr_w(u8 data); + u8 porta_r(); + void porta_w(u8 data); + u8 portb_r(); + void portb_w(u8 data); + u8 portc_r(); + void portc_w(u8 data); + u8 portd_r(); + void portd_w(u8 data); void reset_regs(); void watchdog_reset(); -- cgit v1.2.3