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.cpp1431
1 files changed, 761 insertions, 670 deletions
diff --git a/src/devices/cpu/pic16c5x/pic16c5x.cpp b/src/devices/cpu/pic16c5x/pic16c5x.cpp
index c0aeeab5d8f..1a4fc4dce00 100644
--- a/src/devices/cpu/pic16c5x/pic16c5x.cpp
+++ b/src/devices/cpu/pic16c5x/pic16c5x.cpp
@@ -1,80 +1,104 @@
// license:BSD-3-Clause
// copyright-holders:Tony La Porta
- /**************************************************************************\
- * Microchip PIC16C5x Emulator *
- * *
- * Copyright Tony La Porta *
- * Originally written for the MAME project. *
- * *
- * *
- * Addressing architecture is based on the Harvard addressing scheme. *
- * *
- * *
- * **** Change Log **** *
- * TLP (06-Apr-2003) *
- * - First Public release. *
- * BO (07-Apr-2003) Ver 1.01 *
- * - Renamed 'sleep' function to 'sleepic' to avoid C conflicts. *
- * TLP (09-Apr-2003) Ver 1.10 *
- * - Fixed modification of file register $03 (Status). *
- * - Corrected support for 7FFh (12-bit) size ROMs. *
- * - The 'call' and 'goto' instructions weren't correctly handling the *
- * STATUS page info correctly. *
- * - The FSR register was incorrectly oring the data with 0xe0 when read. *
- * - Prescaler masking information was set to 3 instead of 7. *
- * - Prescaler assign bit was set to 4 instead of 8. *
- * - Timer source and edge select flags/masks were wrong. *
- * - Corrected the memory bank selection in GET/SET_REGFILE and also the *
- * indirect register addressing. *
- * BMP (18-May-2003) Ver 1.11 *
- * - pic16c5x_get_reg functions were missing 'returns'. *
- * TLP (27-May-2003) Ver 1.12 *
- * - Fixed the WatchDog timer count. *
- * - The Prescaler rate was incorrectly being zeroed, instead of the *
- * actual Prescaler counter in the CLRWDT and SLEEP instructions. *
- * - Added masking to the FSR register. Upper unused bits are always 1. *
- * TLP (27-Aug-2009) Ver 1.13 *
- * - Indirect addressing was not taking into account special purpose *
- * memory mapped locations. *
- * - 'iorlw' instruction was saving the result to memory instead of *
- * the W register. *
- * - 'tris' instruction no longer modifies Port-C on PIC models that *
- * do not have Port-C implemented. *
- * TLP (07-Sep-2009) Ver 1.14 *
- * - Edge sense control for the T0 count input was incorrectly reversed *
- * LE (05-Feb-2017) Ver 1.15 *
- * - Allow writing all bits of the status register except TO and PD. *
- * This enables e.g. bcf, bsf or clrf to change the flags when the *
- * status register is the destination. *
- * - Changed rlf and rrf to update the carry flag in the last step. *
- * Fixes the case where the status register is the destination. *
- * hap (12-Feb-2017) Ver 1.16 *
- * - Added basic support for the old GI PIC1650 and PIC1655. *
- * - Made RTCC(aka T0CKI) pin an inputline handler. *
- * *
- * *
- * **** Notes: **** *
- * PIC WatchDog Timer has a separate internal clock. For the moment, we're *
- * basing the count on a 4MHz input clock, since 4MHz is the typical *
- * input frequency (but by no means always). *
- * A single scaler is available for the Counter/Timer or WatchDog Timer. *
- * When connected to the Counter/Timer, it functions as a Prescaler, *
- * hence prescale overflows, tick the Counter/Timer. *
- * When connected to the WatchDog Timer, it functions as a Postscaler *
- * hence WatchDog Timer overflows, tick the Postscaler. This scenario *
- * means that the WatchDog timeout occurs when the Postscaler has *
- * reached the scaler rate value, not when the WatchDog reaches zero. *
- * CLRWDT should prevent the WatchDog Timer from timing out and generating *
- * a device reset, but how is not known. The manual also mentions that *
- * the WatchDog Timer can only be disabled during ROM programming, and *
- * no other means seem to exist??? *
- * *
- \**************************************************************************/
+/************************************************************************
+
+ Microchip PIC16C5x Emulator
+
+ Copyright Tony La Porta
+ Originally written for the MAME project.
+
+
+**** Notes: ****
+
+Addressing architecture is based on the Harvard addressing scheme.
+
+Initially meant to be an interface chip to GI's CP1600, but pretty quickly
+marketed as a more generic MCU.
+
+A single scaler is available for the Counter/Timer or WatchDog Timer.
+When connected to the Counter/Timer, it functions as a Prescaler,
+hence prescale overflows, tick the Counter/Timer.
+When connected to the WatchDog Timer, it functions as a Postscaler
+hence WatchDog Timer overflows, tick the Postscaler. This scenario
+means that the WatchDog timeout occurs when the Postscaler has
+reached the scaler rate value, not when the WatchDog reaches zero.
+
+
+**** TODO: ****
+
+- PIC WatchDog Timer has a separate internal clock. For the moment, we're
+ basing the count on a 4MHz input clock, since 4MHz is the typical
+ input frequency (but by no means always).
+- CLRWDT should prevent the WatchDog Timer from timing out and generating
+ a device reset, but how is not known. The manual also mentions that
+ the WatchDog Timer can only be disabled during ROM programming, and
+ no other means seem to exist???
+- RTCC/T0CKI frequency should be limited by internal clock. In other words:
+ It shouldn't be able to detect all pulses if the frequency on the pin is
+ higher than the CLKOUT frequency. On 4 clocks-per-cycle, the pin state is
+ sensed at clock #2 and clock #4.
+- get rid of m_picmodel checks (use virtual function overrides in subclasses)
+
+
+**** Change Log: ****
+
+TLP (06-Apr-2003)
+- First Public release.
+
+BO (07-Apr-2003) Ver 1.01
+- Renamed 'sleep' function to 'sleepic' to avoid C conflicts.
+
+TLP (09-Apr-2003) Ver 1.10
+- Fixed modification of file register $03 (Status).
+- Corrected support for 7FFh (12-bit) size ROMs.
+- The 'call' and 'goto' instructions weren't correctly handling the
+ STATUS page info correctly.
+- The FSR register was incorrectly oring the data with 0xe0 when read.
+- Prescaler masking information was set to 3 instead of 7.
+- Prescaler assign bit was set to 4 instead of 8.
+- Timer source and edge select flags/masks were wrong.
+- Corrected the memory bank selection in GET/SET_REGFILE and also the
+ indirect register addressing.
+
+BMP (18-May-2003) Ver 1.11
+- pic16c5x_get_reg functions were missing 'returns'.
+
+TLP (27-May-2003) Ver 1.12
+- Fixed the WatchDog timer count.
+- The Prescaler rate was incorrectly being zeroed, instead of the
+ actual Prescaler counter in the CLRWDT and SLEEP instructions.
+- Added masking to the FSR register. Upper unused bits are always 1.
+
+TLP (27-Aug-2009) Ver 1.13
+- Indirect addressing was not taking into account special purpose
+ memory mapped locations.
+- 'iorlw' instruction was saving the result to memory instead of
+ the W register.
+- 'tris' instruction no longer modifies Port-C on PIC models that
+ do not have Port-C implemented.
+
+TLP (07-Sep-2009) Ver 1.14
+- Edge sense control for the T0 count input was incorrectly reversed
+
+LE (05-Feb-2017) Ver 1.15
+- Allow writing all bits of the status register except TO and PD.
+ This enables e.g. bcf, bsf or clrf to change the flags when the
+ status register is the destination.
+- Changed rlf and rrf to update the carry flag in the last step.
+ Fixes the case where the status register is the destination.
+
+hap (12-Feb-2017) Ver 1.16
+- Added basic support for the old GI PIC1650 and PIC1655.
+- Made RTCC(aka T0CKI) pin an inputline handler.
+
+pa (12-Jun-2022) Ver 1.17
+- Port callback functions pass tristate value in mem_mask.
+
+************************************************************************/
#include "emu.h"
#include "pic16c5x.h"
#include "16c5xdsm.h"
-#include "debugger.h"
DEFINE_DEVICE_TYPE(PIC16C54, pic16c54_device, "pic16c54", "Microchip PIC16C54")
@@ -84,6 +108,7 @@ DEFINE_DEVICE_TYPE(PIC16C57, pic16c57_device, "pic16c57", "Microchip PIC16C57")
DEFINE_DEVICE_TYPE(PIC16C58, pic16c58_device, "pic16c58", "Microchip PIC16C58")
DEFINE_DEVICE_TYPE(PIC1650, pic1650_device, "pic1650", "GI PIC1650")
+DEFINE_DEVICE_TYPE(PIC1654S, pic1654s_device, "pic1654s", "GI PIC1654S")
DEFINE_DEVICE_TYPE(PIC1655, pic1655_device, "pic1655", "GI PIC1655")
@@ -96,11 +121,6 @@ void pic16c5x_device::rom_9(address_map &map)
map(0x000, 0x1ff).rom();
}
-void pic16c5x_device::ram_5(address_map &map)
-{
- map(0x00, 0x1f).ram();
-}
-
void pic16c5x_device::rom_10(address_map &map)
{
map(0x000, 0x3ff).rom();
@@ -111,9 +131,76 @@ void pic16c5x_device::rom_11(address_map &map)
map(0x000, 0x7ff).rom();
}
-void pic16c5x_device::ram_7(address_map &map)
+void pic16c5x_device::core_regs(address_map &map, u8 mirror)
{
- map(0x00, 0x0f).ram().mirror(0x60);
+ 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);
+}
+
+// PIC16C54, PIC16C56: 2 ports (12 pins) + 25 bytes of RAM
+void pic16c5x_device::ram_5_2ports(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, 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();
@@ -121,62 +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, uint32_t 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_reset_vector((program_width == 9) ? 0x1ff : ((program_width == 10) ? 0x3ff : 0x7ff))
+ , 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_map)
, m_picmodel(picmodel)
+ , m_data_width(data_width)
+ , m_program_width(program_width)
, m_temp_config(0)
- , m_rtcc(0)
- , m_picRAMmask((data_width == 5) ? 0x1f : 0x7f)
- , m_read_a(*this)
- , m_read_b(*this)
- , m_read_c(*this)
- , m_read_d(*this)
- , 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, uint32_t clock)
- : pic16c5x_device(mconfig, PIC16C54, tag, owner, clock, 9, 5, 0x16C54)
+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, 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, address_map_constructor(FUNC(pic16c55_device::ram_5_3ports), this))
{
}
-pic16c55_device::pic16c55_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC16C55, tag, owner, clock, 9, 5, 0x16C55)
+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, address_map_constructor(FUNC(pic16c56_device::ram_5_2ports), this))
{
}
-pic16c56_device::pic16c56_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC16C56, tag, owner, clock, 10, 5, 0x16C56)
+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, address_map_constructor(FUNC(pic16c57_device::ram_7_3ports), this))
{
}
-pic16c57_device::pic16c57_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC16C57, tag, owner, clock, 11, 7, 0x16C57)
+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, address_map_constructor(FUNC(pic16c58_device::ram_7_2ports), this))
{
}
-pic16c58_device::pic16c58_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC16C58, tag, owner, clock, 11, 7, 0x16C58)
+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, address_map_constructor(FUNC(pic1650_device::ram_5_4ports), this))
{
}
-pic1650_device::pic1650_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC1650, tag, owner, clock, 9, 5, 0x1650)
+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, address_map_constructor(FUNC(pic1654s_device::ram_5_2ports), this))
{
}
-pic1655_device::pic1655_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pic16c5x_device(mconfig, PIC1655, tag, owner, clock, 9, 5, 0x1655)
+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, address_map_constructor(FUNC(pic1655_device::ram_1655_3ports), this))
{
}
@@ -194,62 +279,32 @@ std::unique_ptr<util::disasm_interface> pic16c5x_device::create_disassembler()
}
-void pic16c5x_device::update_internalram_ptr()
-{
- m_internalram = (uint8_t *)space(AS_DATA).get_write_ptr(0x00);
-}
-
-
-
-#define PIC16C5x_RDOP(A) (m_program.read_word(A))
-#define PIC16C5x_RAM_RDMEM(A) ((uint8_t)m_data.read_byte(A))
-#define PIC16C5x_RAM_WRMEM(A,V) (m_data.write_byte(A,V))
-#define M_RDRAM(A) (((A) < 9) ? m_internalram[A] : PIC16C5x_RAM_RDMEM(A))
-#define M_WRTRAM(A,V) do { if ((A) < 9) m_internalram[A] = (V); else PIC16C5x_RAM_WRMEM(A,V); } while (0)
-#define M_RDOP(A) PIC16C5x_RDOP(A)
-#define ADDR_MASK 0x7ff
+// ******** The following is the Status Flag register definition. ********
+// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+// | PA | TO | PD | Z | DC | C |
+#define PA_REG 0xe0 // PA Program Page Preselect - bit 8 is unused here
+#define TO_FLAG 0x10 // TO Time Out flag (WatchDog)
+#define PD_FLAG 0x08 // PD Power Down flag
+#define Z_FLAG 0x04 // Z Zero Flag
+#define DC_FLAG 0x02 // DC Digit Carry/Borrow flag (Nibble)
+#define C_FLAG 0x01 // C Carry/Borrow Flag (Byte)
+#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)
-#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]
-#define INDF M_RDRAM(FSR)
-
-#define ADDR (m_opcode.b.l & 0x1f)
-
-
-/******** The following is the Status Flag register definition. *********/
- /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
- /* | PA | TO | PD | Z | DC | C | */
-#define PA_REG 0xe0 /* PA Program Page Preselect - bit 8 is unused here */
-#define TO_FLAG 0x10 /* TO Time Out flag (WatchDog) */
-#define PD_FLAG 0x08 /* PD Power Down flag */
-#define Z_FLAG 0x04 /* Z Zero Flag */
-#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)
-
-
-/******** The following is the Option Flag register definition. *********/
- /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
- /* | 0 | 0 | TOCS | TOSE | PSA | PS | */
-#define T0CS_FLAG 0x20 /* TOCS Timer 0 clock source select */
-#define T0SE_FLAG 0x10 /* TOSE Timer 0 clock source edge select */
-#define PSA_FLAG 0x08 /* PSA Prescaler Assignment bit */
-#define PS_REG 0x07 /* PS Prescaler Rate select */
+// ******** The following is the Option Flag register definition. ********
+// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+// | 0 | 0 | TOCS | TOSE | PSA | PS |
+#define T0CS_FLAG 0x20 // TOCS Timer 0 clock source select
+#define T0SE_FLAG 0x10 // TOSE Timer 0 clock source edge select
+#define PSA_FLAG 0x08 // PSA Prescaler Assignment bit
+#define PS_REG 0x07 // PS Prescaler Rate select
#define T0CS (m_OPTION & T0CS_FLAG)
#define T0SE (m_OPTION & T0SE_FLAG)
@@ -257,12 +312,12 @@ void pic16c5x_device::update_internalram_ptr()
#define PS (m_OPTION & PS_REG)
-/******** The following is the Config Flag register definition. *********/
- /* | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
- /* | CP | WDTE | FOSC | */
- /* CP Code Protect (ROM read protect) */
-#define WDTE_FLAG 0x04 /* WDTE WatchDog Timer enable */
-#define FOSC_FLAG 0x03 /* FOSC Oscillator source select */
+// ******** The following is the Config Flag register definition. ********
+// | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+// | CP | WDTE | FOSC |
+ // CP Code Protect (ROM read protect)
+#define WDTE_FLAG 0x04 // WDTE WatchDog Timer enable
+#define FOSC_FLAG 0x03 // FOSC Oscillator source select
#define WDTE (m_CONFIG & WDTE_FLAG)
#define FOSC (m_CONFIG & FOSC_FLAG)
@@ -272,228 +327,256 @@ void pic16c5x_device::update_internalram_ptr()
* Shortcuts
************************************************************************/
-#define CLR(flagreg, flag) ( flagreg &= (uint8_t)(~flag) )
-#define SET(flagreg, flag) ( flagreg |= flag )
+#define CLR(flagreg, flag) (flagreg &= u8(~flag))
+#define SET(flagreg, flag) (flagreg |= (flag))
+#define ADDR (m_opcode.b.l & 0x1f)
+#define BITPOS ((m_opcode.b.l >> 5) & 7)
-/* Easy bit position selectors */
-#define POS ((m_opcode.b.l >> 5) & 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 };
+void pic16c5x_device::calc_zero_flag()
+{
+ if (m_ALU == 0)
+ SET(m_STATUS, Z_FLAG);
+ else
+ CLR(m_STATUS, Z_FLAG);
+}
-void pic16c5x_device::CALCULATE_Z_FLAG()
+void pic16c5x_device::calc_add_flags(u8 augend)
{
- if (m_ALU == 0) SET(STATUS, Z_FLAG);
- else CLR(STATUS, Z_FLAG);
+ calc_zero_flag();
+
+ if (augend > m_ALU)
+ SET(m_STATUS, C_FLAG);
+ else
+ CLR(m_STATUS, C_FLAG);
+
+ if ((augend & 0x0f) > (m_ALU & 0x0f))
+ SET(m_STATUS, DC_FLAG);
+ else
+ CLR(m_STATUS, DC_FLAG);
}
-void pic16c5x_device::CALCULATE_ADD_CARRY()
+void pic16c5x_device::calc_sub_flags(u8 minuend)
{
- if ((uint8_t)(m_old_data) > (uint8_t)(m_ALU)) {
- SET(STATUS, C_FLAG);
- }
- else {
- CLR(STATUS, C_FLAG);
- }
+ calc_zero_flag();
+
+ if (minuend < m_ALU)
+ CLR(m_STATUS, C_FLAG);
+ else
+ SET(m_STATUS, C_FLAG);
+
+ if ((minuend & 0x0f) < (m_ALU & 0x0f))
+ CLR(m_STATUS, DC_FLAG);
+ else
+ SET(m_STATUS, DC_FLAG);
}
-void pic16c5x_device::CALCULATE_ADD_DIGITCARRY()
+
+
+void pic16c5x_device::set_pc(u16 addr)
{
- if (((uint8_t)(m_old_data) & 0x0f) > ((uint8_t)(m_ALU) & 0x0f)) {
- SET(STATUS, DC_FLAG);
- }
- else {
- CLR(STATUS, DC_FLAG);
- }
+ m_PC = addr & m_program_mask;
}
-void pic16c5x_device::CALCULATE_SUB_CARRY()
+u16 pic16c5x_device::pop_stack()
{
- if ((uint8_t)(m_old_data) < (uint8_t)(m_ALU)) {
- CLR(STATUS, C_FLAG);
- }
- else {
- SET(STATUS, C_FLAG);
- }
+ u16 data = m_STACK[1];
+ m_STACK[1] = m_STACK[0];
+ return data & m_program_mask;
}
-void pic16c5x_device::CALCULATE_SUB_DIGITCARRY()
+void pic16c5x_device::push_stack(u16 data)
{
- if (((uint8_t)(m_old_data) & 0x0f) < ((uint8_t)(m_ALU) & 0x0f)) {
- CLR(STATUS, DC_FLAG);
+ m_STACK[0] = m_STACK[1];
+ m_STACK[1] = data & m_program_mask;
+}
+
+
+
+u8 pic16c5x_device::get_regfile(u8 addr) // Read from 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
}
- else {
- SET(STATUS, DC_FLAG);
+
+ 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
}
+
+ m_data.write_byte(addr, data);
+}
+
+
+void pic16c5x_device::store_result(u8 addr, u8 data)
+{
+ if (m_opcode.b.l & 0x20)
+ store_regfile(addr, data);
+ else
+ m_W = data;
}
-uint16_t pic16c5x_device::POP_STACK()
+u8 pic16c5x_device::tmr0_r()
{
- uint16_t data = m_STACK[1];
- m_STACK[1] = m_STACK[0];
- return (data & ADDR_MASK);
+ return m_TMR0;
}
-void pic16c5x_device::PUSH_STACK(uint16_t data)
+
+void pic16c5x_device::tmr0_w(u8 data)
{
- m_STACK[0] = m_STACK[1];
- m_STACK[1] = (data & ADDR_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;
}
+u8 pic16c5x_device::pcl_r()
+{
+ return m_PC & 0x0ff;
+}
+void pic16c5x_device::pcl_w(u8 data)
+{
+ set_pc(((m_STATUS & PA_REG) << 4) | data);
+ if (!machine().side_effects_disabled())
+ m_inst_cycles++;
+}
-uint8_t pic16c5x_device::GET_REGFILE(offs_t addr) /* Read from internal memory */
+u8 pic16c5x_device::status_r()
{
- uint8_t data = 0;
+ return m_STATUS;
+}
- if (addr == 0) { /* Indirect addressing */
- addr = (FSR & m_picRAMmask);
- }
+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)));
+}
- if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) {
- addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */
- }
+u8 pic16c5x_device::fsr_r()
+{
+ // high bits are 1
+ return m_FSR | u8(~m_data_mask);
+}
- if ((addr & 0x10) == 0) addr &= 0x0f;
+void pic16c5x_device::fsr_w(u8 data)
+{
+ m_FSR = data & m_data_mask;
+}
- switch(addr)
- {
- case 0: /* Not an actual register, so return 0 */
- data = 0;
- break;
- case 4: data = (FSR | (uint8_t)(~m_picRAMmask));
- break;
- case 5: /* read port A */
- if (m_picmodel == 0x1650) {
- 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 |= ((uint8_t)(~m_TRISA) & PORTA);
- data &= 0x0f; /* 4-bit port (only lower 4 bits used) */
- }
- break;
- case 6: /* read port B */
- if (m_picmodel == 0x1650) {
- 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 |= ((uint8_t)(~m_TRISB) & PORTB);
- }
- break;
- 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 |= ((uint8_t)(~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;
+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)
}
- return data;
}
-void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to internal memory */
+void pic16c5x_device::porta_w(u8 data)
{
- if (addr == 0) { /* Indirect addressing */
- addr = (FSR & m_picRAMmask);
+ // write port A
+ if ((m_picmodel == 0x1650) || (m_picmodel == 0x1654)) {
+ m_write_port[PORTA](PORTA, data, 0xff);
}
-
- if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) {
- addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */
+ 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;
+}
- if ((addr & 0x10) == 0) addr &= 0x0f;
+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];
+}
- switch(addr)
- {
- case 0: /* Not an actual register, nothing to save */
- break;
- case 1: m_delay_timer = 2; /* Timer starts after next two instructions */
- if (PSA == 0) m_prescaler = 0; /* Must clear the Prescaler */
- TMR0 = data;
- break;
- case 2: PCL = data;
- m_PC = ((STATUS & PA_REG) << 4) | data;
- break;
- case 3: STATUS = (STATUS & (TO_FLAG | PD_FLAG)) | (data & (uint8_t)(~(TO_FLAG | PD_FLAG)));
- break;
- case 4: FSR = (data | (uint8_t)(~m_picRAMmask));
- break;
- case 5: /* write port A */
- if (m_picmodel == 0x1650) {
- 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 & (uint8_t)(~m_TRISA), 0xff);
- }
- PORTA = data;
- break;
- case 6: /* write port B */
- if (m_picmodel == 0x1650 || m_picmodel == 0x1655) {
- m_write_b(PIC16C5x_PORTB, data, 0xff);
- }
- else {
- m_write_b(PIC16C5x_PORTB, data & (uint8_t)(~m_TRISB), 0xff);
- }
- PORTB = data;
- break;
- 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 & (uint8_t)(~m_TRISC), 0xff);
- }
- PORTC = data; /* also writes to RAM */
- break;
- case 8: /* write port D */
- if (m_picmodel == 0x1650) {
- m_write_d(PIC16C5x_PORTD, data, 0xff);
- }
- PORTD = data; /* also writes to RAM */
- break;
- default: M_WRTRAM(addr, data);
- 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;
}
+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;
+ }
+}
-void pic16c5x_device::STORE_RESULT(offs_t addr, uint8_t data)
+void pic16c5x_device::portc_w(u8 data)
{
- if (m_opcode.b.l & 0x20)
- {
- STORE_REGFILE(addr, data);
+ // write port C
+ if (m_picmodel == 0x1650 || m_picmodel == 0x1655) {
+ m_write_port[PORTC](PORTC, data, 0xff);
}
- else
- {
- m_W = data;
+ 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::portd_w(u8 data)
+{
+ // write port D
+ assert(m_picmodel == 0x1650);
+ m_write_port[PORTD](PORTD, data, 0xff);
+ m_port_data[PORTD] = data;
}
@@ -501,159 +584,141 @@ void pic16c5x_device::STORE_RESULT(offs_t addr, uint8_t data)
* Emulate the Instructions
************************************************************************/
-/* This following function is here to fill in the void for */
-/* the opcode call function. This function is never called. */
-
-
void pic16c5x_device::illegal()
{
- logerror("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", (m_PC-1), m_opcode.w.l);
+ logerror("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", m_PREVPC, m_opcode.w);
}
/*
- Note:
- According to the manual, if the STATUS register is the destination for an instruction that affects the Z, DC or C bits
- then the write to these three bits is disabled. These bits are set or cleared according to the device logic.
- To ensure this is correctly emulated, in instructions that write to the file registers, always change the status flags
- *after* storing the result of the instruction.
- e.g. CALCULATE_*, SET(STATUS,*_FLAG) and CLR(STATUS,*_FLAG) should appear as the last steps of the instruction emulation.
+ Note:
+ According to the manual, if the STATUS register is the destination for an instruction that affects the Z, DC or C bits
+ then the write to these three bits is disabled. These bits are set or cleared according to the device logic.
+ To ensure this is correctly emulated, in instructions that write to the file registers, always change the status flags
+ *after* storing the result of the instruction.
+ e.g. CALCULATE_*, SET(STATUS,*_FLAG) and CLR(STATUS,*_FLAG) should appear as the last steps of the instruction emulation.
*/
void pic16c5x_device::addwf()
{
- m_old_data = GET_REGFILE(ADDR);
- m_ALU = m_old_data + m_W;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
- CALCULATE_ADD_CARRY();
- CALCULATE_ADD_DIGITCARRY();
+ u8 augend = get_regfile(ADDR);
+ m_ALU = augend + m_W;
+ store_result(ADDR, m_ALU);
+ calc_add_flags(augend);
}
void pic16c5x_device::andwf()
{
- m_ALU = GET_REGFILE(ADDR) & m_W;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR) & m_W;
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::andlw()
{
m_ALU = m_opcode.b.l & m_W;
m_W = m_ALU;
- CALCULATE_Z_FLAG();
+ calc_zero_flag();
}
void pic16c5x_device::bcf()
{
- m_ALU = GET_REGFILE(ADDR);
- m_ALU &= bit_clr[POS];
- STORE_REGFILE(ADDR, m_ALU);
+ m_ALU = get_regfile(ADDR);
+ m_ALU &= ~(1 << BITPOS);
+ store_regfile(ADDR, m_ALU);
}
void pic16c5x_device::bsf()
{
- m_ALU = GET_REGFILE(ADDR);
- m_ALU |= bit_set[POS];
- STORE_REGFILE(ADDR, m_ALU);
+ m_ALU = get_regfile(ADDR);
+ m_ALU |= 1 << BITPOS;
+ store_regfile(ADDR, m_ALU);
}
void pic16c5x_device::btfss()
{
- if ((GET_REGFILE(ADDR) & bit_set[POS]) == bit_set[POS])
- {
- m_PC++;
- PCL = m_PC & 0xff;
- m_inst_cycles += 1; /* Add NOP cycles */
+ if (BIT(get_regfile(ADDR), BITPOS)) {
+ set_pc(m_PC + 1);
+ m_inst_cycles++; // Add NOP cycles
}
}
void pic16c5x_device::btfsc()
{
- if ((GET_REGFILE(ADDR) & bit_set[POS]) == 0)
- {
- m_PC++;
- PCL = m_PC & 0xff;
- m_inst_cycles += 1; /* Add NOP cycles */
+ if (!BIT(get_regfile(ADDR), BITPOS)) {
+ set_pc(m_PC + 1);
+ m_inst_cycles++; // Add NOP cycles
}
}
void pic16c5x_device::call()
{
- PUSH_STACK(m_PC);
- m_PC = ((STATUS & PA_REG) << 4) | m_opcode.b.l;
- m_PC &= 0x6ff;
- PCL = m_PC & 0xff;
+ push_stack(m_PC);
+ 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);
+ store_regfile(ADDR, 0);
+ 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()
{
- m_ALU = (uint8_t)(~(GET_REGFILE(ADDR)));
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = u8(~(get_regfile(ADDR)));
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::decf()
{
- m_ALU = GET_REGFILE(ADDR) - 1;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR) - 1;
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::decfsz()
{
- m_ALU = GET_REGFILE(ADDR) - 1;
- STORE_RESULT(ADDR, m_ALU);
- if (m_ALU == 0)
- {
- m_PC++;
- PCL = m_PC & 0xff;
- m_inst_cycles += 1; /* Add NOP cycles */
+ m_ALU = get_regfile(ADDR) - 1;
+ store_result(ADDR, m_ALU);
+ if (m_ALU == 0) {
+ set_pc(m_PC + 1);
+ m_inst_cycles++; // Add NOP cycles
}
}
void pic16c5x_device::goto_op()
{
- m_PC = ((STATUS & PA_REG) << 4) | (m_opcode.w.l & 0x1ff);
- m_PC &= ADDR_MASK;
- PCL = m_PC & 0xff;
+ set_pc(((m_STATUS & PA_REG) << 4) | (m_opcode.w & 0x1ff));
}
void pic16c5x_device::incf()
{
- m_ALU = GET_REGFILE(ADDR) + 1;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR) + 1;
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::incfsz()
{
- m_ALU = GET_REGFILE(ADDR) + 1;
- STORE_RESULT(ADDR, m_ALU);
- if (m_ALU == 0)
- {
- m_PC++;
- PCL = m_PC & 0xff;
- m_inst_cycles += 1; /* Add NOP cycles */
+ m_ALU = get_regfile(ADDR) + 1;
+ store_result(ADDR, m_ALU);
+ if (m_ALU == 0) {
+ set_pc(m_PC + 1);
+ m_inst_cycles++; // Add NOP cycles
}
}
@@ -661,21 +726,21 @@ void pic16c5x_device::iorlw()
{
m_ALU = m_opcode.b.l | m_W;
m_W = m_ALU;
- CALCULATE_Z_FLAG();
+ calc_zero_flag();
}
void pic16c5x_device::iorwf()
{
- m_ALU = GET_REGFILE(ADDR) | m_W;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR) | m_W;
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::movf()
{
- m_ALU = GET_REGFILE(ADDR);
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR);
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
void pic16c5x_device::movlw()
@@ -685,12 +750,12 @@ void pic16c5x_device::movlw()
void pic16c5x_device::movwf()
{
- STORE_REGFILE(ADDR, m_W);
+ store_regfile(ADDR, m_W);
}
void pic16c5x_device::nop()
{
- /* Do nothing */
+ // Do nothing
}
void pic16c5x_device::option()
@@ -701,73 +766,93 @@ void pic16c5x_device::option()
void pic16c5x_device::retlw()
{
m_W = m_opcode.b.l;
- m_PC = POP_STACK();
- PCL = m_PC & 0xff;
+ set_pc(pop_stack());
}
void pic16c5x_device::rlf()
{
- m_ALU = GET_REGFILE(ADDR);
- uint8_t bit7 = m_ALU & 0x80;
+ m_ALU = get_regfile(ADDR);
+ int carry = BIT(m_ALU, 7);
m_ALU <<= 1;
- if (STATUS & C_FLAG) m_ALU |= 1;
- STORE_RESULT(ADDR, m_ALU);
- if (bit7) SET(STATUS, C_FLAG);
- else CLR(STATUS, C_FLAG);
+ if (m_STATUS & C_FLAG) m_ALU |= 1;
+ store_result(ADDR, m_ALU);
+
+ if (carry)
+ SET(m_STATUS, C_FLAG);
+ else
+ CLR(m_STATUS, C_FLAG);
}
void pic16c5x_device::rrf()
{
- m_ALU = GET_REGFILE(ADDR);
- uint8_t bit0 = m_ALU & 1;
+ m_ALU = get_regfile(ADDR);
+ int carry = BIT(m_ALU, 0);
m_ALU >>= 1;
- if (STATUS & C_FLAG) m_ALU |= 0x80;
- STORE_RESULT(ADDR, m_ALU);
- if (bit0) SET(STATUS, C_FLAG);
- else CLR(STATUS, C_FLAG);
+ if (m_STATUS & C_FLAG) m_ALU |= 0x80;
+ store_result(ADDR, m_ALU);
+
+ if (carry)
+ SET(m_STATUS, C_FLAG);
+ else
+ 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()
{
- m_old_data = GET_REGFILE(ADDR);
- m_ALU = m_old_data - m_W;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
- CALCULATE_SUB_CARRY();
- CALCULATE_SUB_DIGITCARRY();
+ u8 minuend = get_regfile(ADDR);
+ m_ALU = minuend - m_W;
+ store_result(ADDR, m_ALU);
+ calc_sub_flags(minuend);
}
void pic16c5x_device::swapf()
{
- m_ALU = ((GET_REGFILE(ADDR) << 4) & 0xf0);
- m_ALU |= ((GET_REGFILE(ADDR) >> 4) & 0x0f);
- STORE_RESULT(ADDR, m_ALU);
+ u8 reg = get_regfile(ADDR);
+ m_ALU = reg << 4 | reg >> 4;
+ store_result(ADDR, m_ALU);
}
void pic16c5x_device::tris()
{
- switch(m_opcode.b.l & 0x7)
+ switch (m_opcode.b.l & 0x7)
{
- case 5: if (m_TRISA == m_W) break;
- else { m_TRISA = m_W | 0xf0; m_write_a(PIC16C5x_PORTA, PORTA & (uint8_t)(~m_TRISA) & 0x0f, 0xff); break; }
- case 6: if (m_TRISB == m_W) break;
- else { m_TRISB = m_W; m_write_b(PIC16C5x_PORTB, PORTB & (uint8_t)(~m_TRISB), 0xff); break; }
- case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) {
- if (m_TRISC == m_W) break;
- else { m_TRISC = m_W; m_write_c(PIC16C5x_PORTC, PORTC & (uint8_t)(~m_TRISC), 0xff); break; }
- }
- else {
- illegal(); break;
- }
- default: illegal(); break;
+ case 5:
+ 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_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_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 {
+ illegal();
+ }
+ break;
+
+ default:
+ illegal();
+ break;
}
}
@@ -775,98 +860,97 @@ void pic16c5x_device::xorlw()
{
m_ALU = m_W ^ m_opcode.b.l;
m_W = m_ALU;
- CALCULATE_Z_FLAG();
+ calc_zero_flag();
}
void pic16c5x_device::xorwf()
{
- m_ALU = GET_REGFILE(ADDR) ^ m_W;
- STORE_RESULT(ADDR, m_ALU);
- CALCULATE_Z_FLAG();
+ m_ALU = get_regfile(ADDR) ^ m_W;
+ store_result(ADDR, m_ALU);
+ calc_zero_flag();
}
-
/***********************************************************************
* Opcode Table (Cycles, Instruction)
***********************************************************************/
const pic16c5x_device::pic16c5x_opcode pic16c5x_device::s_opcode_main[256]=
{
-/*00*/ {1, &pic16c5x_device::nop },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::movwf },{1, &pic16c5x_device::movwf },
- {1, &pic16c5x_device::clrw },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::clrf },{1, &pic16c5x_device::clrf },
-/*08*/ {1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },
- {1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },
-/*10*/ {1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },
- {1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },
-/*18*/ {1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },
- {1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },
-/*20*/ {1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },
- {1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },
-/*28*/ {1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },
- {1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },
-/*30*/ {1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },
- {1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },
-/*38*/ {1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },
- {1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },
-/*40*/ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
- {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
-/*48*/ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
- {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
-/*50*/ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
- {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
-/*58*/ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
- {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
-/*60*/ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
- {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
-/*68*/ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
- {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
-/*70*/ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
- {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
-/*78*/ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
- {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
-/*80*/ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
- {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
-/*88*/ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
- {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
-/*90*/ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
- {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
-/*98*/ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
- {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
-/*A0*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
- {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
-/*A8*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
- {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
-/*B0*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
- {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
-/*B8*/ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
- {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
-/*C0*/ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
- {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
-/*C8*/ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
- {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
-/*D0*/ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
- {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
-/*D8*/ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
- {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
-/*E0*/ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
- {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
-/*E8*/ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
- {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
-/*F0*/ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },
- {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },
-/*F8*/ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },
- {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }
+ {1, &pic16c5x_device::nop },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::movwf },{1, &pic16c5x_device::movwf }, // 00
+ {1, &pic16c5x_device::clrw },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::clrf },{1, &pic16c5x_device::clrf },
+ {1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf },{1, &pic16c5x_device::subwf }, // 08
+ {1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },{1, &pic16c5x_device::decf },
+ {1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf },{1, &pic16c5x_device::iorwf }, // 10
+ {1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },{1, &pic16c5x_device::andwf },
+ {1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf },{1, &pic16c5x_device::xorwf }, // 18
+ {1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },{1, &pic16c5x_device::addwf },
+ {1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf },{1, &pic16c5x_device::movf }, // 20
+ {1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },{1, &pic16c5x_device::comf },
+ {1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf },{1, &pic16c5x_device::incf }, // 28
+ {1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },{1, &pic16c5x_device::decfsz },
+ {1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf },{1, &pic16c5x_device::rrf }, // 30
+ {1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },{1, &pic16c5x_device::rlf },
+ {1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf },{1, &pic16c5x_device::swapf }, // 38
+ {1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },{1, &pic16c5x_device::incfsz },
+ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, // 40
+ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
+ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf }, // 48
+ {1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },{1, &pic16c5x_device::bcf },
+ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, // 50
+ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
+ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf }, // 58
+ {1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },{1, &pic16c5x_device::bsf },
+ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, // 60
+ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
+ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc }, // 68
+ {1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },{1, &pic16c5x_device::btfsc },
+ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, // 70
+ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
+ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss }, // 78
+ {1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },{1, &pic16c5x_device::btfss },
+ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, // 80
+ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
+ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw }, // 88
+ {2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },{2, &pic16c5x_device::retlw },
+ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, // 90
+ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
+ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call }, // 98
+ {2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },{2, &pic16c5x_device::call },
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, // A0
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, // A8
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, // B0
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op }, // B8
+ {2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },{2, &pic16c5x_device::goto_op },
+ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, // C0
+ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
+ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw }, // C8
+ {1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },{1, &pic16c5x_device::movlw },
+ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, // D0
+ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
+ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw }, // D8
+ {1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },{1, &pic16c5x_device::iorlw },
+ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, // E0
+ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
+ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw }, // E8
+ {1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },{1, &pic16c5x_device::andlw },
+ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }, // F0
+ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },
+ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }, // F8
+ {1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw },{1, &pic16c5x_device::xorlw }
};
const pic16c5x_device::pic16c5x_opcode pic16c5x_device::s_opcode_00x[16]=
{
-/*00*/ {1, &pic16c5x_device::nop },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::option },{1, &pic16c5x_device::sleepic },
- {1, &pic16c5x_device::clrwdt },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris },
-/*08*/ {1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },
- {1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal }
+ {1, &pic16c5x_device::nop },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::option },{1, &pic16c5x_device::sleepic }, // 00
+ {1, &pic16c5x_device::clrwdt },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris },{1, &pic16c5x_device::tris },
+ {1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal }, // 08
+ {1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal },{1, &pic16c5x_device::illegal }
};
@@ -886,45 +970,62 @@ 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_read_a.resolve_safe(0);
- m_read_b.resolve_safe(0);
- m_read_c.resolve_safe(0);
- m_read_d.resolve_safe(0);
- m_write_a.resolve_safe();
- m_write_b.resolve_safe();
- m_write_c.resolve_safe();
- m_write_d.resolve_safe();
+ m_program_mask = (1 << m_program_width) - 1;
+ m_data_mask = (1 << m_data_width) - 1;
+ m_status_mask = is_nmospic ? 0x07 : 0xff;
+
+ m_PC = 0;
+ m_PREVPC = 0;
+ m_W = 0;
+ m_OPTION = 0;
+ m_CONFIG = 0;
+ m_ALU = 0;
+ m_WDT = 0;
+ 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.w = 0;
- /* ensure the internal ram pointers are set before get_info is called */
- update_internalram_ptr();
+ m_delay_timer = 0;
+ m_rtcc = 0;
+ m_count_cycles = 0;
+ m_inst_cycles = 0;
+ m_debugger_temp = 0;
+ // save states
+ save_item(NAME(m_PC));
+ save_item(NAME(m_PREVPC));
save_item(NAME(m_W));
- save_item(NAME(m_ALU));
save_item(NAME(m_OPTION));
- save_item(NAME(m_TRISA));
- save_item(NAME(m_TRISB));
- save_item(NAME(m_TRISC));
- save_item(NAME(m_rtcc));
- save_item(NAME(m_count_pending));
- save_item(NAME(m_old_data));
- save_item(NAME(m_picRAMmask));
+ save_item(NAME(m_CONFIG));
+ save_item(NAME(m_ALU));
save_item(NAME(m_WDT));
- save_item(NAME(m_prescaler));
+ 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_PC));
- save_item(NAME(m_PREVPC));
- save_item(NAME(m_CONFIG));
- save_item(NAME(m_opcode.d));
- save_item(NAME(m_delay_timer));
- save_item(NAME(m_picmodel));
- save_item(NAME(m_reset_vector));
+ save_item(NAME(m_prescaler));
+ save_item(NAME(m_opcode.w));
+ save_item(NAME(m_delay_timer));
save_item(NAME(m_temp_config));
+ save_item(NAME(m_rtcc));
+ save_item(NAME(m_count_cycles));
save_item(NAME(m_inst_cycles));
+ // debugger
state_add( PIC16C5x_PC, "PC", m_PC).mask(0xfff).formatstr("%03X");
state_add( PIC16C5x_W, "W", m_W).formatstr("%02X");
state_add( PIC16C5x_ALU, "ALU", m_ALU).formatstr("%02X");
@@ -934,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();
@@ -957,25 +1064,22 @@ void pic16c5x_device::state_import(const device_state_entry &entry)
switch (entry.index())
{
case PIC16C5x_STR:
- STATUS = m_debugger_temp;
+ 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 & m_picRAMmask) | (uint8_t)(~m_picRAMmask));
+ m_port_data[PORTD] = m_debugger_temp;
break;
case PIC16C5x_PSCL:
m_prescaler = m_debugger_temp;
@@ -988,25 +1092,22 @@ void pic16c5x_device::state_export(const device_state_entry &entry)
switch (entry.index())
{
case PIC16C5x_STR:
- m_debugger_temp = STATUS;
+ 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) & m_picRAMmask) | (uint8_t)(~m_picRAMmask);
+ m_debugger_temp = m_port_data[PORTD];
break;
}
}
@@ -1021,59 +1122,60 @@ 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_OPTION & 0x08 ? (1<<(m_OPTION&7)) : (2<<(m_OPTION&7)) );
+ (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;
}
}
+
/****************************************************************************
* Reset registers to their initial values
****************************************************************************/
-void pic16c5x_device::pic16c5x_reset_regs()
+void pic16c5x_device::reset_regs()
{
- m_PC = m_reset_vector;
m_CONFIG = m_temp_config;
- m_TRISA = 0xff;
- m_TRISB = 0xff;
- m_TRISC = 0xff;
- m_OPTION = (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG);
- PCL = 0xff;
- FSR |= (uint8_t)(~m_picRAMmask);
+ 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;
+
m_prescaler = 0;
m_delay_timer = 0;
m_inst_cycles = 0;
- m_count_pending = false;
+ m_count_cycles = 0;
}
-void pic16c5x_device::pic16c5x_soft_reset()
+void pic16c5x_device::watchdog_reset()
{
- SET(STATUS, (TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG));
- pic16c5x_reset_regs();
+ SET(m_STATUS, TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG);
+ reset_regs();
}
-void pic16c5x_device::set_config(uint16_t data)
+void pic16c5x_device::set_config(u16 data)
{
- logerror("Writing %04x to the PIC16C5x config register\n",data);
+ logerror("Writing %04x to the PIC16C5x config register\n", data);
m_temp_config = data;
}
void pic16c5x_device::device_reset()
{
- pic16c5x_reset_regs();
- CLR(STATUS, PA_REG);
- SET(STATUS, (TO_FLAG | PD_FLAG));
+ reset_regs();
+ CLR(m_STATUS, PA_REG);
+ SET(m_STATUS, TO_FLAG | PD_FLAG);
}
@@ -1081,18 +1183,19 @@ void pic16c5x_device::device_reset()
* WatchDog
****************************************************************************/
-void pic16c5x_device::pic16c5x_update_watchdog(int counts)
+void pic16c5x_device::update_watchdog(int counts)
{
- /* WatchDog is set up to count 18,000 (0x464f hex) ticks to provide */
- /* the timeout period of 0.018ms based on a 4MHz input clock. */
- /* Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER */
- /* which effectively makes the PIC run at 1MHz internally. */
+ /*
+ WatchDog is set up to count 18,000 (0x464f hex) ticks to provide
+ the timeout period of 0.018ms based on a 4MHz input clock.
+ Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER
+ which effectively makes the PIC run at 1MHz internally.
- /* If the current instruction is CLRWDT or SLEEP, don't update the WDT */
+ If the current instruction is CLRWDT or SLEEP, don't update the WDT
+ */
- if ((m_opcode.w.l != 3) && (m_opcode.w.l != 4))
- {
- uint16_t old_WDT = m_WDT;
+ if ((m_opcode.w != 3) && (m_opcode.w != 4)) {
+ u16 old_WDT = m_WDT;
m_WDT -= counts;
@@ -1100,19 +1203,18 @@ void pic16c5x_device::pic16c5x_update_watchdog(int counts)
m_WDT = 0x464f - (0xffff - m_WDT);
}
- if (((old_WDT != 0) && (old_WDT < m_WDT)) || (m_WDT == 0))
- {
+ if (((old_WDT != 0) && (old_WDT < m_WDT)) || (m_WDT == 0)) {
if (PSA) {
m_prescaler++;
- if (m_prescaler >= (1 << PS)) { /* Prescale values from 1 to 128 */
+ if (m_prescaler >= (1 << PS)) { // Prescale values from 1 to 128
m_prescaler = 0;
- CLR(STATUS, TO_FLAG);
- pic16c5x_soft_reset();
+ CLR(m_STATUS, TO_FLAG);
+ watchdog_reset();
}
}
else {
- CLR(STATUS, TO_FLAG);
- pic16c5x_soft_reset();
+ CLR(m_STATUS, TO_FLAG);
+ watchdog_reset();
}
}
}
@@ -1123,17 +1225,26 @@ void pic16c5x_device::pic16c5x_update_watchdog(int counts)
* Update Timer
****************************************************************************/
-void pic16c5x_device::pic16c5x_update_timer(int counts)
+void pic16c5x_device::update_timer(int counts)
{
+ if (m_delay_timer > 0) { // Timer increment is inhibited
+ int dt = m_delay_timer;
+ m_delay_timer -= m_inst_cycles;
+ counts -= dt;
+ }
+
+ if (m_delay_timer > 0 || counts <= 0)
+ return;
+
if (PSA == 0) {
m_prescaler += counts;
- if (m_prescaler >= (2 << PS)) { /* Prescale values from 2 to 256 */
- TMR0 += (m_prescaler / (2 << PS));
- m_prescaler %= (2 << PS); /* Overflow prescaler */
+ if (m_prescaler >= (2 << PS)) { // Prescale values from 2 to 256
+ m_TMR0 += (m_prescaler / (2 << PS));
+ m_prescaler %= (2 << PS); // Overflow prescaler
}
}
else {
- TMR0 += counts;
+ m_TMR0 += counts;
}
}
@@ -1141,12 +1252,12 @@ void pic16c5x_device::execute_set_input(int line, int state)
{
switch (line)
{
- /* RTCC/T0CKI pin */
+ // RTCC/T0CKI pin
case PIC16C5x_RTCC:
- if (T0CS && state != m_rtcc) /* Count mode, edge triggered */
+ if (T0CS && state != m_rtcc) { // Count mode, edge triggered
if ((T0SE && !state) || (!T0SE && state))
- m_count_pending = true;
-
+ m_count_cycles++;
+ }
m_rtcc = state;
break;
@@ -1162,57 +1273,37 @@ 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_pending = false;
+ do {
+ if (PD == 0) { // Sleep Mode
+ m_count_cycles = 0;
m_inst_cycles = 1;
debugger_instruction_hook(m_PC);
- if (WDTE) {
- pic16c5x_update_watchdog(1);
- }
}
- else
- {
- if (m_count_pending) { /* RTCC/T0CKI clocked while in Count mode */
- m_count_pending = false;
- pic16c5x_update_timer(1);
- }
-
+ else {
m_PREVPC = m_PC;
debugger_instruction_hook(m_PC);
- m_opcode.d = M_RDOP(m_PC);
- m_PC++;
- PCL++;
+ m_opcode.w = m_program.read_word(m_PC);
+ set_pc(m_PC + 1);
- if (m_picmodel == 0x1650 || 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 */
+ else { // Opcode 0x00? has many opcodes in its minor nibble
m_inst_cycles = s_opcode_00x[(m_opcode.b.l & 0x1f)].cycles;
(this->*s_opcode_00x[(m_opcode.b.l & 0x1f)].function)();
}
- if (!T0CS) { /* Timer mode */
- if (m_delay_timer) {
- m_delay_timer--;
- }
- else {
- pic16c5x_update_timer(m_inst_cycles);
- }
- }
- if (WDTE) {
- pic16c5x_update_watchdog(m_inst_cycles);
- }
+ update_timer(T0CS ? m_count_cycles : m_inst_cycles);
+ m_count_cycles = 0;
}
- m_icount -= m_inst_cycles;
+ if (WDTE) {
+ update_watchdog(m_inst_cycles);
+ }
+ m_icount -= m_inst_cycles;
} while (m_icount > 0);
}