summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/pic16c62x/pic16c62x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/pic16c62x/pic16c62x.cpp')
-rw-r--r--src/devices/cpu/pic16c62x/pic16c62x.cpp703
1 files changed, 392 insertions, 311 deletions
diff --git a/src/devices/cpu/pic16c62x/pic16c62x.cpp b/src/devices/cpu/pic16c62x/pic16c62x.cpp
index 166b26b731e..22914038a2d 100644
--- a/src/devices/cpu/pic16c62x/pic16c62x.cpp
+++ b/src/devices/cpu/pic16c62x/pic16c62x.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Tony La Porta
+// copyright-holders:Tony La Porta, Samuele Zannoli
/**************************************************************************\
* Microchip PIC16C62X Emulator *
* *
@@ -55,7 +55,6 @@
#include "emu.h"
#include "pic16c62x.h"
#include "16c62xdsm.h"
-#include "debugger.h"
DEFINE_DEVICE_TYPE(PIC16C620, pic16c620_device, "pic16c620", "Microchip PIC16C620")
@@ -86,86 +85,97 @@ void pic16c62x_device::pic16c62x_rom_11(address_map &map)
map(0x000, 0x7ff).rom();
}
+void pic16c62x_device::core_regs(address_map &map)
+{
+ map(0x01, 0x01).rw(FUNC(pic16c62x_device::tmr0_r), FUNC(pic16c62x_device::tmr0_w));
+ map(0x02, 0x02).mirror(0x80).rw(FUNC(pic16c62x_device::pcl_r), FUNC(pic16c62x_device::pcl_w));
+ map(0x03, 0x03).mirror(0x80).rw(FUNC(pic16c62x_device::status_r), FUNC(pic16c62x_device::status_w));
+ map(0x04, 0x04).mirror(0x80).rw(FUNC(pic16c62x_device::fsr_r), FUNC(pic16c62x_device::fsr_w));
+ map(0x05, 0x05).rw(FUNC(pic16c62x_device::porta_r), FUNC(pic16c62x_device::porta_w));
+ map(0x06, 0x06).rw(FUNC(pic16c62x_device::portb_r), FUNC(pic16c62x_device::portb_w));
+ map(0x0a, 0x0a).mirror(0x80).rw(FUNC(pic16c62x_device::pclath_r), FUNC(pic16c62x_device::pclath_w));
+ map(0x0b, 0x0b).mirror(0x80).rw(FUNC(pic16c62x_device::intcon_r), FUNC(pic16c62x_device::intcon_w));
+ map(0x0c, 0x0c).rw(FUNC(pic16c62x_device::pir1_r), FUNC(pic16c62x_device::pir1_w));
+ map(0x1f, 0x1f).rw(FUNC(pic16c62x_device::cmcon_r), FUNC(pic16c62x_device::cmcon_w));
+ map(0x81, 0x81).rw(FUNC(pic16c62x_device::option_r), FUNC(pic16c62x_device::option_w));
+ map(0x85, 0x85).rw(FUNC(pic16c62x_device::trisa_r), FUNC(pic16c62x_device::trisa_w));
+ map(0x86, 0x86).rw(FUNC(pic16c62x_device::trisb_r), FUNC(pic16c62x_device::trisb_w));
+ map(0x8c, 0x8c).rw(FUNC(pic16c62x_device::pie1_r), FUNC(pic16c62x_device::pie1_w));
+ map(0x8e, 0x8e).rw(FUNC(pic16c62x_device::pcon_r), FUNC(pic16c62x_device::pcon_w));
+ map(0x9f, 0x9f).rw(FUNC(pic16c62x_device::vrcon_r), FUNC(pic16c62x_device::vrcon_w));
+}
+
void pic16c62x_device::pic16c620_ram(address_map &map)
{
- map(0x00, 0x06).ram();
- map(0x0a, 0x0c).ram();
- map(0x1f, 0x6f).ram();
- map(0x80, 0x86).ram();
- map(0x8a, 0x8e).ram();
- map(0x9f, 0x9f).ram();
+ core_regs(map);
+ map(0x20, 0x6f).ram();
}
void pic16c62x_device::pic16c622_ram(address_map &map)
{
- map(0x00, 0x06).ram();
- map(0x0a, 0x0c).ram();
- map(0x1f, 0x7f).ram();
- map(0x80, 0x86).ram();
- map(0x8a, 0x8e).ram();
- map(0x9f, 0xbf).ram();
+ core_regs(map);
+ map(0x20, 0x7f).ram();
+ map(0xa0, 0xbf).ram();
+}
+
+void pic16c62x_device::pic16c620a_ram(address_map &map)
+{
+ core_regs(map);
+ map(0x20, 0x6f).ram();
+ map(0x70, 0x7f).mirror(0x80).ram();
}
-// pic16c620a, pic16c621a and pic16c622a
-void pic16c62x_device::pic16c62xa_ram(address_map &map)
+void pic16c62x_device::pic16c622a_ram(address_map &map)
{
- map(0x00, 0x06).ram();
- map(0x0a, 0x0c).ram();
- map(0x1f, 0x6f).ram();
- map(0x70, 0x7f).ram().share(nullptr);
- map(0x80, 0x86).ram();
- map(0x8a, 0x8e).ram();
- map(0x9f, 0xbf).ram();
- map(0xf0, 0xff).ram().share(nullptr);
+ core_regs(map);
+ map(0x20, 0x6f).ram();
+ map(0x70, 0x7f).mirror(0x80).ram();
+ map(0xa0, 0xbf).ram();
}
-pic16c62x_device::pic16c62x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int program_width, int picmodel)
+pic16c62x_device::pic16c62x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int program_width, address_map_constructor ram_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(pic16c62x_device::pic16c62x_rom_9), this) :
( ( program_width == 10 ) ? address_map_constructor(FUNC(pic16c62x_device::pic16c62x_rom_10), this) :
address_map_constructor(FUNC(pic16c62x_device::pic16c62x_rom_11), this) )))
- , m_data_config("data", ENDIANNESS_LITTLE, 8, 8, 0
- , ( ( picmodel == 0x16C620 || picmodel == 0x16C621 ) ? address_map_constructor(FUNC(pic16c62x_device::pic16c620_ram), this) :
- ( ( picmodel == 0x16C622 ) ? address_map_constructor(FUNC(pic16c62x_device::pic16c622_ram), this) :
- address_map_constructor(FUNC(pic16c62x_device::pic16c62xa_ram), this) ) ) )
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 5, 0)
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, 8, 0, ram_map)
, m_CONFIG(0x3fff)
, m_reset_vector(0x0)
- , m_picmodel(picmodel)
- , m_picRAMmask(0xff)
+ , m_read_port(*this, 0)
+ , m_write_port(*this)
{
}
pic16c620_device::pic16c620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C620, tag, owner, clock, 9, 0x16C620)
+ : pic16c62x_device(mconfig, PIC16C620, tag, owner, clock, 9, address_map_constructor(FUNC(pic16c620_device::pic16c620_ram), this))
{
}
pic16c620a_device::pic16c620a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C620A, tag, owner, clock, 9, 0x16C620A)
+ : pic16c62x_device(mconfig, PIC16C620A, tag, owner, clock, 9, address_map_constructor(FUNC(pic16c620a_device::pic16c620a_ram), this))
{
}
pic16c621_device::pic16c621_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C621, tag, owner, clock, 10, 0x16C621)
+ : pic16c62x_device(mconfig, PIC16C621, tag, owner, clock, 10, address_map_constructor(FUNC(pic16c621_device::pic16c620_ram), this))
{
}
pic16c621a_device::pic16c621a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C621A, tag, owner, clock, 10, 0x16C621A)
+ : pic16c62x_device(mconfig, PIC16C621A, tag, owner, clock, 10, address_map_constructor(FUNC(pic16c621a_device::pic16c620a_ram), this))
{
}
pic16c622_device::pic16c622_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C622, tag, owner, clock, 11, 0x16C622)
+ : pic16c62x_device(mconfig, PIC16C622, tag, owner, clock, 11, address_map_constructor(FUNC(pic16c622_device::pic16c622_ram), this))
{
}
pic16c622a_device::pic16c622a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c62x_device(mconfig, PIC16C622A, tag, owner, clock, 11, 0x16C622A)
+ : pic16c62x_device(mconfig, PIC16C622A, tag, owner, clock, 11, address_map_constructor(FUNC(pic16c622a_device::pic16c622a_ram), this))
{
}
@@ -174,8 +184,7 @@ device_memory_interface::space_config_vector pic16c62x_device::memory_space_conf
{
return space_config_vector{
std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_DATA, &m_data_config),
- std::make_pair(AS_IO, &m_io_config)
+ std::make_pair(AS_DATA, &m_data_config)
};
}
@@ -185,37 +194,16 @@ std::unique_ptr<util::disasm_interface> pic16c62x_device::create_disassembler()
}
-void pic16c62x_device::update_internalram_ptr()
-{
- m_internalram = (uint8_t *)m_data.space().get_write_ptr(0x00);
-}
-
#define PIC16C62x_RDOP(A) (m_cache.read_word(A))
-#define PIC16C62x_RAM_RDMEM(A) ((uint8_t)m_data.read_byte(A))
-#define PIC16C62x_RAM_WRMEM(A,V) (m_data.write_byte(A,V))
-#define PIC16C62x_In(Port) ((uint8_t)m_io.read_byte((Port)))
-#define PIC16C62x_Out(Port,Value) (m_io.write_byte((Port),Value))
/************ Read the state of the T0 Clock input signal ************/
-#define PIC16C62x_T0_In (m_io.read_byte(PIC16C62x_T0) >> 4)
+#define PIC16C62x_T0_In ((porta_r() >> 4) & 1)
-#define M_RDRAM(A) (((A) == 0) ? m_internalram[0] : PIC16C62x_RAM_RDMEM(A))
-#define M_WRTRAM(A,V) do { if ((A) == 0) m_internalram[0] = (V); else PIC16C62x_RAM_WRMEM(A,V); } while (0)
#define M_RDOP(A) PIC16C62x_RDOP(A)
-#define P_IN(A) PIC16C62x_In(A)
-#define P_OUT(A,V) PIC16C62x_Out(A,V)
#define S_T0_IN PIC16C62x_T0_In
#define ADDR_MASK 0x1fff
-#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 INDF M_RDRAM(FSR)
-
#define RISING_EDGE_T0 (( (int)(T0_in - m_old_T0) > 0) ? 1 : 0)
#define FALLING_EDGE_T0 (( (int)(T0_in - m_old_T0) < 0) ? 1 : 0)
@@ -232,14 +220,14 @@ void pic16c62x_device::update_internalram_ptr()
#define DC_FLAG 0x02 /* DC Digit Carry/Borrow flag (Nibble) */
#define C_FLAG 0x01 /* C Carry/Borrow Flag (Byte) */
-#define IRP (STATUS & IRP_FLAG)
-#define RP1 (STATUS & RP1_FLAG)
-#define RP0 (STATUS & RP0_FLAG)
-#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 IRP (m_STATUS & IRP_FLAG)
+#define RP1 (m_STATUS & RP1_FLAG)
+#define RP0 (m_STATUS & RP0_FLAG)
+#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)
#define ADDR ((m_opcode.b.l & 0x7f) | (RP0 << 2))
@@ -280,55 +268,53 @@ void pic16c62x_device::update_internalram_ptr()
/* Easy bit position selectors */
-#define POS ((m_opcode.w.l >> 7) & 7)
-static const unsigned int bit_clr[8] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
-static const unsigned int bit_set[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+#define POS ((m_opcode.w >> 7) & 7)
void pic16c62x_device::CALCULATE_Z_FLAG()
{
- if (m_ALU == 0) SET(STATUS, Z_FLAG);
- else CLR(STATUS, Z_FLAG);
+ if (m_ALU == 0) SET(m_STATUS, Z_FLAG);
+ else CLR(m_STATUS, Z_FLAG);
}
void pic16c62x_device::CALCULATE_ADD_CARRY()
{
if ((uint8_t)(m_old_data) > (uint8_t)(m_ALU)) {
- SET(STATUS, C_FLAG);
+ SET(m_STATUS, C_FLAG);
}
else {
- CLR(STATUS, C_FLAG);
+ CLR(m_STATUS, C_FLAG);
}
}
void pic16c62x_device::CALCULATE_ADD_DIGITCARRY()
{
if (((uint8_t)(m_old_data) & 0x0f) > ((uint8_t)(m_ALU) & 0x0f)) {
- SET(STATUS, DC_FLAG);
+ SET(m_STATUS, DC_FLAG);
}
else {
- CLR(STATUS, DC_FLAG);
+ CLR(m_STATUS, DC_FLAG);
}
}
void pic16c62x_device::CALCULATE_SUB_CARRY()
{
if ((uint8_t)(m_old_data) < (uint8_t)(m_ALU)) {
- CLR(STATUS, C_FLAG);
+ CLR(m_STATUS, C_FLAG);
}
else {
- SET(STATUS, C_FLAG);
+ SET(m_STATUS, C_FLAG);
}
}
void pic16c62x_device::CALCULATE_SUB_DIGITCARRY()
{
if (((uint8_t)(m_old_data) & 0x0f) < ((uint8_t)(m_ALU) & 0x0f)) {
- CLR(STATUS, DC_FLAG);
+ CLR(m_STATUS, DC_FLAG);
}
else {
- SET(STATUS, DC_FLAG);
+ SET(m_STATUS, DC_FLAG);
}
}
@@ -360,119 +346,26 @@ void pic16c62x_device::PUSH_STACK(uint16_t data)
-uint8_t pic16c62x_device::GET_REGFILE(offs_t addr) /* Read from internal memory */
+uint8_t pic16c62x_device::GET_REGFILE(uint8_t addr) /* Read from internal memory */
{
- uint8_t data;
-
- if (addr == 0) { /* Indirect addressing */
- addr = (FSR & m_picRAMmask);
+ if ((addr & 0x7f) == 0) { /* Indirect addressing */
+ addr = m_FSR;
}
- switch(addr)
- {
- case 0x00: /* Not an actual register, so return 0 */
- case 0x80:
- data = 0;
- break;
- case 0x02:
- case 0x03:
- case 0x0b:
- case 0x82:
- case 0x83:
- case 0x8b:
- data = M_RDRAM(addr & 0x7f);
- break;
- case 0x84:
- case 0x04: data = (FSR | (uint8_t)(~m_picRAMmask));
- break;
- case 0x05: data = P_IN(0);
- data &= m_TRISA;
- data |= ((uint8_t)(~m_TRISA) & PORTA);
- data &= 0x1f; /* 5-bit port (only lower 5 bits used) */
- break;
- case 0x06: data = P_IN(1);
- data &= m_TRISB;
- data |= ((uint8_t)(~m_TRISB) & PORTB);
- break;
- case 0x8a:
- case 0x0a: data = m_PCLATH;
- break;
- case 0x81: data = m_OPTION;
- break;
- case 0x85: data = m_TRISA;
- break;
- case 0x86: data = m_TRISB;
- break;
- default: data = M_RDRAM(addr);
- break;
- }
- return data;
+ return m_data.read_byte(addr);
}
-void pic16c62x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to internal memory */
+void pic16c62x_device::STORE_REGFILE(uint8_t addr, uint8_t data) /* Write to internal memory */
{
- if (addr == 0) { /* Indirect addressing */
- addr = (FSR & m_picRAMmask);
+ if ((addr & 0x7f) == 0) { /* Indirect addressing */
+ addr = m_FSR;
}
- switch(addr)
- {
- case 0x80:
- case 0x00: /* Not an actual register, nothing to save */
- break;
- case 0x01: m_delay_timer = 2; /* Timer starts after next two instructions */
- if (PSA == 0) m_prescaler = 0; /* Must clear the Prescaler */
- TMR0 = data;
- break;
- case 0x82:
- case 0x02: PCL = data;
- m_PC = (m_PCLATH << 8) | data;
- break;
- case 0x83:
- case 0x03: STATUS &= (uint8_t)(~(IRP_FLAG|RP1_FLAG|RP0_FLAG)); STATUS |= (data & (IRP_FLAG|RP1_FLAG|RP0_FLAG));
- break;
- case 0x84:
- case 0x04: FSR = (data | (uint8_t)(~m_picRAMmask));
- break;
- case 0x05: data &= 0x1f; /* 5-bit port (only lower 5 bits used) */
- P_OUT(0,data & (uint8_t)(~m_TRISA)); PORTA = data;
- break;
- case 0x06: P_OUT(1,data & (uint8_t)(~m_TRISB)); PORTB = data;
- break;
- case 0x8a:
- case 0x0a:
- m_PCLATH = data & 0x1f;
- M_WRTRAM(0x0a, m_PCLATH);
- break;
- case 0x8b:
- case 0x0b: M_WRTRAM(0x0b, data);
- break;
- case 0x81: m_OPTION = data;
- M_WRTRAM(0x81, data);
- break;
- case 0x85: if (m_TRISA != data)
- {
- m_TRISA = data | 0xf0;
- P_OUT(2,m_TRISA);
- P_OUT(0,PORTA & (uint8_t)(~m_TRISA) & 0x0f);
- M_WRTRAM(addr, data);
- }
- break;
- case 0x86: if (m_TRISB != data)
- {
- m_TRISB = data;
- P_OUT(3,m_TRISB);
- P_OUT(1,PORTB & (uint8_t)(~m_TRISB));
- M_WRTRAM(addr, data);
- }
- break;
- default: M_WRTRAM(addr, data);
- break;
- }
+ m_data.write_byte(addr, data);
}
-void pic16c62x_device::STORE_RESULT(offs_t addr, uint8_t data)
+void pic16c62x_device::STORE_RESULT(uint8_t addr, uint8_t data)
{
if (m_opcode.b.l & 0x80)
{
@@ -485,6 +378,190 @@ void pic16c62x_device::STORE_RESULT(offs_t addr, uint8_t data)
}
+uint8_t pic16c62x_device::tmr0_r()
+{
+ return m_TMR0;
+}
+
+void pic16c62x_device::tmr0_w(uint8_t data)
+{
+ m_delay_timer = 2; /* Timer starts after next two instructions */
+ if (PSA == 0) m_prescaler = 0; /* Must clear the Prescaler */
+ m_TMR0 = data;
+}
+
+uint8_t pic16c62x_device::pcl_r()
+{
+ return m_PC & 0xff;
+}
+
+void pic16c62x_device::pcl_w(uint8_t data)
+{
+ m_PC = (m_PCLATH << 8) | data;
+}
+
+uint8_t pic16c62x_device::status_r()
+{
+ return m_STATUS;
+}
+
+void pic16c62x_device::status_w(uint8_t data)
+{
+ m_STATUS &= (uint8_t)(~(IRP_FLAG|RP1_FLAG|RP0_FLAG));
+ m_STATUS |= (data & (IRP_FLAG|RP1_FLAG|RP0_FLAG));
+}
+
+uint8_t pic16c62x_device::fsr_r()
+{
+ return m_FSR;
+}
+
+void pic16c62x_device::fsr_w(uint8_t data)
+{
+ m_FSR = data;
+}
+
+uint8_t pic16c62x_device::porta_r()
+{
+ uint8_t data = m_read_port[0](0, ~m_port_tris[0]);
+ data &= m_port_tris[0];
+ data |= ((uint8_t)(~m_port_tris[0]) & m_port_data[0]);
+ return data & 0x1f; /* 5-bit port (only lower 5 bits used) */
+}
+
+void pic16c62x_device::porta_w(uint8_t data)
+{
+ data &= 0x1f; /* 5-bit port (only lower 5 bits used) */
+ m_write_port[0](0, data & (~m_port_tris[0]), ~m_port_tris[0]);
+ m_port_data[0] = data;
+}
+
+uint8_t pic16c62x_device::portb_r()
+{
+ uint8_t data = m_read_port[1](0, ~m_port_tris[1]);
+ data &= m_port_tris[1];
+ data |= ((uint8_t)(~m_port_tris[1]) & m_port_data[1]);
+ return data;
+}
+
+void pic16c62x_device::portb_w(uint8_t data)
+{
+ m_write_port[1](0, data & (~m_port_tris[1]), ~m_port_tris[1]);
+ m_port_data[1] = data;
+}
+
+uint8_t pic16c62x_device::pclath_r()
+{
+ return m_PCLATH;
+}
+
+void pic16c62x_device::pclath_w(uint8_t data)
+{
+ m_PCLATH = data & 0x1f;
+}
+
+uint8_t pic16c62x_device::intcon_r()
+{
+ return m_INTCON;
+}
+
+void pic16c62x_device::intcon_w(uint8_t data)
+{
+ m_INTCON = data;
+}
+
+uint8_t pic16c62x_device::option_r()
+{
+ return m_OPTION;
+}
+
+void pic16c62x_device::option_w(uint8_t data)
+{
+ m_OPTION = data;
+}
+
+uint8_t pic16c62x_device::trisa_r()
+{
+ return m_port_tris[0];
+}
+
+void pic16c62x_device::trisa_w(uint8_t data)
+{
+ data &= 0x1f;
+ if (m_port_tris[0] != data)
+ {
+ m_port_tris[0] = data;
+ m_write_port[0](0, m_port_data[0] & (~m_port_tris[0]), ~m_port_tris[0] & 0x1f);
+ }
+}
+
+uint8_t pic16c62x_device::trisb_r()
+{
+ return m_port_tris[1];
+}
+
+void pic16c62x_device::trisb_w(uint8_t data)
+{
+ if (m_port_tris[1] != data)
+ {
+ m_port_tris[1] = data;
+ m_write_port[1](0, m_port_data[1] & (~m_port_tris[1]), ~m_port_tris[1]);
+ }
+}
+
+uint8_t pic16c62x_device::pir1_r()
+{
+ return m_PIR1;
+}
+
+void pic16c62x_device::pir1_w(uint8_t data)
+{
+ // Only CMIF is implemented
+ m_PIR1 = data & 0x40;
+}
+
+uint8_t pic16c62x_device::pie1_r()
+{
+ return m_PIE1;
+}
+
+void pic16c62x_device::pie1_w(uint8_t data)
+{
+ // Only CMIE is implemented
+ m_PIE1 = data & 0x40;
+}
+
+uint8_t pic16c62x_device::pcon_r()
+{
+ return m_PCON;
+}
+
+void pic16c62x_device::pcon_w(uint8_t data)
+{
+ m_PCON = data & 0x03;
+}
+
+uint8_t pic16c62x_device::cmcon_r()
+{
+ // TODO: C1OUT, C2OUT
+ return m_CMCON;
+}
+
+void pic16c62x_device::cmcon_w(uint8_t data)
+{
+ m_CMCON = data & 0x0f;
+}
+
+uint8_t pic16c62x_device::vrcon_r()
+{
+ return m_VRCON;
+}
+
+void pic16c62x_device::vrcon_w(uint8_t data)
+{
+ m_VRCON = data & 0xef;
+}
+
/************************************************************************
* Emulate the Instructions
************************************************************************/
@@ -495,7 +572,7 @@ void pic16c62x_device::STORE_RESULT(offs_t addr, uint8_t data)
void pic16c62x_device::illegal()
{
- logerror("PIC16C62x: PC=%03x, Illegal opcode = %04x\n", (m_PC-1), m_opcode.w.l);
+ logerror("PIC16C62x: PC=%03x, Illegal opcode = %04x\n", (m_PC-1), m_opcode.w);
}
@@ -535,33 +612,31 @@ void pic16c62x_device::andlw()
void pic16c62x_device::bcf()
{
m_ALU = GET_REGFILE(ADDR);
- m_ALU &= bit_clr[POS];
+ m_ALU &= ~(1 << POS);
STORE_REGFILE(ADDR, m_ALU);
}
void pic16c62x_device::bsf()
{
m_ALU = GET_REGFILE(ADDR);
- m_ALU |= bit_set[POS];
+ m_ALU |= 1 << POS;
STORE_REGFILE(ADDR, m_ALU);
}
void pic16c62x_device::btfss()
{
- if ((GET_REGFILE(ADDR) & bit_set[POS]) == bit_set[POS])
+ if ((GET_REGFILE(ADDR) & (1 << POS)) != 0)
{
m_PC++;
- PCL = m_PC & 0xff;
m_inst_cycles += 1; /* Add NOP cycles */
}
}
void pic16c62x_device::btfsc()
{
- if ((GET_REGFILE(ADDR) & bit_set[POS]) == 0)
+ if ((GET_REGFILE(ADDR) & (1 << POS)) == 0)
{
m_PC++;
- PCL = m_PC & 0xff;
m_inst_cycles += 1; /* Add NOP cycles */
}
}
@@ -569,29 +644,28 @@ void pic16c62x_device::btfsc()
void pic16c62x_device::call()
{
PUSH_STACK(m_PC);
- m_PC = ((m_PCLATH & 0x18) << 8) | (m_opcode.w.l & 0x7ff);
+ m_PC = ((m_PCLATH & 0x18) << 8) | (m_opcode.w & 0x7ff);
m_PC &= ADDR_MASK;
- PCL = m_PC & 0xff;
}
void pic16c62x_device::clrw()
{
m_W = 0;
- SET(STATUS, Z_FLAG);
+ SET(m_STATUS, Z_FLAG);
}
void pic16c62x_device::clrf()
{
STORE_REGFILE(ADDR, 0);
- SET(STATUS, Z_FLAG);
+ SET(m_STATUS, Z_FLAG);
}
void pic16c62x_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 pic16c62x_device::comf()
@@ -615,16 +689,14 @@ void pic16c62x_device::decfsz()
if (m_ALU == 0)
{
m_PC++;
- PCL = m_PC & 0xff;
m_inst_cycles += 1; /* Add NOP cycles */
}
}
void pic16c62x_device::goto_op()
{
- m_PC = ((m_PCLATH & 0x18) << 8) | (m_opcode.w.l & 0x7ff);
+ m_PC = ((m_PCLATH & 0x18) << 8) | (m_opcode.w & 0x7ff);
m_PC &= ADDR_MASK;
- PCL = m_PC & 0xff;
}
void pic16c62x_device::incf()
@@ -641,7 +713,6 @@ void pic16c62x_device::incfsz()
if (m_ALU == 0)
{
m_PC++;
- PCL = m_PC & 0xff;
m_inst_cycles += 1; /* Add NOP cycles */
}
}
@@ -691,39 +762,36 @@ void pic16c62x_device::retlw()
{
m_W = m_opcode.b.l;
m_PC = POP_STACK();
- PCL = m_PC & 0xff;
}
void pic16c62x_device::returns()
{
m_PC = POP_STACK();
- PCL = m_PC & 0xff;
}
void pic16c62x_device::retfie()
{
m_PC = POP_STACK();
- PCL = m_PC & 0xff;
//INTCON(7)=1;
}
void pic16c62x_device::rlf()
{
- m_ALU = GET_REGFILE(ADDR);
- m_ALU <<= 1;
- if (STATUS & C_FLAG) m_ALU |= 1;
- if (GET_REGFILE(ADDR) & 0x80) SET(STATUS, C_FLAG);
- else CLR(STATUS, C_FLAG);
+ m_old_data = GET_REGFILE(ADDR);
+ m_ALU = m_old_data << 1;
+ if (m_STATUS & C_FLAG) m_ALU |= 1;
+ if (m_old_data & 0x80) SET(m_STATUS, C_FLAG);
+ else CLR(m_STATUS, C_FLAG);
STORE_RESULT(ADDR, m_ALU);
}
void pic16c62x_device::rrf()
{
- m_ALU = GET_REGFILE(ADDR);
- m_ALU >>= 1;
- if (STATUS & C_FLAG) m_ALU |= 0x80;
- if (GET_REGFILE(ADDR) & 1) SET(STATUS, C_FLAG);
- else CLR(STATUS, C_FLAG);
+ m_old_data = GET_REGFILE(ADDR);
+ m_ALU = m_old_data >> 1;
+ if (m_STATUS & C_FLAG) m_ALU |= 0x80;
+ if (m_old_data & 1) SET(m_STATUS, C_FLAG);
+ else CLR(m_STATUS, C_FLAG);
STORE_RESULT(ADDR, m_ALU);
}
@@ -731,8 +799,8 @@ void pic16c62x_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 pic16c62x_device::subwf()
@@ -747,7 +815,8 @@ void pic16c62x_device::subwf()
void pic16c62x_device::sublw()
{
- m_ALU = (m_opcode.b.l & 0xff) - m_W;
+ m_old_data = m_opcode.b.l;
+ m_ALU = m_old_data - m_W;
m_W = m_ALU;
CALCULATE_Z_FLAG();
CALCULATE_SUB_CARRY();
@@ -756,8 +825,8 @@ void pic16c62x_device::sublw()
void pic16c62x_device::swapf()
{
- m_ALU = ((GET_REGFILE(ADDR) << 4) & 0xf0);
- m_ALU |= ((GET_REGFILE(ADDR) >> 4) & 0x0f);
+ m_ALU = GET_REGFILE(ADDR);
+ m_ALU = (m_ALU << 4) | (m_ALU >> 4);
STORE_RESULT(ADDR, m_ALU);
}
@@ -765,8 +834,8 @@ void pic16c62x_device::tris()
{
switch(m_opcode.b.l & 0x7)
{
- case 5: STORE_REGFILE(0x85, m_W); break;
- case 6: STORE_REGFILE(0x86, m_W); break;
+ case 5: m_data.write_byte(0x85, m_W); break;
+ case 6: m_data.write_byte(0x86, m_W); break;
default: illegal(); break;
}
}
@@ -792,43 +861,43 @@ void pic16c62x_device::xorwf()
const pic16c62x_device::pic16c62x_instruction pic16c62x_device::s_instructiontable[]=
{
- {(char *)"000111dfffffff", &pic16c62x_device::addwf, 1},
- {(char *)"000101dfffffff", &pic16c62x_device::andwf, 1},
- {(char *)"0000011fffffff", &pic16c62x_device::clrf, 1},
- {(char *)"00000100000011", &pic16c62x_device::clrw, 1},
- {(char *)"001001dfffffff", &pic16c62x_device::comf, 1},
- {(char *)"000011dfffffff", &pic16c62x_device::decf, 1},
- {(char *)"001011dfffffff", &pic16c62x_device::decfsz, 1},
- {(char *)"001010dfffffff", &pic16c62x_device::incf, 1},
- {(char *)"001111dfffffff", &pic16c62x_device::incfsz, 1},
- {(char *)"000100dfffffff", &pic16c62x_device::iorwf, 1},
- {(char *)"001000dfffffff", &pic16c62x_device::movf, 1},
- {(char *)"0000001fffffff", &pic16c62x_device::movwf, 1},
- {(char *)"0000000xx00000", &pic16c62x_device::nop, 1},
- {(char *)"001101dfffffff", &pic16c62x_device::rlf, 1},
- {(char *)"001100dfffffff", &pic16c62x_device::rrf, 1},
- {(char *)"000010dfffffff", &pic16c62x_device::subwf, 1},
- {(char *)"001110dfffffff", &pic16c62x_device::swapf, 1},
- {(char *)"000110dfffffff", &pic16c62x_device::xorwf, 1},
- {(char *)"0100bbbfffffff", &pic16c62x_device::bcf, 1},
- {(char *)"0101bbbfffffff", &pic16c62x_device::bsf, 1},
- {(char *)"0110bbbfffffff", &pic16c62x_device::btfsc, 1},
- {(char *)"0111bbbfffffff", &pic16c62x_device::btfss, 1},
- {(char *)"11111xkkkkkkkk", &pic16c62x_device::addlw, 1},
- {(char *)"111001kkkkkkkk", &pic16c62x_device::andlw, 1},
- {(char *)"100aaaaaaaaaaa", &pic16c62x_device::call, 2},
- {(char *)"101aaaaaaaaaaa", &pic16c62x_device::goto_op, 2},
- {(char *)"111000kkkkkkkk", &pic16c62x_device::iorlw, 1},
- {(char *)"1100xxkkkkkkkk", &pic16c62x_device::movlw, 1},
- {(char *)"00000000001001", &pic16c62x_device::retfie, 2},
- {(char *)"1101xxkkkkkkkk", &pic16c62x_device::retlw, 2},
- {(char *)"00000000001000", &pic16c62x_device::returns, 2},
- {(char *)"00000001100011", &pic16c62x_device::sleepic, 1},
- {(char *)"11110xkkkkkkkk", &pic16c62x_device::sublw, 1},
- {(char *)"111010kkkkkkkk", &pic16c62x_device::xorlw, 1},
- {(char *)"00000001100100", &pic16c62x_device::clrwdt, 1},
- {(char *)"00000001100010", &pic16c62x_device::option, 1}, // deprecated
- {(char *)"00000001100fff", &pic16c62x_device::tris, 1}, // deprecated
+ {"000111dfffffff", &pic16c62x_device::addwf, 1},
+ {"000101dfffffff", &pic16c62x_device::andwf, 1},
+ {"0000011fffffff", &pic16c62x_device::clrf, 1},
+ {"00000100000011", &pic16c62x_device::clrw, 1},
+ {"001001dfffffff", &pic16c62x_device::comf, 1},
+ {"000011dfffffff", &pic16c62x_device::decf, 1},
+ {"001011dfffffff", &pic16c62x_device::decfsz, 1},
+ {"001010dfffffff", &pic16c62x_device::incf, 1},
+ {"001111dfffffff", &pic16c62x_device::incfsz, 1},
+ {"000100dfffffff", &pic16c62x_device::iorwf, 1},
+ {"001000dfffffff", &pic16c62x_device::movf, 1},
+ {"0000001fffffff", &pic16c62x_device::movwf, 1},
+ {"0000000xx00000", &pic16c62x_device::nop, 1},
+ {"001101dfffffff", &pic16c62x_device::rlf, 1},
+ {"001100dfffffff", &pic16c62x_device::rrf, 1},
+ {"000010dfffffff", &pic16c62x_device::subwf, 1},
+ {"001110dfffffff", &pic16c62x_device::swapf, 1},
+ {"000110dfffffff", &pic16c62x_device::xorwf, 1},
+ {"0100bbbfffffff", &pic16c62x_device::bcf, 1},
+ {"0101bbbfffffff", &pic16c62x_device::bsf, 1},
+ {"0110bbbfffffff", &pic16c62x_device::btfsc, 1},
+ {"0111bbbfffffff", &pic16c62x_device::btfss, 1},
+ {"11111xkkkkkkkk", &pic16c62x_device::addlw, 1},
+ {"111001kkkkkkkk", &pic16c62x_device::andlw, 1},
+ {"100aaaaaaaaaaa", &pic16c62x_device::call, 2},
+ {"101aaaaaaaaaaa", &pic16c62x_device::goto_op, 2},
+ {"111000kkkkkkkk", &pic16c62x_device::iorlw, 1},
+ {"1100xxkkkkkkkk", &pic16c62x_device::movlw, 1},
+ {"00000000001001", &pic16c62x_device::retfie, 2},
+ {"1101xxkkkkkkkk", &pic16c62x_device::retlw, 2},
+ {"00000000001000", &pic16c62x_device::returns, 2},
+ {"00000001100011", &pic16c62x_device::sleepic, 1},
+ {"11110xkkkkkkkk", &pic16c62x_device::sublw, 1},
+ {"111010kkkkkkkk", &pic16c62x_device::xorlw, 1},
+ {"00000001100100", &pic16c62x_device::clrwdt, 1},
+ {"00000001100010", &pic16c62x_device::option, 1}, // deprecated
+ {"00000001100fff", &pic16c62x_device::tris, 1}, // deprecated
{nullptr, nullptr, 0}
};
@@ -888,33 +957,48 @@ void pic16c62x_device::build_opcode_table(void)
void pic16c62x_device::device_start()
{
space(AS_PROGRAM).cache(m_cache);
- space(AS_PROGRAM).specific(m_program);
space(AS_DATA).specific(m_data);
- space(AS_IO).specific(m_io);
-
- /* ensure the internal ram pointers are set before get_info is called */
- update_internalram_ptr();
build_opcode_table();
+ // Set largely arbitrary initial values for special registers
+ m_W = 0;
+ m_ALU = 0;
+ m_WDT = 0;
+ m_TMR0 = 0;
+ m_STATUS = 0x18;
+ m_FSR = 0;
+ m_port_data[0] = 0;
+ m_port_data[1] = 0;
+ m_PCON = 0;
+ m_INTCON = 0;
+ std::fill(std::begin(m_STACK), std::end(m_STACK), 0);
+
save_item(NAME(m_W));
save_item(NAME(m_ALU));
save_item(NAME(m_OPTION));
save_item(NAME(m_PCLATH));
- save_item(NAME(m_TRISA));
- save_item(NAME(m_TRISB));
+ save_item(NAME(m_TMR0));
+ save_item(NAME(m_STATUS));
+ save_item(NAME(m_FSR));
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_tris));
+ save_item(NAME(m_INTCON));
+ save_item(NAME(m_PIR1));
+ save_item(NAME(m_PIE1));
+ save_item(NAME(m_PCON));
+ save_item(NAME(m_CMCON));
+ save_item(NAME(m_VRCON));
save_item(NAME(m_old_T0));
save_item(NAME(m_old_data));
- save_item(NAME(m_picRAMmask));
save_item(NAME(m_WDT));
save_item(NAME(m_prescaler));
save_item(NAME(m_STACK));
save_item(NAME(m_PC));
save_item(NAME(m_PREVPC));
save_item(NAME(m_CONFIG));
- save_item(NAME(m_opcode.d));
+ save_item(NAME(m_opcode.w));
save_item(NAME(m_delay_timer));
- save_item(NAME(m_picmodel));
save_item(NAME(m_reset_vector));
save_item(NAME(m_temp_config));
@@ -937,10 +1021,11 @@ void pic16c62x_device::device_start()
state_add( PIC16C62x_STK7, "STK7", m_STACK[7]).mask(0xfff).formatstr("%03X");
state_add( PIC16C62x_PRTA, "PRTA", m_debugger_temp).mask(0x1f).callimport().callexport().formatstr("%02X");
state_add( PIC16C62x_PRTB, "PRTB", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X");
- state_add( PIC16C62x_TRSA, "TRSA", m_TRISA).mask(0x1f).formatstr("%02X");
- state_add( PIC16C62x_TRSB, "TRSB", m_TRISB).formatstr("%02X");
+ state_add( PIC16C62x_TRSA, "TRSA", m_port_tris[0]).mask(0x1f).formatstr("%02X");
+ state_add( PIC16C62x_TRSB, "TRSB", m_port_tris[1]).formatstr("%02X");
state_add( PIC16C62x_FSR, "FSR", m_debugger_temp).mask(0xff).callimport().callexport().formatstr("%02X");
state_add( PIC16C62x_PSCL, "PSCL", m_debugger_temp).callimport().formatstr("%3s");
+ state_add( PIC16C62x_PCLATH, "PCLATH", m_PCLATH).mask(0x1f);
state_add( STATE_GENPC, "GENPC", m_PC).noshow();
state_add( STATE_GENPCBASE, "CURPC", m_PREVPC).noshow();
@@ -954,19 +1039,19 @@ void pic16c62x_device::state_import(const device_state_entry &entry)
switch (entry.index())
{
case PIC16C62x_STR:
- STATUS = m_debugger_temp;
+ m_STATUS = m_debugger_temp;
break;
case PIC16C62x_TMR0:
- TMR0 = m_debugger_temp;
+ m_TMR0 = m_debugger_temp;
break;
case PIC16C62x_PRTA:
- PORTA = m_debugger_temp;
+ m_port_data[0] = m_debugger_temp;
break;
case PIC16C62x_PRTB:
- PORTB = m_debugger_temp;
+ m_port_data[1] = m_debugger_temp;
break;
case PIC16C62x_FSR:
- FSR = ((m_debugger_temp & m_picRAMmask) | (uint8_t)(~m_picRAMmask));
+ m_FSR = m_debugger_temp;
break;
case PIC16C62x_PSCL:
m_prescaler = m_debugger_temp;
@@ -979,19 +1064,19 @@ void pic16c62x_device::state_export(const device_state_entry &entry)
switch (entry.index())
{
case PIC16C62x_STR:
- m_debugger_temp = STATUS;
+ m_debugger_temp = m_STATUS;
break;
case PIC16C62x_TMR0:
- m_debugger_temp = TMR0;
+ m_debugger_temp = m_TMR0;
break;
case PIC16C62x_PRTA:
- m_debugger_temp = PORTA & 0x1f;
+ m_debugger_temp = m_port_data[0] & 0x1f;
break;
case PIC16C62x_PRTB:
- m_debugger_temp = PORTB;
+ m_debugger_temp = m_port_data[1];
break;
case PIC16C62x_FSR:
- m_debugger_temp = ((FSR) & m_picRAMmask) | (uint8_t)(~m_picRAMmask);
+ m_debugger_temp = m_FSR;
break;
}
}
@@ -1006,12 +1091,12 @@ void pic16c62x_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 */
@@ -1028,25 +1113,26 @@ void pic16c62x_device::state_string_export(const device_state_entry &entry, std:
void pic16c62x_device::pic16c62x_reset_regs()
{
m_PC = m_reset_vector;
- m_TRISA = 0x1f;
- m_TRISB = 0xff;
+ m_port_tris[0] = 0x1f;
+ m_port_tris[1] = 0xff;
m_OPTION = 0xff;
- STATUS = 0x18;
- PCL = 0;
- FSR |= (uint8_t)(~m_picRAMmask);
- PORTA = 0;
+ m_STATUS &= 0x1f;
+ m_port_data[0] &= 0x10;
m_prescaler = 0;
m_delay_timer = 0;
m_old_T0 = 0;
m_inst_cycles = 0;
- PIC16C62x_RAM_WRMEM(0x85,m_TRISA);
- PIC16C62x_RAM_WRMEM(0x86,m_TRISB);
- PIC16C62x_RAM_WRMEM(0x81,m_OPTION);
+ m_PCLATH = 0;
+ m_INTCON &= 0x01;
+ m_PIR1 = 0;
+ m_PIE1 = 0;
+ m_CMCON = 0;
+ m_VRCON = 0;
}
void pic16c62x_device::pic16c62x_soft_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));
pic16c62x_reset_regs();
}
@@ -1071,7 +1157,7 @@ void pic16c62x_device::pic16c62x_update_watchdog(int counts)
/* If the current instruction is CLRWDT or SLEEP, don't update the WDT */
- if ((m_opcode.w.l != 0x64) && (m_opcode.w.l != 0x63))
+ if ((m_opcode.w != 0x64) && (m_opcode.w != 0x63))
{
uint16_t old_WDT = m_WDT;
@@ -1087,12 +1173,12 @@ void pic16c62x_device::pic16c62x_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);
pic16c62x_soft_reset();
}
}
else {
- CLR(STATUS, TO_FLAG);
+ CLR(m_STATUS, TO_FLAG);
pic16c62x_soft_reset();
}
}
@@ -1109,12 +1195,12 @@ void pic16c62x_device::pic16c62x_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;
}
}
@@ -1127,8 +1213,6 @@ void pic16c62x_device::execute_run()
{
uint8_t T0_in;
- update_internalram_ptr();
-
do
{
if (PD == 0) /* Sleep Mode */
@@ -1145,12 +1229,11 @@ void pic16c62x_device::execute_run()
debugger_instruction_hook(m_PC);
- m_opcode.d = M_RDOP(m_PC);
+ m_opcode.w = M_RDOP(m_PC);
m_PC++;
- PCL++;
- m_inst_cycles = m_opcode_table[m_opcode.w.l & 0x3fff].cycles;
- (this->*m_opcode_table[m_opcode.w.l & 0x3fff].function)();
+ m_inst_cycles = m_opcode_table[m_opcode.w & 0x3fff].cycles;
+ (this->*m_opcode_table[m_opcode.w & 0x3fff].function)();
if (T0CS) { /* Count mode */
T0_in = S_T0_IN;
@@ -1188,8 +1271,6 @@ void pic16c62x_device::execute_run()
void pic16c62x_device::device_reset()
{
- update_internalram_ptr();
-
pic16c62x_reset_regs();
- SET(STATUS, (TO_FLAG | PD_FLAG));
+ SET(m_STATUS, (TO_FLAG | PD_FLAG));
}