summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/pic16c5x/pic16c5x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/pic16c5x/pic16c5x.cpp')
-rw-r--r--src/devices/cpu/pic16c5x/pic16c5x.cpp633
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;