diff options
Diffstat (limited to 'src/devices/cpu/pic16c5x/pic16c5x.cpp')
-rw-r--r-- | src/devices/cpu/pic16c5x/pic16c5x.cpp | 633 |
1 files changed, 337 insertions, 296 deletions
diff --git a/src/devices/cpu/pic16c5x/pic16c5x.cpp b/src/devices/cpu/pic16c5x/pic16c5x.cpp index 5f2a02a23b6..1a4fc4dce00 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<util::disasm_interface> 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; + } 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); +} + +void pic16c5x_device::store_regfile(u8 addr, u8 data) // Write to internal memory +{ + if (addr == 0) { // Indirect addressing + addr = m_FSR; + } else if (m_data_width != 5) { + addr |= (m_FSR & 0x60); // FSR bits 6-5 are used for banking in direct mode } - if ((addr & 0x10) == 0) addr &= 0x0f; + m_data.write_byte(addr, data); +} - switch (addr) - { - case 0: - // Not an actual register, reading indirectly (FSR=0) returns 0 - data = 0; - break; - 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() +{ + // high bits are 1 + return m_FSR | u8(~m_data_mask); +} - 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) +{ + m_FSR = data & 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,14 +1035,20 @@ 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"); - state_add( PIC16C5x_FSR, "FSR", m_debugger_temp).mask(0xff).callimport().callexport().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(m_data_mask).formatstr("%02X"); state_add( PIC16C5x_PSCL, "PSCL", m_debugger_temp).callimport().formatstr("%3s"); state_add( STATE_GENPC, "GENPC", m_PC).noshow(); @@ -1013,25 +1064,22 @@ 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; - break; - case PIC16C5x_FSR: - FSR = m_debugger_temp | u8(~m_data_mask); + m_port_data[PORTD] = m_debugger_temp; break; case PIC16C5x_PSCL: m_prescaler = m_debugger_temp; @@ -1044,25 +1092,22 @@ 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; - break; - case PIC16C5x_FSR: - m_debugger_temp = FSR | u8(~m_data_mask); + m_debugger_temp = m_port_data[PORTD]; break; } } @@ -1077,16 +1122,16 @@ 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_OPTION & 0x20 ? 'C':'T', // Counter/Timer - m_OPTION & 0x10 ? 'N':'P', // Negative/Positive - m_OPTION & 0x08 ? 'W':'T', // WatchDog/Timer + (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 + m_OPTION & 0x08 ? 'W':'T', // WatchDog/Timer m_OPTION & 0x08 ? (1<<(m_OPTION&7)) : (2<<(m_OPTION&7))); break; } @@ -1100,9 +1145,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 +1160,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 +1174,8 @@ 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); } @@ -1151,7 +1194,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 +1208,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 +1239,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 +1273,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 +1284,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; |