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