summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2021-03-05 20:20:33 +0100
committer hap <happppp@users.noreply.github.com>2021-03-05 20:20:46 +0100
commit9a79ec0a50cf1827228b741cea445f5f795a6969 (patch)
treeadc23d530b1943c36e6d07de9c307b2cb88640d1 /src/devices
parentf9e493cc6a67ee959fc59748beaa6f544ad5e577 (diff)
pps41: added most of the mm76 opcodes except for i/o
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/pps41/mm76.cpp83
-rw-r--r--src/devices/cpu/pps41/mm76.h60
-rw-r--r--src/devices/cpu/pps41/mm76op.cpp353
-rw-r--r--src/devices/cpu/pps41/pps41base.cpp27
-rw-r--r--src/devices/cpu/pps41/pps41base.h14
5 files changed, 523 insertions, 14 deletions
diff --git a/src/devices/cpu/pps41/mm76.cpp b/src/devices/cpu/pps41/mm76.cpp
index 2981467c0ac..3af749c62ce 100644
--- a/src/devices/cpu/pps41/mm76.cpp
+++ b/src/devices/cpu/pps41/mm76.cpp
@@ -59,7 +59,7 @@ void mm76e_device::program_1k(address_map &map)
void mm76_device::data_48x4(address_map &map)
{
- map(0x00, 0x2f).ram();
+ //map(0x00, 0x2f).ram();
}
@@ -97,5 +97,84 @@ void mm76_device::device_reset()
void mm76_device::execute_one()
{
- op_nop();
+ if (op_is_tr(m_prev_op))
+ {
+ switch (m_op & 0xf0)
+ {
+ case 0x20: op_skbei(); break;
+ case 0x60: op_skaei(); break;
+
+ case 0x80: case 0x90: case 0xa0: case 0xb0: op_tml(); break;
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_tl(); break;
+
+ default: op_illegal(); break;
+ }
+ }
+ else
+ {
+ switch (m_op & 0xf0)
+ {
+ case 0x20: op_lb(); break;
+ case 0x30: op_tr(); break;
+ case 0x60: op_aisk(); break;
+ case 0x70: op_lai(); break;
+
+ case 0x80: case 0x90: case 0xa0: case 0xb0: op_tm(); break;
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_t(); break;
+
+ default:
+ switch (m_op & 0xfc)
+ {
+ case 0x08: op_skbf(); break;
+ case 0x10: op_sb(); break;
+ case 0x14: op_rb(); break;
+ case 0x1c: op_eob(); break;
+ case 0x50: op_l(); break;
+ case 0x54: op_xnsk(); break;
+ case 0x58: op_x(); break;
+ case 0x5c: op_xdsk(); break;
+
+ default:
+ switch (m_op)
+ {
+ case 0x00: op_nop(); break;
+ case 0x01: op_sknc(); break;
+ case 0x02: op_rt(); break;
+ case 0x03: op_rtsk(); break;
+ case 0x04: op_int0l(); break;
+ case 0x05: op_int1h(); break;
+ case 0x06: op_din1(); break;
+ case 0x07: op_din0(); break;
+ case 0x0c: op_sc(); break;
+ case 0x0d: op_rc(); break;
+ case 0x0e: op_seg1(); break;
+ case 0x0f: op_seg2(); break;
+
+ case 0x18: op_oa(); break;
+ case 0x19: op_ob(); break;
+ case 0x1a: op_iam(); break;
+ case 0x1b: op_ibm(); break;
+
+ case 0x40: op_ac(); break;
+ case 0x41: op_acsk(); break;
+ case 0x42: op_a(); break;
+ case 0x43: op_ask(); break;
+ case 0x44: op_lba(); break;
+ case 0x45: op_com(); break;
+ case 0x46: op_xab(); break;
+ case 0x47: op_skmea(); break;
+ case 0x4a: op_i1(); break;
+ case 0x4b: op_i2c(); break;
+ case 0x4c: op_lsa(); break;
+ case 0x4d: op_ios(); break;
+ case 0x4e: op_xas(); break;
+
+ default: op_illegal(); break;
+ }
+ break; // 0xff
+
+ }
+ break; // 0xfc
+ }
+ }
}
diff --git a/src/devices/cpu/pps41/mm76.h b/src/devices/cpu/pps41/mm76.h
index 2bc3c7af670..bbad09218b5 100644
--- a/src/devices/cpu/pps41/mm76.h
+++ b/src/devices/cpu/pps41/mm76.h
@@ -68,13 +68,69 @@ protected:
void ram_w(u8 data);
void pop_pc();
void push_pc();
+ void op_tr();
void op_illegal();
+ void op_todo();
- virtual bool op_is_prefix(u8 op) override { return (op & 0xf0) == 0x30; };
+ virtual bool op_is_tr(u8 op) override { return (op & 0xf0) == 0x30; };
+ virtual bool op_is_eob(u8 op) { return (op & 0xfc) == 0x1c; };
+ virtual bool op_is_lb(u8 op) { return (op & 0xf0) == 0x20; };
+ virtual bool op_is_lai(u8 op) { return (op & 0xf0) == 0x70; };
// opcode handlers
- void op_nop();
+ virtual void op_xab();
+ virtual void op_lba();
+ virtual void op_lb();
+ virtual void op_eob();
+
+ virtual void op_sb();
+ virtual void op_rb();
+ virtual void op_skbf();
+
+ virtual void op_xas();
+ virtual void op_lsa();
+
+ virtual void op_l();
+ virtual void op_x();
+ virtual void op_xdsk();
+ virtual void op_xnsk();
+
+ virtual void op_a();
+ virtual void op_ac();
+ virtual void op_acsk();
+ virtual void op_ask();
+ virtual void op_com();
+ virtual void op_rc();
+ virtual void op_sc();
+ virtual void op_sknc();
+ virtual void op_lai();
+ virtual void op_aisk();
+
+ virtual void op_rt();
+ virtual void op_rtsk();
+ virtual void op_t();
+ virtual void op_tl();
+ virtual void op_tm();
+ virtual void op_tml();
+ virtual void op_nop();
+
+ virtual void op_skmea();
+ virtual void op_skbei();
+ virtual void op_skaei();
+
+ virtual void op_ibm();
+ virtual void op_ob();
+ virtual void op_iam();
+ virtual void op_oa();
virtual void op_ios();
+ virtual void op_i1();
+ virtual void op_i2c();
+ virtual void op_int1h();
+ virtual void op_din1();
+ virtual void op_int0l();
+ virtual void op_din0();
+ virtual void op_seg1();
+ virtual void op_seg2();
};
class mm76l_device : public mm76_device
diff --git a/src/devices/cpu/pps41/mm76op.cpp b/src/devices/cpu/pps41/mm76op.cpp
index f0560fee9d8..fced467662c 100644
--- a/src/devices/cpu/pps41/mm76op.cpp
+++ b/src/devices/cpu/pps41/mm76op.cpp
@@ -11,12 +11,12 @@
inline u8 mm76_device::ram_r()
{
- return m_data->read_byte(m_b & m_datamask) & 0xf;
+ return m_data->read_byte(m_ram_addr & m_datamask) & 0xf;
}
inline void mm76_device::ram_w(u8 data)
{
- m_data->write_byte(m_b & m_datamask, data & 0xf);
+ m_data->write_byte(m_ram_addr & m_datamask, data & 0xf);
}
void mm76_device::pop_pc()
@@ -33,18 +33,367 @@ void mm76_device::push_pc()
m_stack[0] = m_pc;
}
+void mm76_device::op_tr()
+{
+ // TR x: prefix for extended opcode
+}
+
void mm76_device::op_illegal()
{
logerror("unknown opcode $%02X at $%03X\n", m_op, m_prev_pc);
}
+void mm76_device::op_todo()
+{
+ logerror("unimplemented opcode $%02X at $%03X\n", m_op, m_prev_pc);
+}
+
// opcodes
+// RAM addressing instructions
+
+void mm76_device::op_xab()
+{
+ // XAB: exchange A with Bl
+ u8 a = m_a;
+ m_a = m_b & 0xf;
+ m_b = (m_b & ~0xf) | a;
+ m_ram_delay = true;
+}
+
+void mm76_device::op_lba()
+{
+ // LBA: load Bl from A
+ m_b = (m_b & ~0xf) | m_a;
+ m_ram_delay = true;
+}
+
+void mm76_device::op_lb()
+{
+ // LB x: load B from x (successive LB/EOB are ignored)
+ if (!(op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !op_is_eob(m_prev_op))
+ m_b = m_op & 0xf;
+}
+
+void mm76_device::op_eob()
+{
+ // EOB x: XOR Bu with x (successive LB/EOB are ignored, except after first executed LB)
+ bool first_lb = (op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !(op_is_lb(m_prev2_op) && !op_is_tr(m_prev3_op)) && !op_is_eob(m_prev2_op);
+ if ((!(op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !op_is_eob(m_prev_op)) || first_lb)
+ m_b ^= m_op << 4 & m_datamask;
+}
+
+
+// bit manipulation instructions
+
+void mm76_device::op_sb()
+{
+ // Bu != 3: SB x: set memory bit
+ // Bu == 3: SOS: set output
+ op_todo();
+}
+
+void mm76_device::op_rb()
+{
+ // Bu != 3: RB x: reset memory bit
+ // Bu == 3: ROS: reset output
+ op_todo();
+}
+
+void mm76_device::op_skbf()
+{
+ // Bu != 3: SKBF x: test memory bit
+ // Bu == 3: SKISL: test input
+ op_todo();
+}
+
+
+// register to register instructions
+
+void mm76_device::op_xas()
+{
+ // XAS: exchange A with S
+ u8 a = m_a;
+ m_a = m_s;
+ m_s = a;
+}
+
+void mm76_device::op_lsa()
+{
+ // LSA: load S from A
+ m_s = m_a;
+}
+
+
+// register memory instructions
+
+void mm76_device::op_l()
+{
+ // L x: load A from memory, XOR Bu with x
+ m_a = ram_r();
+ m_b ^= m_op << 4 & 0x30;
+}
+
+void mm76_device::op_x()
+{
+ // X x: exchange A with memory, XOR Bu with x
+ u8 a = m_a;
+ m_a = ram_r();
+ ram_w(a);
+ m_b ^= m_op << 4 & 0x30;
+}
+
+void mm76_device::op_xdsk()
+{
+ // XDSK x: X x + decrement Bl
+ op_x();
+ m_b = (m_b & ~0xf) | ((m_b - 1) & 0xf);
+ m_skip = (m_b & 0xf) == 0xf;
+ m_ram_delay = true;
+}
+
+void mm76_device::op_xnsk()
+{
+ // XNSK x: X x + increment Bl
+ op_x();
+ m_b = (m_b & ~0xf) | ((m_b + 1) & 0xf);
+ m_skip = (m_b & 0xf) == 0;
+ m_ram_delay = true;
+}
+
+
+// arithmetic instructions
+
+void mm76_device::op_a()
+{
+ // A: add memory to A
+ m_a = (m_a + ram_r()) & 0xf;
+}
+
+void mm76_device::op_ac()
+{
+ // AC: add memory and carry to A
+ m_a += ram_r() + m_c_in;
+ m_c = m_a >> 4 & 1;
+ m_a &= 0xf;
+ m_c_delay = true;
+}
+
+void mm76_device::op_acsk()
+{
+ // ACSK: AC + skip on no overflow
+ op_ac();
+ m_skip = !m_c;
+}
+
+void mm76_device::op_ask()
+{
+ // ASK: A + skip on no overflow
+ u8 a = m_a;
+ op_a();
+ m_skip = m_a >= a;
+}
+
+void mm76_device::op_com()
+{
+ // COM: complement A
+ m_a ^= 0xf;
+}
+
+void mm76_device::op_rc()
+{
+ // RC: reset carry
+ m_c = 0;
+}
+
+void mm76_device::op_sc()
+{
+ // SC: set carry
+ m_c = 1;
+}
+
+void mm76_device::op_sknc()
+{
+ // SKNC: skip on no carry
+ m_skip = !m_c_in;
+}
+
+void mm76_device::op_lai()
+{
+ // LAI x: load A from x (successive LAI are ignored)
+ if (!(op_is_lai(m_prev_op) && !op_is_tr(m_prev2_op)))
+ m_a = m_op & 0xf;
+}
+
+void mm76_device::op_aisk()
+{
+ // AISK x: add x to A, skip on no overflow
+ m_a += m_op & 0xf;
+ m_skip = !(m_a & 0x10);
+ m_a &= 0xf;
+}
+
+
+// ROM addressing instructions
+
+void mm76_device::op_rt()
+{
+ // RT: return from subroutine
+ cycle();
+ pop_pc();
+}
+
+void mm76_device::op_rtsk()
+{
+ // RTSK: RT + skip next instruction
+ op_rt();
+ m_skip = true;
+}
+
+void mm76_device::op_t()
+{
+ // T x: transfer on-page
+ cycle();
+
+ // jumps from subroutine pages reset page to SR1
+ u16 mask = m_prgmask ^ 0x7f;
+ if ((m_pc & mask) == mask)
+ m_pc &= ~0x40;
+
+ m_pc = (m_pc & ~0x3f) | (~m_op & 0x3f);
+}
+
+void mm76_device::op_tl()
+{
+ // TL x: transfer long off-page
+ cycle();
+ m_pc = (~m_prev_op & 0xf) << 6 | (~m_op & 0x3f);
+}
+
+void mm76_device::op_tm()
+{
+ // TM x: transfer and mark to SR0
+ cycle();
+
+ // calls from subroutine pages don't push PC
+ u16 mask = m_prgmask ^ 0x7f;
+ if ((m_pc & mask) != mask)
+ push_pc();
+
+ m_pc = ((~m_op & 0x3f) | ~0x3f) & m_prgmask;
+}
+
+void mm76_device::op_tml()
+{
+ // TML x: transfer and mark long
+ cycle();
+ push_pc();
+ m_pc = (~m_prev_op & 0xf) << 6 | (~m_op & 0x3f);
+}
+
void mm76_device::op_nop()
{
+ // NOP: no operation
+}
+
+
+// logical comparison instructions
+
+void mm76_device::op_skmea()
+{
+ // SKMEA: skip on memory equals A
+ m_skip = m_a == ram_r();
+}
+
+void mm76_device::op_skbei()
+{
+ // SKBEI x: skip on Bl equals x
+ m_skip = (m_b & 0xf) == (m_op & 0xf);
+}
+
+void mm76_device::op_skaei()
+{
+ // SKAEI x: skip on A equals X
+ m_skip = m_a == (~m_op & 0xf);
+}
+
+
+// input/output instructions
+
+void mm76_device::op_ibm()
+{
+ // IBM: input channel B to A
+}
+
+void mm76_device::op_ob()
+{
+ // OB: output from A to channel B
+ op_todo();
+}
+
+void mm76_device::op_iam()
+{
+ // IAM: input channel A to A
+ op_todo();
+}
+
+void mm76_device::op_oa()
+{
+ // OA: output from A to channel A
+ op_todo();
}
void mm76_device::op_ios()
{
+ // IOS: start serial I/O
+ op_todo();
+}
+
+void mm76_device::op_i1()
+{
+ // I1: input channel 1 to A
+ op_todo();
+}
+
+void mm76_device::op_i2c()
+{
+ // I2C: input channel 2 to A
+ op_todo();
+}
+
+void mm76_device::op_int1h()
+{
+ // INT1H: skip on INT1
+ op_todo();
+}
+
+void mm76_device::op_din1()
+{
+ // DIN1: test INT1 flip-flop
+ op_todo();
+}
+
+void mm76_device::op_int0l()
+{
+ // INT1H: skip on INT0
+ op_todo();
+}
+
+void mm76_device::op_din0()
+{
+ // DIN0: test INT0 flip-flop
+ op_todo();
+}
+
+void mm76_device::op_seg1()
+{
+ // SEG1: output A+carry through PLA to channel A
+ op_todo();
+}
+
+void mm76_device::op_seg2()
+{
+ // SEG2: output A+carry through PLA to channel B
+ op_todo();
}
diff --git a/src/devices/cpu/pps41/pps41base.cpp b/src/devices/cpu/pps41/pps41base.cpp
index 2766fead2cf..4177c4c4841 100644
--- a/src/devices/cpu/pps41/pps41base.cpp
+++ b/src/devices/cpu/pps41/pps41base.cpp
@@ -48,7 +48,9 @@ pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type
m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data),
m_prgwidth(prgwidth),
m_datawidth(datawidth),
- m_opla(*this, "opla")
+ m_opla(*this, "opla"),
+ m_read_r(*this),
+ m_write_r(*this)
{ }
@@ -58,7 +60,7 @@ pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type
enum
{
- PPS41_PC=1, PPS41_A, PPS41_C, PPS41_B
+ PPS41_PC=1, PPS41_A, PPS41_C, PPS41_B, PPS41_S
};
void pps41_base_device::device_start()
@@ -69,7 +71,8 @@ void pps41_base_device::device_start()
m_datamask = (1 << m_datawidth) - 1;
// resolve callbacks
- //..
+ m_read_r.resolve_safe(0);
+ m_write_r.resolve_safe();
// zerofill
m_pc = 0;
@@ -77,6 +80,7 @@ void pps41_base_device::device_start()
m_op = 0;
m_prev_op = 0;
m_prev2_op = 0;
+ m_prev3_op = 0;
memset(m_stack, 0, sizeof(m_stack));
m_a = 0;
@@ -90,15 +94,20 @@ void pps41_base_device::device_start()
m_prev_c = 0;
m_c_in = 0;
m_c_delay = false;
+ m_s = 0;
m_skip = false;
m_skip_count = 0;
+ m_cha = 0;
+ m_chb = 0;
+
// register for savestates
save_item(NAME(m_pc));
save_item(NAME(m_prev_pc));
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_prev2_op));
+ save_item(NAME(m_prev3_op));
save_item(NAME(m_stack));
save_item(NAME(m_a));
@@ -112,9 +121,13 @@ void pps41_base_device::device_start()
save_item(NAME(m_prev_c));
save_item(NAME(m_c_in));
save_item(NAME(m_c_delay));
+ save_item(NAME(m_s));
save_item(NAME(m_skip));
save_item(NAME(m_skip_count));
+ save_item(NAME(m_cha));
+ save_item(NAME(m_chb));
+
// register state for debugger
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%03X").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_prev_pc).formatstr("%03X").noshow();
@@ -123,6 +136,7 @@ void pps41_base_device::device_start()
state_add(PPS41_A, "A", m_a).formatstr("%01X");
state_add(PPS41_C, "C", m_c_in).formatstr("%01X");
state_add(PPS41_B, "B", m_b).formatstr("%02X");
+ state_add(PPS41_S, "S", m_s).formatstr("%01X");
set_icountptr(m_icount);
}
@@ -148,7 +162,8 @@ void pps41_base_device::device_reset()
m_skip_count = 0;
// clear outputs
- //..
+ m_cha = m_chb = 0xf;
+ m_write_r(0);
}
@@ -174,6 +189,7 @@ void pps41_base_device::execute_run()
while (m_icount > 0)
{
// remember previous state
+ m_prev3_op = m_prev2_op;
m_prev2_op = m_prev_op;
m_prev_op = m_op;
m_prev_pc = m_pc;
@@ -193,7 +209,7 @@ void pps41_base_device::execute_run()
if (m_skip)
{
// still skip through prefix(es)
- m_skip = op_is_prefix(m_op);
+ m_skip = op_is_tr(m_op);
m_op = 0; // fake nop
}
else if (m_skip_count)
@@ -203,6 +219,7 @@ void pps41_base_device::execute_run()
// restore opcode state
m_op = m_prev_op;
m_prev_op = m_prev2_op;
+ m_prev2_op = m_prev3_op;
}
else
execute_one();
diff --git a/src/devices/cpu/pps41/pps41base.h b/src/devices/cpu/pps41/pps41base.h
index 3f8459c8002..5157e53f417 100644
--- a/src/devices/cpu/pps41/pps41base.h
+++ b/src/devices/cpu/pps41/pps41base.h
@@ -20,7 +20,9 @@ public:
// configuration helpers
// I/O ports:
- //..
+ // 8-bit R I/O
+ auto read_r() { return m_read_r.bind(); }
+ auto write_r() { return m_write_r.bind(); }
// set MCU mask options:
@@ -59,7 +61,8 @@ protected:
optional_device<pla_device> m_opla; // segment output PLA
// i/o handlers
- //..
+ devcb_read8 m_read_r;
+ devcb_write8 m_write_r;
// internal state, regs
u16 m_pc;
@@ -67,6 +70,7 @@ protected:
u8 m_op;
u8 m_prev_op;
u8 m_prev2_op;
+ u8 m_prev3_op;
int m_stack_levels;
u16 m_stack[2]; // max 2
int m_d_pins;
@@ -82,11 +86,15 @@ protected:
int m_prev_c;
int m_c_in;
bool m_c_delay;
+ u8 m_s;
bool m_skip;
int m_skip_count;
+ u8 m_cha;
+ u8 m_chb;
+
// misc handlers
- virtual bool op_is_prefix(u8 op) = 0;
+ virtual bool op_is_tr(u8 op) = 0;
void cycle();
void increment_pc();
};