summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/st62xx
diff options
context:
space:
mode:
author mooglyguy <therealmogminer@gmail.com>2018-08-25 12:25:28 +0200
committer mooglyguy <therealmogminer@gmail.com>2018-08-25 12:25:51 +0200
commit60538922c83907a9f61e30b587c560d3af2a3491 (patch)
treec51a61e634eac3bcbe5ab0d91534ae89870c3de6 /src/devices/cpu/st62xx
parentac355d1559d954ba7b7d7b6946c1f968e7fc5de5 (diff)
-st62xx: Various changes: [Ryan Holtz]
* Made banking functional through a hack; bank finders in internal maps do not seem to work. * Added preliminary, untested GPIO support. * Fixed INC rr opcode. * Fixed disassembly of JRR, JRS, RES, SET opcodes, and added name for A register.
Diffstat (limited to 'src/devices/cpu/st62xx')
-rw-r--r--src/devices/cpu/st62xx/st62xx.cpp367
-rw-r--r--src/devices/cpu/st62xx/st62xx.h80
-rw-r--r--src/devices/cpu/st62xx/st62xx_dasm.cpp10
3 files changed, 394 insertions, 63 deletions
diff --git a/src/devices/cpu/st62xx/st62xx.cpp b/src/devices/cpu/st62xx/st62xx.cpp
index 7131add19fe..6848844b918 100644
--- a/src/devices/cpu/st62xx/st62xx.cpp
+++ b/src/devices/cpu/st62xx/st62xx.cpp
@@ -17,19 +17,6 @@
DEFINE_DEVICE_TYPE(ST6228, st6228_device, "st6228", "STmicro ST6228")
-void st6228_device::st6228_program_map(address_map &map)
-{
- map(0x000, 0x7ff).bankr("program_rombank");
- map(0x800, 0xfff).rom().region(tag(), 0x800);
-}
-
-void st6228_device::st6228_data_map(address_map &map)
-{
- map(0x00, 0x3f).bankrw("rambank");
- map(0x40, 0x7f).bankr("data_rombank");
- map(0x80, 0xff).rw(FUNC(st6228_device::regs_r), FUNC(st6228_device::regs_w));
-}
-
st6228_device::st6228_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, ST6228, tag, owner, clock)
, m_pc(0)
@@ -37,18 +24,36 @@ st6228_device::st6228_device(const machine_config &mconfig, const char *tag, dev
, m_prev_mode(MODE_NORMAL)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, address_map_constructor(FUNC(st6228_device::st6228_program_map), this))
, m_data_config("data", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(st6228_device::st6228_data_map), this))
+ , m_porta_out{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_portb_out{{*this}, {*this}, {*this}}
+ , m_portc_out{{*this}, {*this}, {*this}, {*this}}
+ , m_portd_out{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
, m_program(nullptr)
, m_data(nullptr)
- , m_rambank(*this, "^rambank")
- , m_program_rombank(*this, "^program_rombank")
- , m_data_rombank(*this, "^data_rombank")
+ // FIXME: memory banks do not currently work with internal maps.
+ //, m_rambank(*this, "^rambank")
+ //, m_program_rombank(*this, "^program_rombank")
+ //, m_data_rombank(*this, "^data_rombank")
, m_rom(*this, this->tag())
{
}
-void st6228_device::unimplemented_opcode(uint8_t op)
+void st6228_device::st6228_program_map(address_map &map)
{
- fatalerror("ST62xx: unknown opcode (%02x) at %04x\n", op, m_pc);
+ // FIXME: memory banks do not currently work with internal maps.
+ //map(0x000, 0x7ff).bankr(m_program_rombank);
+ map(0x000, 0x7ff).r(FUNC(st6228_device::program_rombank_r));
+ map(0x800, 0xfff).rom().region(tag(), 0x800);
+}
+
+void st6228_device::st6228_data_map(address_map &map)
+{
+ // FIXME: memory banks do not currently work with internal maps.
+ //map(0x00, 0x3f).bankrw(m_rambank);
+ //map(0x40, 0x7f).bankr(m_data_rombank);
+ map(0x00, 0x3f).rw(FUNC(st6228_device::rambank_r), FUNC(st6228_device::rambank_w));
+ map(0x40, 0x7f).r(FUNC(st6228_device::data_rombank_r));
+ map(0x80, 0xff).rw(FUNC(st6228_device::regs_r), FUNC(st6228_device::regs_w));
}
void st6228_device::device_start()
@@ -86,13 +91,34 @@ void st6228_device::device_start()
save_item(NAME(m_stack));
save_item(NAME(m_stack_index));
save_item(NAME(m_icount));
+ save_item(NAME(m_port_dir));
+ save_item(NAME(m_port_option));
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_pullup));
+ save_item(NAME(m_port_analog));
+ save_item(NAME(m_port_input));
+ save_item(NAME(m_port_irq_enable));
// set our instruction counter
set_icountptr(m_icount);
- m_rambank->configure_entries(0, 2, m_ram, 0x40);
- m_program_rombank->configure_entries(0, 2, m_rom, 0x800);
- m_data_rombank->configure_entries(0, 128, m_rom, 0x40);
+ // FIXME: memory banks do not currently work with internal maps.
+ //m_rambank->configure_entries(0, 2, m_ram, 0x40);
+ //m_program_rombank->configure_entries(0, 4, m_rom, 0x800);
+ //m_data_rombank->configure_entries(0, 128, m_rom, 0x40);
+
+ // TODO: magic numbers
+ for (uint8_t bit = 0; bit < 6; bit++)
+ m_porta_out[bit].resolve_safe();
+
+ for (uint8_t bit = 0; bit < 3; bit++)
+ m_portb_out[bit].resolve_safe();
+
+ for (uint8_t bit = 0; bit < 4; bit++)
+ m_portc_out[bit].resolve_safe();
+
+ for (uint8_t bit = 0; bit < 7; bit++)
+ m_portd_out[bit].resolve_safe();
}
void st6228_device::device_reset()
@@ -102,14 +128,23 @@ void st6228_device::device_reset()
std::fill(std::begin(m_stack), std::end(m_stack), 0);
std::fill(std::begin(m_flags), std::end(m_flags), 0);
+ std::fill(std::begin(m_port_dir), std::end(m_port_dir), 0);
+ std::fill(std::begin(m_port_option), std::end(m_port_option), 0);
+ std::fill(std::begin(m_port_data), std::end(m_port_data), 0);
+ std::fill(std::begin(m_port_pullup), std::end(m_port_pullup), 0);
+ std::fill(std::begin(m_port_analog), std::end(m_port_analog), 0);
+ std::fill(std::begin(m_port_input), std::end(m_port_input), 0);
+ std::fill(std::begin(m_port_irq_enable), std::end(m_port_irq_enable), 0);
+
m_pc = m_program->read_word(VEC_RESET);
m_stack_index = 0;
m_mode = MODE_NMI;
m_prev_mode = MODE_NORMAL;
- m_rambank->set_entry(0);
- m_program_rombank->set_entry(0);
- m_data_rombank->set_entry(0);
+ // FIXME: memory banks do not currently work with internal maps.
+ //m_rambank->set_entry(0);
+ //m_program_rombank->set_entry(0);
+ //m_data_rombank->set_entry(0);
m_regs[REG_TIMER_COUNT] = 0xff;
m_regs[REG_TIMER_PRESCALE] = 0x7f;
@@ -146,6 +181,113 @@ std::unique_ptr<util::disasm_interface> st6228_device::create_disassembler()
return std::make_unique<st62xx_disassembler>();
}
+// TODO: interrupts
+WRITE_LINE_MEMBER(st6228_device::porta0_w) { m_port_input[PORT_A] &= ~(1 << 0); m_port_input[PORT_A] |= (state << 0); }
+WRITE_LINE_MEMBER(st6228_device::porta1_w) { m_port_input[PORT_A] &= ~(1 << 1); m_port_input[PORT_A] |= (state << 1); }
+WRITE_LINE_MEMBER(st6228_device::porta2_w) { m_port_input[PORT_A] &= ~(1 << 2); m_port_input[PORT_A] |= (state << 2); }
+WRITE_LINE_MEMBER(st6228_device::porta3_w) { m_port_input[PORT_A] &= ~(1 << 3); m_port_input[PORT_A] |= (state << 3); }
+WRITE_LINE_MEMBER(st6228_device::porta4_w) { m_port_input[PORT_A] &= ~(1 << 4); m_port_input[PORT_A] |= (state << 4); }
+WRITE_LINE_MEMBER(st6228_device::porta5_w) { m_port_input[PORT_A] &= ~(1 << 5); m_port_input[PORT_A] |= (state << 5); }
+
+WRITE_LINE_MEMBER(st6228_device::portb4_w) { m_port_input[PORT_B] &= ~(1 << 4); m_port_input[PORT_B] |= (state << 4); }
+WRITE_LINE_MEMBER(st6228_device::portb5_w) { m_port_input[PORT_B] &= ~(1 << 5); m_port_input[PORT_B] |= (state << 5); }
+WRITE_LINE_MEMBER(st6228_device::portb6_w) { m_port_input[PORT_B] &= ~(1 << 6); m_port_input[PORT_B] |= (state << 6); }
+
+WRITE_LINE_MEMBER(st6228_device::portc4_w) { m_port_input[PORT_C] &= ~(1 << 4); m_port_input[PORT_C] |= (state << 4); }
+WRITE_LINE_MEMBER(st6228_device::portc5_w) { m_port_input[PORT_C] &= ~(1 << 5); m_port_input[PORT_C] |= (state << 5); }
+WRITE_LINE_MEMBER(st6228_device::portc6_w) { m_port_input[PORT_C] &= ~(1 << 6); m_port_input[PORT_C] |= (state << 6); }
+WRITE_LINE_MEMBER(st6228_device::portc7_w) { m_port_input[PORT_C] &= ~(1 << 7); m_port_input[PORT_C] |= (state << 7); }
+
+WRITE_LINE_MEMBER(st6228_device::portd1_w) { m_port_input[PORT_D] &= ~(1 << 1); m_port_input[PORT_D] |= (state << 1); }
+WRITE_LINE_MEMBER(st6228_device::portd2_w) { m_port_input[PORT_D] &= ~(1 << 2); m_port_input[PORT_D] |= (state << 2); }
+WRITE_LINE_MEMBER(st6228_device::portd3_w) { m_port_input[PORT_D] &= ~(1 << 3); m_port_input[PORT_D] |= (state << 3); }
+WRITE_LINE_MEMBER(st6228_device::portd4_w) { m_port_input[PORT_D] &= ~(1 << 4); m_port_input[PORT_D] |= (state << 4); }
+WRITE_LINE_MEMBER(st6228_device::portd5_w) { m_port_input[PORT_D] &= ~(1 << 5); m_port_input[PORT_D] |= (state << 5); }
+WRITE_LINE_MEMBER(st6228_device::portd6_w) { m_port_input[PORT_D] &= ~(1 << 6); m_port_input[PORT_D] |= (state << 6); }
+WRITE_LINE_MEMBER(st6228_device::portd7_w) { m_port_input[PORT_D] &= ~(1 << 7); m_port_input[PORT_D] |= (state << 7); }
+
+void st6228_device::set_port_output_bit(uint8_t index, uint8_t bit, uint8_t state)
+{
+ switch (index)
+ {
+ case PORT_A:
+ if (bit < 6)
+ m_porta_out[bit](state);
+ break;
+ case PORT_B:
+ if (bit >= 4 && bit <= 6)
+ m_portb_out[bit - 4](state);
+ break;
+ case PORT_C:
+ if (bit >= 4)
+ m_portc_out[bit - 4](state);
+ break;
+ case PORT_D:
+ if (bit >= 1)
+ m_portd_out[bit - 1](state);
+ break;
+ }
+}
+
+void st6228_device::update_port_mode(uint8_t index, uint8_t changed)
+{
+ const uint8_t dir = m_port_dir[index];
+ const uint8_t option = m_port_option[index];
+ for (uint8_t bit = 0; bit < 8; bit++)
+ {
+ const uint8_t mask = (1 << bit);
+ if (BIT(changed, bit) && !BIT(dir, bit))
+ {
+ if (BIT(m_port_data[index], bit))
+ {
+ m_port_irq_enable[index] &= ~mask;
+ m_port_pullup[index] &= ~mask;
+
+ if (BIT(option, bit))
+ m_port_analog[index] |= mask;
+ else
+ m_port_analog[index] &= ~mask;
+ }
+ else
+ {
+ m_port_pullup[index] |= mask;
+ m_port_analog[index] &= ~mask;
+
+ if (BIT(option, bit))
+ m_port_irq_enable[index] |= mask;
+ else
+ m_port_irq_enable[index] &= ~mask;
+ }
+ }
+ else if (BIT(dir, bit))
+ {
+ m_port_pullup[index] &= ~mask;
+ m_port_analog[index] &= ~mask;
+ m_port_irq_enable[index] &= ~mask;
+ }
+ }
+}
+
+READ8_MEMBER(st6228_device::program_rombank_r)
+{
+ return m_rom->base()[(m_regs[REG_ROM_BANK_SELECT] & 3) * 0x800 + offset];
+}
+
+READ8_MEMBER(st6228_device::data_rombank_r)
+{
+ return m_rom->base()[(m_regs[REG_DATA_ROM_WINDOW] & 0x7f) * 0x40 + offset];
+}
+
+WRITE8_MEMBER(st6228_device::rambank_w)
+{
+ m_ram[(m_regs[REG_RAM_BANK_SELECT] & 1) * 0x40 + offset] = data;
+}
+
+READ8_MEMBER(st6228_device::rambank_r)
+{
+ return m_ram[(m_regs[REG_RAM_BANK_SELECT] & 1) * 0x40 + offset];
+}
+
WRITE8_MEMBER(st6228_device::regs_w)
{
offset += 0x80;
@@ -157,6 +299,8 @@ WRITE8_MEMBER(st6228_device::regs_w)
return;
}
+ static char PORT_NAMES[4] = { 'A', 'B', 'C', 'D' };
+
switch (offset)
{
case REG_X:
@@ -168,16 +312,84 @@ WRITE8_MEMBER(st6228_device::regs_w)
break;
case REG_DATA_ROM_WINDOW:
- m_data_rombank->set_entry(data & 0x7f);
+ m_regs[offset] = data;
+ //m_data_rombank->set_entry(data & 0x7f);
break;
case REG_ROM_BANK_SELECT:
- m_program_rombank->set_entry(data & 3);
+ m_regs[offset] = data;
+ //m_program_rombank->set_entry(data & 3);
break;
case REG_RAM_BANK_SELECT:
- m_rambank->set_entry(data & 1);
+ m_regs[offset] = data;
+ //m_rambank->set_entry(data & 1);
+ break;
+
+ case REG_PORTA_DATA:
+ case REG_PORTB_DATA:
+ case REG_PORTC_DATA:
+ case REG_PORTD_DATA:
+ {
+ const uint8_t index = offset - REG_PORTA_DATA;
+ logerror("%s: Port %c data = %02x\n", machine().describe_context(), PORT_NAMES[index], data);
+ const uint8_t old_data = m_port_data[index];
+ const uint8_t changed = old_data ^ data;
+
+ m_port_data[index] = data;
+ update_port_mode(index, changed);
+
+ if (changed & m_port_dir[index])
+ {
+ for (uint8_t bit = 0; bit < 8; bit++)
+ {
+ if (BIT(changed, bit))
+ set_port_output_bit(index, bit, BIT(data, bit));
+ }
+ }
break;
+ }
+
+ case REG_PORTA_DIR:
+ case REG_PORTB_DIR:
+ case REG_PORTC_DIR:
+ case REG_PORTD_DIR:
+ {
+ const uint8_t index = offset - REG_PORTA_DIR;
+ logerror("%s: Port %c dir = %02x\n", machine().describe_context(), PORT_NAMES[index], data);
+ const uint8_t old_dir = m_port_dir[index];
+ const uint8_t changed = old_dir ^ data;
+
+ m_port_dir[index] = data;
+ update_port_mode(index, changed);
+
+ if (changed)
+ {
+ for (uint8_t bit = 0; bit < 8; bit++)
+ {
+ if (BIT(changed, bit))
+ {
+ set_port_output_bit(index, bit, BIT(m_port_data[index], bit));
+ }
+ }
+ }
+ break;
+ }
+
+ case REG_PORTA_OPTION:
+ case REG_PORTB_OPTION:
+ case REG_PORTC_OPTION:
+ case REG_PORTD_OPTION:
+ {
+ const uint8_t index = offset - REG_PORTA_OPTION;
+ logerror("%s: Port %c option = %02x\n", machine().describe_context(), PORT_NAMES[index], data);
+
+ const uint8_t changed = m_port_option[index] ^ data;
+ m_port_option[index] = data;
+
+ update_port_mode(index, changed);
+ break;
+ }
case REG_WATCHDOG:
// Do nothing for now
@@ -200,6 +412,8 @@ READ8_MEMBER(st6228_device::regs_r)
return m_regs[offset];
}
+ static char PORT_NAMES[4] = { 'A', 'B', 'C', 'D' };
+
switch (offset)
{
case REG_X:
@@ -210,6 +424,41 @@ READ8_MEMBER(st6228_device::regs_r)
ret = m_regs[offset];
break;
+ case REG_PORTA_DATA:
+ case REG_PORTB_DATA:
+ case REG_PORTC_DATA:
+ case REG_PORTD_DATA:
+ {
+ const uint8_t index = offset - REG_PORTA_DATA;
+ ret = (m_port_data[index] & m_port_dir[index]) |
+ (m_port_input[index] & ~m_port_dir[index]) |
+ (m_port_pullup[index] & ~m_port_dir[index]);
+ logerror("%s: Port %c data read (%02x)\n", machine().describe_context(), PORT_NAMES[index], ret);
+ break;
+ }
+
+ case REG_PORTA_DIR:
+ case REG_PORTB_DIR:
+ case REG_PORTC_DIR:
+ case REG_PORTD_DIR:
+ {
+ const uint8_t index = offset - REG_PORTA_DIR;
+ ret = m_port_dir[index];
+ logerror("%s: Port %c direction read (%02x)\n", machine().describe_context(), PORT_NAMES[index], ret);
+ break;
+ }
+
+ case REG_PORTA_OPTION:
+ case REG_PORTB_OPTION:
+ case REG_PORTC_OPTION:
+ case REG_PORTD_OPTION:
+ {
+ const uint8_t index = offset - REG_PORTA_OPTION;
+ ret = m_port_option[index];
+ logerror("%s: Port %c option read (%02x)\n", machine().describe_context(), PORT_NAMES[index], ret);
+ break;
+ }
+
default:
logerror("%s: Unknown register read: %02x\n", machine().describe_context(), offset);
break;
@@ -241,6 +490,11 @@ void st6228_device::tick_timers(int cycles)
{
}
+void st6228_device::unimplemented_opcode(uint8_t op)
+{
+ fatalerror("ST62xx: unknown opcode (%02x) at %04x\n", op, m_pc);
+}
+
void st6228_device::execute_run()
{
while (m_icount > 0)
@@ -248,7 +502,6 @@ void st6228_device::execute_run()
debugger_instruction_hook(m_pc);
uint8_t op = m_program->read_byte(m_pc);
- m_pc++;
int cycles = 4;
@@ -267,8 +520,8 @@ void st6228_device::execute_run()
case 0x01: case 0x11: case 0x21: case 0x31: case 0x41: case 0x51: case 0x61: case 0x71:
case 0x81: case 0x91: case 0xa1: case 0xb1: case 0xc1: case 0xd1: case 0xe1: case 0xf1: // CALL abc
{
- const uint8_t ab = m_program->read_byte(m_pc);
- m_pc++;
+ const uint8_t ab = m_program->read_byte(m_pc+1);
+ m_pc += 2;
const uint16_t abc = ((op & 0xf0) >> 4) | (ab << 4);
if (m_stack_index < 6) // FIXME: magic numbers
{
@@ -281,16 +534,15 @@ void st6228_device::execute_run()
// values will be lost. In this case, returns will return to the PC
// values stacked first."
}
- m_pc = abc;
+ m_pc = abc-1;
break;
}
case 0x09: case 0x19: case 0x29: case 0x39: case 0x49: case 0x59: case 0x69: case 0x79:
case 0x89: case 0x99: case 0xa9: case 0xb9: case 0xc9: case 0xd9: case 0xe9: case 0xf9: // JP abc
{
- const uint8_t ab = m_program->read_byte(m_pc);
- m_pc++;
+ const uint8_t ab = m_program->read_byte(m_pc+1);
const uint16_t abc = ((op & 0xf0) >> 4) | (ab << 4);
- m_pc = abc;
+ m_pc = abc-1;
break;
}
case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x72:
@@ -330,7 +582,7 @@ void st6228_device::execute_run()
case 0x0b: case 0x2b: case 0x4b: case 0x6b: case 0x8b: case 0xab: case 0xcb: case 0xeb: // RES b,rr
{
const uint8_t b = (op >> 5) & 7;
- const uint8_t rr = m_program->read_byte(m_pc);
+ const uint8_t rr = m_program->read_byte(m_pc+1);
const uint8_t nn = m_data->read_byte(rr);
m_data->write_byte(rr, nn & ~(1 << b));
m_pc++;
@@ -339,7 +591,7 @@ void st6228_device::execute_run()
case 0x1b: case 0x3b: case 0x5b: case 0x7b: case 0x9b: case 0xbb: case 0xdb: case 0xfb: // SET b,rr
{
const uint8_t b = (op >> 5) & 7;
- const uint8_t rr = m_program->read_byte(m_pc);
+ const uint8_t rr = m_program->read_byte(m_pc+1);
const uint8_t nn = m_data->read_byte(rr);
m_data->write_byte(rr, nn | (1 << b));
m_pc++;
@@ -431,8 +683,8 @@ void st6228_device::execute_run()
break;
case 0x0d: // LDI rr,nn
{
- const uint8_t rr = m_program->read_byte(m_pc);
- const uint8_t nn = m_program->read_byte(m_pc + 1);
+ const uint8_t rr = m_program->read_byte(m_pc+1);
+ const uint8_t nn = m_program->read_byte(m_pc+2);
m_data->write_byte(rr, nn);
if (nn)
@@ -475,7 +727,7 @@ void st6228_device::execute_run()
if (m_stack_index > 0)
{
m_stack_index--;
- m_pc = m_stack[m_stack_index];
+ m_pc = m_stack[m_stack_index] - 1;
m_mode = m_prev_mode;
m_prev_mode = MODE_NORMAL;
}
@@ -538,7 +790,7 @@ void st6228_device::execute_run()
if (m_stack_index > 0)
{
m_stack_index--;
- m_pc = m_stack[m_stack_index];
+ m_pc = m_stack[m_stack_index] - 1;
}
else
{
@@ -574,7 +826,7 @@ void st6228_device::execute_run()
break;
case 0x17: // LDI A,rr
{
- m_regs[REG_A] = m_program->read_byte(m_pc);
+ m_regs[REG_A] = m_program->read_byte(m_pc+1);
if (m_regs[REG_A])
m_flags[m_mode] &= ~FLAG_Z;
@@ -604,7 +856,7 @@ void st6228_device::execute_run()
}
case 0x37: // CPI A,nn
{
- const uint8_t nn = m_program->read_byte(m_pc);
+ const uint8_t nn = m_program->read_byte(m_pc+1);
if (m_regs[REG_A] < nn)
{
@@ -645,7 +897,7 @@ void st6228_device::execute_run()
}
case 0x57: // ADDI A,nn
{
- const uint8_t nn = m_program->read_byte(m_pc);
+ const uint8_t nn = m_program->read_byte(m_pc+1);
const uint16_t sum = m_regs[REG_A] + nn;
if (sum > 0xff)
@@ -694,7 +946,7 @@ void st6228_device::execute_run()
break;
case 0xb7: // ANDI A,nn
{
- m_regs[REG_A] &= m_program->read_byte(m_pc);
+ m_regs[REG_A] &= m_program->read_byte(m_pc+1);
if (m_regs[REG_A])
m_flags[m_mode] &= ~FLAG_Z;
@@ -725,7 +977,7 @@ void st6228_device::execute_run()
}
case 0xd7: // SUBI A,nn
{
- const uint8_t nn = m_program->read_byte(m_pc);
+ const uint8_t nn = m_program->read_byte(m_pc+1);
if (m_regs[REG_A] < nn)
{
@@ -765,7 +1017,7 @@ void st6228_device::execute_run()
break;
case 0x1f: // LD A,rr
{
- m_regs[REG_A] = m_data->read_byte(m_program->read_byte(m_pc));
+ m_regs[REG_A] = m_data->read_byte(m_program->read_byte(m_pc+1));
if (m_regs[REG_V])
m_flags[m_mode] &= ~FLAG_Z;
@@ -795,7 +1047,7 @@ void st6228_device::execute_run()
}
case 0x3f: // CP A,rr
{
- const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc));
+ const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc+1));
if (m_regs[REG_A] < nn)
{
@@ -836,7 +1088,7 @@ void st6228_device::execute_run()
}
case 0x5f: // ADD A,rr
{
- const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc));
+ const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc+1));
const uint16_t sum = m_regs[REG_A] + nn;
if (sum > 0xff)
@@ -867,10 +1119,13 @@ void st6228_device::execute_run()
m_flags[m_mode] |= FLAG_Z;
break;
}
- case 0x7f: // INC A
+ case 0x7f: // INC rr
{
- m_regs[REG_A]++;
- if (m_regs[REG_A])
+ const uint8_t rr = m_program->read_byte(m_pc+1);
+ const uint8_t nn = m_data->read_byte(rr) + 1;
+ m_data->write_byte(rr, nn);
+
+ if (nn)
m_flags[m_mode] &= ~FLAG_Z;
else
m_flags[m_mode] |= FLAG_Z;
@@ -887,7 +1142,7 @@ void st6228_device::execute_run()
break;
case 0x9f: // LD rr,A
{
- m_regs[REG_A] = m_data->read_byte(m_program->read_byte(m_pc));
+ m_regs[REG_A] = m_data->read_byte(m_program->read_byte(m_pc+1));
if (m_regs[REG_A])
m_flags[m_mode] &= ~FLAG_Z;
@@ -907,7 +1162,7 @@ void st6228_device::execute_run()
break;
case 0xbf: // AND A,rr
{
- m_regs[REG_A] &= m_data->read_byte(m_program->read_byte(m_pc));
+ m_regs[REG_A] &= m_data->read_byte(m_program->read_byte(m_pc+1));
if (m_regs[REG_A])
m_flags[m_mode] &= ~FLAG_Z;
@@ -938,7 +1193,7 @@ void st6228_device::execute_run()
}
case 0xdf: // SUB A,rr
{
- const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc));
+ const uint8_t nn = m_data->read_byte(m_program->read_byte(m_pc+1));
if (m_regs[REG_A] < nn)
{
@@ -970,7 +1225,7 @@ void st6228_device::execute_run()
}
case 0xff: // DEC rr
{
- const uint8_t rr = m_program->read_byte(m_pc);
+ const uint8_t rr = m_program->read_byte(m_pc+1);
const uint8_t value = m_data->read_byte(rr) - 1;
m_data->write_byte(rr, value);
@@ -985,6 +1240,8 @@ void st6228_device::execute_run()
logerror("%s: Unsupported opcode: %02x\n", op);
}
+ m_pc++;
+
tick_timers(cycles);
m_icount -= cycles;
diff --git a/src/devices/cpu/st62xx/st62xx.h b/src/devices/cpu/st62xx/st62xx.h
index cd74dc59f5b..8eae2774df0 100644
--- a/src/devices/cpu/st62xx/st62xx.h
+++ b/src/devices/cpu/st62xx/st62xx.h
@@ -33,6 +33,51 @@ class st6228_device : public cpu_device
public:
st6228_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <unsigned Bit> auto port_a()
+ {
+ static_assert(Bit < 6, "ST6228 port A bit must be in the range 0..5\n");
+ return m_porta_out[Bit].bind();
+ }
+ template <unsigned Bit> auto port_b()
+ {
+ static_assert(Bit >= 4 && Bit <= 6, "ST6228 port B bit must be in the range 4..6\n");
+ return m_portb_out[Bit - 4].bind();
+ }
+ template <unsigned Bit> auto port_c()
+ {
+ static_assert(Bit >= 4 && Bit <= 7, "ST6228 port C bit must be in the range 4..7\n");
+ return m_portc_out[Bit - 4].bind();
+ }
+ template <unsigned Bit> auto port_d()
+ {
+ static_assert(Bit >= 1 && Bit <= 7, "ST6228 port D bit must be in the range 1..7\n");
+ return m_portd_out[Bit - 1].bind();
+ }
+
+ DECLARE_WRITE_LINE_MEMBER(porta0_w);
+ DECLARE_WRITE_LINE_MEMBER(porta1_w);
+ DECLARE_WRITE_LINE_MEMBER(porta2_w);
+ DECLARE_WRITE_LINE_MEMBER(porta3_w);
+ DECLARE_WRITE_LINE_MEMBER(porta4_w);
+ DECLARE_WRITE_LINE_MEMBER(porta5_w);
+
+ DECLARE_WRITE_LINE_MEMBER(portb4_w);
+ DECLARE_WRITE_LINE_MEMBER(portb5_w);
+ DECLARE_WRITE_LINE_MEMBER(portb6_w);
+
+ DECLARE_WRITE_LINE_MEMBER(portc4_w);
+ DECLARE_WRITE_LINE_MEMBER(portc5_w);
+ DECLARE_WRITE_LINE_MEMBER(portc6_w);
+ DECLARE_WRITE_LINE_MEMBER(portc7_w);
+
+ DECLARE_WRITE_LINE_MEMBER(portd1_w);
+ DECLARE_WRITE_LINE_MEMBER(portd2_w);
+ DECLARE_WRITE_LINE_MEMBER(portd3_w);
+ DECLARE_WRITE_LINE_MEMBER(portd4_w);
+ DECLARE_WRITE_LINE_MEMBER(portd5_w);
+ DECLARE_WRITE_LINE_MEMBER(portd6_w);
+ DECLARE_WRITE_LINE_MEMBER(portd7_w);
+
protected:
// device-level overrides
virtual void device_start() override;
@@ -60,6 +105,13 @@ protected:
void unimplemented_opcode(uint8_t op);
void tick_timers(int cycles);
+ void update_port_mode(uint8_t index, uint8_t changed);
+ void set_port_output_bit(uint8_t index, uint8_t bit, uint8_t state);
+
+ DECLARE_READ8_MEMBER(program_rombank_r);
+ DECLARE_READ8_MEMBER(data_rombank_r);
+ DECLARE_WRITE8_MEMBER(rambank_w);
+ DECLARE_READ8_MEMBER(rambank_r);
DECLARE_WRITE8_MEMBER(regs_w);
DECLARE_READ8_MEMBER(regs_r);
@@ -150,6 +202,14 @@ protected:
FLAG_Z = 0x02
};
+ enum
+ {
+ PORT_A = 0,
+ PORT_B,
+ PORT_C,
+ PORT_D
+ };
+
// CPU registers
uint8_t m_regs[0x100];
uint8_t m_ram[64*2];
@@ -167,12 +227,26 @@ protected:
const address_space_config m_program_config;
const address_space_config m_data_config;
+ devcb_write_line m_porta_out[6];
+ devcb_write_line m_portb_out[3];
+ devcb_write_line m_portc_out[4];
+ devcb_write_line m_portd_out[7];
+
+ uint8_t m_port_dir[4];
+ uint8_t m_port_option[4];
+ uint8_t m_port_data[4];
+ uint8_t m_port_pullup[4];
+ uint8_t m_port_analog[4];
+ uint8_t m_port_input[4];
+ uint8_t m_port_irq_enable[4];
+
address_space *m_program;
address_space *m_data;
- required_memory_bank m_rambank;
- required_memory_bank m_program_rombank;
- required_memory_bank m_data_rombank;
+ // FIXME: memory banks do not currently work with internal maps.
+ //required_memory_bank m_rambank;
+ //required_memory_bank m_program_rombank;
+ //required_memory_bank m_data_rombank;
required_memory_region m_rom;
};
diff --git a/src/devices/cpu/st62xx/st62xx_dasm.cpp b/src/devices/cpu/st62xx/st62xx_dasm.cpp
index dc0f7bbc8c2..0f3c9b4c999 100644
--- a/src/devices/cpu/st62xx/st62xx_dasm.cpp
+++ b/src/devices/cpu/st62xx/st62xx_dasm.cpp
@@ -39,7 +39,7 @@ std::string st62xx_disassembler::reg_name(const uint8_t reg)
"DRA", "DRB", "DRC", "DRD", "DDRA", "DDRB", "DDRC", "DDRD", "IOR", "DWR", "PRPR", "DRBR", "ORA", "ORB", "ORC", "ORD",
"ADR", "ADCR", "PSC", "TCR", "TSCR", nullptr, "UARTDR","UARTCR", "DWDR", nullptr, "IPR", nullptr, "SIDR", "SDSR", nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, "ARMC", "ARSC0", "ARSC1", nullptr, "ARRC", "ARCP", "ARLR", nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "A",
};
if (REG_NAMES[reg])
@@ -99,7 +99,7 @@ offs_t st62xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
pc++;
const int8_t ee = (int8_t)opcodes.r8(pc);
pc++;
- util::stream_format(stream, "JRR %d,%Xh,$%Xh", b, rr, ee);
+ util::stream_format(stream, "JRR %d,%s,$%Xh", b, reg_name(rr), ee);
break;
}
case 0x13: case 0x33: case 0x53: case 0x73: case 0x93: case 0xb3: case 0xd3: case 0xf3:
@@ -109,7 +109,7 @@ offs_t st62xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
pc++;
const int8_t ee = (int8_t)opcodes.r8(pc);
pc++;
- util::stream_format(stream, "JRS %d,%Xh,$%Xh", b, rr, ee);
+ util::stream_format(stream, "JRS %d,%s,$%Xh", b, reg_name(rr), ee);
break;
}
case 0x0b: case 0x2b: case 0x4b: case 0x6b: case 0x8b: case 0xab: case 0xcb: case 0xeb:
@@ -117,7 +117,7 @@ offs_t st62xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
const uint8_t b = (op >> 5) & 7;
const uint8_t rr = opcodes.r8(pc);
pc++;
- util::stream_format(stream, "RES %d,%Xh", b, rr);
+ util::stream_format(stream, "RES %d,%s", b, reg_name(rr));
break;
}
case 0x1b: case 0x3b: case 0x5b: case 0x7b: case 0x9b: case 0xbb: case 0xdb: case 0xfb:
@@ -125,7 +125,7 @@ offs_t st62xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
const uint8_t b = (op >> 5) & 7;
const uint8_t rr = opcodes.r8(pc);
pc++;
- util::stream_format(stream, "SET %d,%Xh", b, rr);
+ util::stream_format(stream, "SET %d,%s", b, reg_name(rr));
break;
}
case 0x04: case 0x14: case 0x24: case 0x34: case 0x44: case 0x54: case 0x64: case 0x74: