diff options
author | 2024-09-19 21:23:11 -0400 | |
---|---|---|
committer | 2024-09-19 21:23:11 -0400 | |
commit | d8761b090c01d96c2ce76c47a962286d78d330a8 (patch) | |
tree | ad07cb3c97a15d61d36b0486a2e0d228eda1a36b /src/devices/cpu/mpk1839 | |
parent | d49d4e00c22b5be6d0a260a4532dc85b7562d9ab (diff) |
ussr/pk32.cpp: Electronika PK-32 - not working (#12732)
mpl1839/kl1839vm1.cpp: MPL's l1839vm1 cpu device
Diffstat (limited to 'src/devices/cpu/mpk1839')
-rw-r--r-- | src/devices/cpu/mpk1839/kl1839vm1.cpp | 686 | ||||
-rw-r--r-- | src/devices/cpu/mpk1839/kl1839vm1.h | 94 | ||||
-rw-r--r-- | src/devices/cpu/mpk1839/kl1839vm1dasm.cpp | 441 | ||||
-rw-r--r-- | src/devices/cpu/mpk1839/kl1839vm1dasm.h | 25 |
4 files changed, 1246 insertions, 0 deletions
diff --git a/src/devices/cpu/mpk1839/kl1839vm1.cpp b/src/devices/cpu/mpk1839/kl1839vm1.cpp new file mode 100644 index 00000000000..5f19497a019 --- /dev/null +++ b/src/devices/cpu/mpk1839/kl1839vm1.cpp @@ -0,0 +1,686 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub + +#include "emu.h" + +#include "kl1839vm1.h" +#include "kl1839vm1dasm.h" + + +#define VERBOSE ( LOG_GENERAL ) +#include "logmacro.h" + +#define UNIMPLEMENTED(msg) LOG("Unimplemented: %s\n", msg) + +#define MCA m_mca.w.l // Micro Command Address +#define VMA m_vma.d // Virtual Memory Address +#define RV m_rv.d +#define SCH m_sch.b.l // Program Counter +#define RSP m_rsp.b.l + +#define K(x) m_consts[x & 0x0f] +#define PCM K(5) +#define RC K(6) + +/* registers of various sizes */ +#define R(x) m_reg[x].d + +#define AP R(0x0c) +#define FP R(0x0d) +#define SP R(0x0e) +#define PC R(0x0f) + +#define RNK R(0x1c) +#define RKA R(0x1d) // KRSP? +#define PSL R(0x1e) +#define PSW m_reg[0x1e].w.l +#define BO R(0x1f) + +#define NF 0x08 +#define ZF 0x04 +#define VF 0x02 +#define CF 0x01 + +DEFINE_DEVICE_TYPE(KL1839VM1, kl1839vm1_device, "kl1839vm1", "KL1839VM1") + + +kl1839vm1_device::kl1839vm1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : cpu_device(mconfig, KL1839VM1, tag, owner, clock) + , m_microcode_config("microcode", ENDIANNESS_BIG, 32, 14, -2) + , m_sysram_config("sysram", ENDIANNESS_BIG, 8, 24, 0) + , m_ram_config("ram", ENDIANNESS_LITTLE, 8, 24, 0) + , m_io_config("io", ENDIANNESS_LITTLE, 32, 6, -2) +{ +} + +device_memory_interface::space_config_vector kl1839vm1_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_OPCODES, &m_microcode_config), + std::make_pair(AS_DATA, &m_sysram_config), + std::make_pair(AS_PROGRAM, &m_ram_config), + std::make_pair(AS_IO, &m_io_config) + }; +} + +void kl1839vm1_device::flag(u32 op) +{ + const u8 copwt = BIT(op, 15, 1); + + if (copwt) + { + RNK = PC; + RKA = PSL; + } +} + +void kl1839vm1_device::rest(u32 op) +{ +} + +/* + Shift/Rotate + + val: + va: 0 - Carry read; 1 - Carry write + fo: 0 - dw, 1 - w, 2 - b; 3 - dd + a_c: 1 - arithmetical, 0 - cyclic + l_r: 1 - left, 0 - right +*/ +u32 kl1839vm1_device::shr(u32 val, bool va, u8 fo, bool a_c, bool l_r) +{ + u8 left_bit; + switch (fo & 0b11) + { + case 0b00: left_bit = 31; break; + case 0b01: left_bit = 15; break; + case 0b10: left_bit = 31; break; // ??? dd + case 0b11: left_bit = 7; break; + } + const u8 rd = l_r ? left_bit : 0; + const u8 wr = l_r ? 0 : left_bit; + + const bool carry_out = BIT(val, rd); + u32 res = l_r ? (val << 1) : (val >> 1); + res &= ~(1 << wr); + if (!a_c) + { + res |= (va ? (RSP & CF) : carry_out) << wr; + } + else if (l_r && !va) + { + res |= carry_out << wr; + } + + RSP &= ~(VF | CF); + RSP |= carry_out; + if (a_c && l_r && (fo == 0b10) && (carry_out != BIT(res, rd))) + { + RSP |= VF; + } + return res; +} + +void kl1839vm1_device::kop(u8 kop, u8 fd, u32 x, u32 y, u32 &z, u8 ps, bool va = false, u8 fo = 0) +{ + u32 res = 0; + RSP &= ~(NF | ZF | VF); + if ((kop & 0b1001) == 0b1001) // shr + { + RSP &= ~CF; + } + switch(kop) + { + case 0b0000: res = y; break; + // 0b0001: + case 0b0010: res = x + y; break; + case 0b0011: res = x; break; + case 0b0100: res = x - y; break; + // 0b0101 + case 0b0110: res = y - x; break; + case 0b0111: res = ~x; break; + case 0b1000: res = x ^ y; break; + case 0b1001: res = shr(x, va, fo, 1, 1); break; // AL + case 0b1010: res = x | y; break; + case 0b1011: res = shr(x, va, fo, 0, 1); break; // CL + case 0b1100: res = x & ~y; break; + case 0b1101: res = shr(x, va, fo, 1, 0); break; // AR + case 0b1110: res = x & y; break; + case 0b1111: res = shr(x, va, fo, 0, 0); break; // CR + default: break; // 0b0001, 0b0101 - reserved + } + + switch(fd) + { + case 0b00: + z = res; + RSP |= BIT(res, 31) ? NF : 0; + break; + case 0b01: + z = (z & 0xffff0000) | (res & 0x0000ffff); + RSP |= BIT(res, 15) ? NF : 0; + break; + case 0b11: + z = (z & 0xffffff00) | (res & 0x000000ff); + RSP |= BIT(res, 7) ? NF : 0; + break; + default: RKA = res; break; // 0b10 + } + RSP |= (res == 0) ? ZF : 0; + + switch (ps) + { + case 0b00: PSW = (PSW & ~0x0f) | (RSP & 0x0f); break; + case 0b01: PSW = (PSW & ~0x0e) | (RSP & 0x0e); break; + case 0b10: PSW = (PSW & ~0x0f) | (RSP & 0x0c); break; + default: break; + } +} + +void kl1839vm1_device::mreg_r() +{ + const u8 kob_tmp = BIT(m_vma_tmp.d, 24, 3); + if (kob_tmp == 0b001) + { + const u8 no_tmp = BIT(m_vma_tmp.d, 30, 2); + switch (no_tmp) + { + case 0b00: + BO = m_ram.read_dword(m_vma_tmp.d); + break; + case 0b10: + BO = m_io.read_dword(m_vma_tmp.d); + break; + case 0b11: + BO = m_sysram.read_dword(m_vma_tmp.d); + break; + default: + UNIMPLEMENTED("Read w/ catch BRA"); + break; + } + } +} + +void kl1839vm1_device::mreg_w() +{ + const u8 kob_tmp = BIT(m_vma_tmp.d, 24, 3); + if (kob_tmp == 0b010) + { + const u8 no_tmp = BIT(m_vma_tmp.d, 30, 2); + switch (no_tmp) + { + case 0b00: + m_ram.write_dword(m_vma_tmp.d, BO); + break; + case 0b10: + m_io.write_dword(m_vma_tmp.d, BO); + break; + case 0b11: + m_sysram.write_dword(m_vma_tmp.d, BO); + break; + default: + UNIMPLEMENTED("Write w/ catch BRA"); + break; + } + } +} + +void kl1839vm1_device::ma(u32 op) +{ + const u8 fd = BIT(op, 28, 2); + const u8 kop1 = BIT(op, 24, 4); + const u8 am = BIT(op, 20, 4); + const u8 x = BIT(op, 15, 5); + const u8 ps = BIT(op, 13, 2); + const bool va = BIT(op, 12); + const u8 no = BIT(op, 10, 2); + const u8 fo = BIT(op, 8, 2); + const u8 kob = BIT(op, 5, 3); + const bool pd = BIT(op, 4); + const bool po = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + if (am==5 || am==8 || am>=0xd) + UNIMPLEMENTED("Read regs with data mirror"); + + if (po | py | px) + UNIMPLEMENTED("MA: P*"); + + u32 kob_data = kop1 ? R(x) : K(am); + kop(kop1, fd, R(x), K(am), R(x), ps, va, fo); + if (pd || x == 0x1f) mreg_w(); + if (va) + { + kob_data = R(x); + } + kob_process(no, fo, kob, kob_data); +} + +void kl1839vm1_device::mb(u32 op) +{ + const u8 fd = BIT(op, 28, 2); + const u8 kop2 = BIT(op, 25, 3); + const u8 y = BIT(op, 20, 5); + const u8 x = BIT(op, 15, 5); + const u8 ps = BIT(op, 13, 2); + const bool va = BIT(op, 12); + const u8 no = BIT(op, 10, 2); + const u8 fo = BIT(op, 8, 2); + const u8 kob = BIT(op, 5, 3); + const bool pd = BIT(op, 4); + const bool po = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + if (po | py | px) + UNIMPLEMENTED("MB: P*"); + + u32 kob_data = kop2 ? R(x) : R(y); + if (pd || y == 0x1f) mreg_r(); + kop(kop2 << 1, fd, R(x), R(y), R(x), ps, va, fo); + if (pd || x == 0x1f) mreg_w(); + if (va) + { + kob_data = R(x); + } + kob_process(no, fo, kob, kob_data); +} + +void kl1839vm1_device::mc(u32 op) +{ + const u8 fd = BIT(op, 28, 2); + const u8 kop2 = BIT(op, 25, 3); + const u8 y = BIT(op, 20, 5); + const u8 x = BIT(op, 15, 5); + const u8 ps = BIT(op, 13, 2); + + const u8 z = BIT(op, 7, 5); + + const bool pd = BIT(op, 4); + const bool pz = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + if (pz | py | px) + UNIMPLEMENTED("MC: P*"); + + if (pd || x == 0x1f) mreg_r(); + kop(kop2 << 1, fd, R(x), kop2 ? R(y) : R(x), R(z), ps); + if (pd || z == 0x1f) mreg_w(); +} + +void kl1839vm1_device::mk(u32 op) +{ + const bool ret = BIT(op, 17); + if (!ret) + { + RV = MCA; + } + + if ((op & 0xfe000000) == 0xe0000000) + { + if (BIT(~op, 16)) // madr == 0 + { + const u16 addr = BIT(op, 2, 14); + MCA = addr; + } + else + { + u16 addr_hi = BIT(op, 8, 8) << 6; + MCA = addr_hi | (R(0x18) & 0x3f); + } + } + else if ((op & 0xfe000000) == 0xe2000000) + { + u16 addr_hi = BIT(op, 8, 8) << 6; + //u8 rpp = BIT(op, 2, 4); // TODO rpp irq code + MCA = addr_hi; + } +} + +void kl1839vm1_device::yp(u32 op) +{ + const bool uv = BIT(op, 28); + const bool n = BIT(op, 27); + const bool z = BIT(op, 26); + const bool v = BIT(op, 25); + const bool c = BIT(op, 24); + const bool fp = BIT(op, 23); + //const bool fpd = BIT(op, 22); + //const bool prb = BIT(op, 21); + //const bool rst = BIT(op, 20); + //const bool rd = BIT(op, 19); + const bool ret = BIT(op, 17); + const bool zhs = BIT(op, 16); + const u16 addr = BIT(op, 2, 14); + + bool jump = false; + if (fp) + { + jump = uv == m_fp; + } + else + { + const u8 mask = (n << 3) | (z << 2) | (v << 1) | (c << 0); + const u8 reg = zhs ? RSP : PSW; + jump = uv ? ((reg & mask) != 0) : ((reg & mask) == 0); + } + + if (jump) + { + if (!ret) + { + RV = MCA; + } + MCA = addr; + } +} + +void kl1839vm1_device::zsch(u32 op) +{ + const bool madr = BIT(op, 16); + if (madr) + { + const u8 cnst_hi = BIT(op, 8, 2) << 6; + SCH = cnst_hi | (R(0x18) & 0x3f); + } + else + { + const u8 cnst = BIT(op, 2, 8); + SCH = cnst; + } +} + +void kl1839vm1_device::psch(u32 op) +{ + const bool madr = BIT(op, 16); + if (madr) + { + const u16 addr_hi = BIT(op, 8, 8) << 6; + MCA = addr_hi | (R(0x18) & 0x3f); + } + else + { + if (SCH--) + { + const u16 addr = BIT(op, 2, 14); + MCA = addr; + } + + } +} + +void kl1839vm1_device::rts(u32 op) +{ + MCA = RV; +} + +void kl1839vm1_device::acc(u32 op) +{ + UNIMPLEMENTED("ACC"); +} + +void kl1839vm1_device::chka(u32 op) +{ + const bool madr = BIT(op, 16); + if (madr) + { + const u16 addr_hi = BIT(op, 8, 8) << 6; + RC = m_microcode.read_dword(addr_hi | (R(0x18) & 0x3f)); + } + else + { + const u16 addr = BIT(op, 2, 14); + RC= m_microcode.read_dword(addr); + } +} + +void kl1839vm1_device::chlk(u32 op) +{ + const bool sb = BIT(op, 1); + const u32 cnst = BIT(op, 2, 24); + RC = (sb * 0xff000000) | cnst; +} + +void kl1839vm1_device::srf(u32 op) +{ + if (BIT(op, 25)) // WIMM + { + UNIMPLEMENTED("SRF: WIMM"); + } + if (BIT(op, 21)) // SFP1 + { + m_fp = true; + } + if (BIT(op, 20)) // RFP1 + { + m_fp = false; + } + if (BIT(op, 5)) // DEC + { + UNIMPLEMENTED("SRF: DEC"); + } + if (BIT(op, 4)) // OCT + { + --MCA; + } + if (BIT(op, 2)) // JDZRA + { + UNIMPLEMENTED("SRF: JDZRA"); + } + if (BIT(op, 1)) // INC + { + UNIMPLEMENTED("SRF: INC"); + } +} + +void kl1839vm1_device::invalid(u32 op) +{ +} + +void kl1839vm1_device::kob_process(u8 no, u8 fo, u8 kob, u32 data) +{ + switch (kob) { + case 0b001: // Data Read + case 0b010: // Data Write + case 0b011: // Read-Modify-Write + m_vma_tmp.d = (no << 30) | (fo << 28) | (kob << 24) | data; + break; + case 0b100: // Write Accum R(17) + case 0b101: // Read Command + case 0b110: // Offset Write + UNIMPLEMENTED("KOB"); + break; + + case 0b000: // NOP + case 0b111: // Reserve + default: break; + } +} + +void kl1839vm1_device::decode_op(u32 op) +{ + if ((op & 0xc0000000) == 0x00000000) // MA + { + if ((op & 0xff000000) == 0x01000000) + flag(op); + else if ((op & 0xff000000) == 0x05000000) + rest(op); + else + ma(op); + } + else if ((op & 0xc0000000) == 0x40000000) // MB + { + mb(op); + } + else if ((op & 0xc0000000) == 0x80000000) // MC + { + mc(op); + } + else + { + if ((op & 0xfc000000) == 0xe0000000) + mk(op); + else if ((op & 0xe0000000) == 0xc0000000) + yp(op); + else if ((op & 0xfc000000) == 0xec000000) + zsch(op); + else if ((op & 0xfc000000) == 0xe4000000) + psch(op); + else if ((op & 0xfc000000) == 0xf0000000) + rts(op); + else if ((op & 0xfc000000) == 0xe8000000) + acc(op); + else if ((op & 0xfc000000) == 0xf4000000) + chka(op); + else if ((op & 0xfc000000) == 0xf8000000) + chlk(op); + else if ((op & 0xfc000000) == 0xfc000000) + srf(op); + else + invalid(op); + } +} + +void kl1839vm1_device::device_start() +{ + space(AS_OPCODES).cache(m_microcode); + space(AS_DATA).specific(m_sysram); + space(AS_PROGRAM).specific(m_ram); + space(AS_IO).specific(m_io); + + save_item(NAME(m_mca)); + save_item(NAME(m_vma)); + save_item(NAME(m_vma_tmp)); + save_item(NAME(m_rv)); + save_item(NAME(m_sch)); + save_item(NAME(m_rsp)); + save_item(NAME(m_ppc)); + save_item(NAME(m_fp)); + save_pointer(NAME(m_reg), 0x20); + save_pointer(NAME(m_consts), 0x10); + + // Register debugger state + state_add(KL1839_MCA, "MCA", MCA).formatstr("%04X"); + state_add(KL1839_VMA, "VMA", VMA).formatstr("%08X"); + state_add_divider(-1); + state_add(KL1839_IF, "cond", m_fp).formatstr("%08s"); + state_add(KL1839_RSP, "RSP", RSP).formatstr("%08s"); + state_add(KL1839_PCM, "PCM", PCM).formatstr("%08X"); + state_add(KL1839_RC, "RC", RC).formatstr("%08X"); + state_add(KL1839_RV, "RV", RV).formatstr("%08X"); + state_add(KL1839_SCH, "SCH", SCH).formatstr("%02X"); + state_add_divider(-1); + state_add(VAX_AP, "AP", AP).formatstr("%08X"); + state_add(VAX_FP, "FP", FP).formatstr("%08X"); + state_add(VAX_SP, "SP", SP).formatstr("%08X"); + state_add(VAX_PC, "PC", PC).formatstr("%08X"); + state_add_divider(-1); + state_add(VAX_R0, "R0", R(0)).formatstr("%08X"); + state_add(VAX_R1, "R1", R(1)).formatstr("%08X"); + state_add(VAX_R2, "R2", R(2)).formatstr("%08X"); + state_add(VAX_R3, "R3", R(3)).formatstr("%08X"); + state_add(VAX_R4, "R4", R(4)).formatstr("%08X"); + state_add(VAX_R5, "R5", R(5)).formatstr("%08X"); + state_add(VAX_R6, "R6", R(6)).formatstr("%08X"); + state_add(VAX_R7, "R7", R(7)).formatstr("%08X"); + state_add(VAX_R8, "R8", R(8)).formatstr("%08X"); + state_add(VAX_R9, "R9", R(9)).formatstr("%08X"); + state_add(VAX_RA, "RA", R(0x0a)).formatstr("%08X"); + state_add(VAX_RB, "RB", R(0x0b)).formatstr("%08X"); + state_add_divider(-1); + state_add(VAX_AK0, "AK0", R(0x14)).formatstr("%08X"); + state_add(VAX_AK1, "AK1", R(0x15)).formatstr("%08X"); + state_add(VAX_AK2, "AK2", R(0x16)).formatstr("%08X"); + state_add(VAX_AK3, "AK3", R(0x12)).formatstr("%08X"); + state_add(VAX_AK4, "AK4", R(0x11)).formatstr("%08X"); + state_add(VAX_AK5, "AK5", R(0x13)).formatstr("%08X"); + state_add(VAX_AK6, "AK6", R(0x17)).formatstr("%08X"); + state_add(VAX_AK7, "AK7", R(0x18)).formatstr("%08X"); + state_add(VAX_AK8, "AK8", R(0x10)).formatstr("%08X"); + state_add_divider(-1); + state_add(VAX_RNK, "RNK", RNK).formatstr("%08X"); + state_add(VAX_RKA, "RKA", RKA).formatstr("%08X"); + state_add(VAX_PSL, "PSL", PSL).formatstr("%08X"); + state_add(VAX_BO, "BO", BO).formatstr("%08X"); + + state_add(STATE_GENPC, "GENPC", MCA).noshow(); // ??? + state_add(STATE_GENPCBASE, "CURPC", m_ppc.d).noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", PSW).formatstr("%8s").noshow(); + + set_icountptr(m_icount); +} + +void kl1839vm1_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + str = string_format("%c%c%c%c%c%c%c%c", + PSW & 0x80 ? '?' : '.', + PSW & 0x40 ? '?' : '.', + PSW & 0x20 ? '?' : '.', + PSW & 0x10 ? '?' : '.', + PSW & NF ? 'N' : '.', + PSW & ZF ? 'Z' : '.', + PSW & VF ? 'V' : '.', + PSW & CF ? 'C' : '.' + ); + break; + case KL1839_RSP: + str = string_format("%c%c%c%c%c%c%c%c", + RSP & 0x80 ? '?' : '.', + RSP & 0x40 ? '?' : '.', + RSP & 0x20 ? '?' : '.', + RSP & 0x10 ? '?' : '.', + RSP & NF ? 'N' : '.', + RSP & ZF ? 'Z' : '.', + RSP & VF ? 'V' : '.', + RSP & CF ? 'C' : '.' + ); + break; + case KL1839_IF: + str = string_format("FP%d", m_fp); + break; + } +} + +void kl1839vm1_device::device_reset() +{ + for (auto ® : m_reg) + reg.d = 0; + + m_ppc.d = MCA = 0x2000; + VMA = 0; + m_fp = false; + RSP = 0; + m_vma_tmp.d = 0; + RV = 0; + SCH = 0; +} + +void kl1839vm1_device::execute_set_input(int irqline, int state) +{ +} + +void kl1839vm1_device::execute_run() +{ + do + { + m_ppc.d = MCA; + debugger_instruction_hook(m_ppc.d); + + u32 op = m_microcode.read_dword(MCA); + m_icount -= 2; + ++MCA &= 0x3fff; + + decode_op(op); + } while (m_icount > 0); +} + +std::unique_ptr<util::disasm_interface> kl1839vm1_device::create_disassembler() +{ + return std::make_unique<kl1839vm1_disassembler>(); +} + diff --git a/src/devices/cpu/mpk1839/kl1839vm1.h b/src/devices/cpu/mpk1839/kl1839vm1.h new file mode 100644 index 00000000000..4723dc89ffe --- /dev/null +++ b/src/devices/cpu/mpk1839/kl1839vm1.h @@ -0,0 +1,94 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub + +#ifndef MAME_CPU_MPK1839_KL1839VM1_H +#define MAME_CPU_MPK1839_KL1839VM1_H + +#pragma once + + +enum +{ + KL1839_MCA = STATE_GENPC, KL1839_VMA, KL1839_IF, KL1839_RSP, KL1839_PCM, KL1839_RC, KL1839_RV, KL1839_SCH, + VAX_R0, VAX_R1, VAX_R2, VAX_R3, VAX_R4, VAX_R5, VAX_R6, VAX_R7, VAX_R8, VAX_R9, VAX_RA, VAX_RB, + VAX_AP, VAX_FP, VAX_SP, VAX_PC, + VAX_AK0, VAX_AK1, VAX_AK2, VAX_AK3, VAX_AK4, VAX_AK5, VAX_AK6, VAX_AK7, VAX_AK8, + VAX_RNK, VAX_RKA, VAX_PSL, VAX_BO +}; + + +class kl1839vm1_device : public cpu_device +{ +public: + // construction/destruction + kl1839vm1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + // device_execute_interface overrides + virtual u32 execute_min_cycles() const noexcept override { return 1; } + virtual u32 execute_max_cycles() const noexcept override { return 16; } + virtual u32 execute_input_lines() const noexcept override { return 1; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + +private: + void flag(u32 op); + void rest(u32 op); + void ma(u32 op); + void mb(u32 op); + void mc(u32 op); + void mk(u32 op); + void yp(u32 op); + void zsch(u32 op); + void psch(u32 op); + void rts(u32 op); + void acc(u32 op); + void chka(u32 op); + void chlk(u32 op); + void srf(u32 op); + void invalid(u32 op); + + u32 shr(u32 val, bool va, u8 fo, bool a_c, bool l_r); + void kob_process(u8 no, u8 fd, u8 kob, u32 data); + void kop(u8 kop, u8 fd, u32 x, u32 y, u32 &z, u8 ps, bool va, u8 fo); + void mreg_w(); + void mreg_r(); + void decode_op(u32 op); + + address_space_config m_microcode_config; + address_space_config m_sysram_config; + address_space_config m_ram_config; + address_space_config m_io_config; + + memory_access<14, 2, -2, ENDIANNESS_BIG>::cache m_microcode; + memory_access<24, 0, 0, ENDIANNESS_BIG>::specific m_sysram; + memory_access<24, 0, 0, ENDIANNESS_LITTLE>::specific m_ram; + memory_access<6, 2, -2, ENDIANNESS_LITTLE>::specific m_io; + PAIR m_mca; + PAIR m_vma; + PAIR m_vma_tmp; // does we have int reg for this? + PAIR m_rv; + PAIR m_sch; + PAIR m_rsp; + PAIR m_ppc; // previous program counter + bool m_fp; + u32 m_consts[0x10] = { 0x4, 0x2, 0x8, 0x1, 0x0, 0, 0, 0x66, 0, 0xc00000, 0xffffffff, 0x1f0000, 0x4000000, 0, 0, 0 }; + PAIR m_reg[0x20]; + int m_icount; +}; + +DECLARE_DEVICE_TYPE(KL1839VM1, kl1839vm1_device) + +#endif // MAME_CPU_MPK1839_KL1839VM1_H diff --git a/src/devices/cpu/mpk1839/kl1839vm1dasm.cpp b/src/devices/cpu/mpk1839/kl1839vm1dasm.cpp new file mode 100644 index 00000000000..1b9ad4e7dc1 --- /dev/null +++ b/src/devices/cpu/mpk1839/kl1839vm1dasm.cpp @@ -0,0 +1,441 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/*************************************************************************** + KL1839VM1 disassembler +***************************************************************************/ + +#include "emu.h" +#include "kl1839vm1dasm.h" + +static const std::string r_name(u8 id) +{ + std::ostringstream ss; + switch (id) + { + case 0x14: ss << "AK0"; break; + case 0x15: ss << "AK1"; break; + case 0x16: ss << "AK2"; break; + case 0x12: ss << "AK3"; break; + case 0x11: ss << "AK4"; break; + case 0x13: ss << "AK5"; break; + case 0x17: ss << "AK6"; break; + case 0x18: ss << "AK7"; break; + case 0x10: ss << "AK8"; break; + case 0x1f: ss << "BO"; break; + default: util::stream_format(ss, "R(%02X)", id); break; + } + return ss.str(); +} + +static const std::string k_name(u8 id) +{ + std::ostringstream ss; + switch (id) + { + case 0x05: ss << "PCM"; break; + case 0x06: ss << "RC"; break; + default: util::stream_format(ss, "K(%X)", id); break; + } + return ss.str(); +} + +static const void m_base(std::ostream &stream, u32 op, char m, u8 kop, std::string x, std::string y, std::string z) +{ + const u8 fd = BIT(op, 28, 2); + const u8 ps = BIT(op, 13, 2); + const bool pd = BIT(op, 4); + + util::stream_format(stream, "M%c%-2s :", m, ""); + std::ostringstream ss; + switch(fd) + { + case 0b00: ss << "DS/"; break; + case 0b01: ss << "SL/"; break; + case 0b11: ss << "BT/"; break; + default: break; // 0b10 + } + switch(kop) + { + case 0b0000: ss << y << "=>" << z; break; + case 0b0010: ss << x << "+" << y << "=>" << z; break; + case 0b0011: ss << x << "=>" << z; break; + case 0b0100: ss << x << "-" << y << "=>" << z; break; + case 0b0110: ss << y << "-" << x << "=>" << z; break; + case 0b0111: ss << x << "=>!" << x; break; + case 0b1000: ss << x << "(+)" << y << "=>" << z; break; + case 0b1001: ss << "AL" << x; break; + case 0b1010: ss << x << "'" << y << "=>" << z; break; + case 0b1011: ss << "CL" << x; break; + case 0b1100: ss << x << "&!" << y << "=>" << z; break; + case 0b1101: ss << "AP" << x; break; + case 0b1110: ss << x << "&" << y << "=>" << z; break; + case 0b1111: ss << "CP" << x; break; + default: break; // 0b0001, 0b0101 - reserved + } + util::stream_format(stream, "%-24s;", ss.str()); + + stream << (pd ? "PD " : ""); + + switch(ps) + { + case 0b00: stream << "ZS "; break; + case 0b01: stream << "MS "; break; + case 0b10: stream << "NV "; break; + default: break; // 0b11 - no state store + } +} + +static const void ma(std::ostream &stream, u32 op) +{ + const u8 kop1 = BIT(op, 24, 4); + const u8 am = BIT(op, 20, 4); + const u8 x = BIT(op, 15, 5); + const bool va = BIT(op, 12); + const u8 no = BIT(op, 10, 2); + const u8 fo = BIT(op, 8, 2); + const u8 kob = BIT(op, 5, 3); + const bool po = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + m_base(stream, op, 'A', kop1, r_name(x), k_name(am), r_name(x)); + + if (kob) + { + stream << (va ? "AZ " : "A4 "); + + switch(no) + { + case 0b00: break; + case 0b01: stream << "PP "; break; + case 0b10: stream << "SR "; break; + case 0b11: stream << "SP "; break; + default: break; + } + + switch(fo) + { + case 0b00: stream << "DSO "; break; + case 0b01: stream << "SLO "; break; + case 0b10: stream << "4SO "; break; + case 0b11: stream << "BO "; break; + default: break; + } + + switch(kob) + { + case 0b000: break; + case 0b001: stream << "4D "; break; + case 0b010: stream << "ZD "; break; + case 0b011: stream << "4Z "; break; + case 0b100: stream << "?R(17)==ACC "; break; + case 0b101: stream << "4K "; break; + case 0b110: break; // reserved + case 0b111: stream << "BRD "; break; + default: break; + } + } + + if (px | po | py) + stream << "?:" << (px ? "PX " : "") << (po ? "PO " : "") << (py ? "PY " : ""); +} + +static const void mb(std::ostream &stream, u32 op) +{ + const u8 kop2 = BIT(op, 25, 3); + const u8 y = BIT(op, 20, 5); + const u8 x = BIT(op, 15, 5); + const u8 ps = BIT(op, 13, 2); + const bool va = BIT(op, 12); + const u8 no = BIT(op, 10, 2); + const u8 fo = BIT(op, 8, 2); + const u8 kob = BIT(op, 5, 3); + const bool pz = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + m_base(stream, op, 'B', kop2 << 1, r_name(x), r_name(y), r_name(x)); + + if (kob) + { + stream << (va ? "AZ " : "A4 "); + + switch(ps) + { + case 0b00: stream << "ZS "; break; + case 0b01: stream << "MS "; break; + case 0b10: stream << "NV "; break; + default: break; // 0b11 - no state store + } + + switch(no) + { + case 0b00: break; + case 0b01: stream << "PP "; break; + case 0b10: stream << "SR "; break; + case 0b11: stream << "SP "; break; + default: break; + } + + switch(fo) + { + case 0b00: stream << "DSO "; break; + case 0b01: stream << "SLO "; break; + case 0b10: stream << "4SO "; break; + case 0b11: stream << "BO "; break; + default: break; + } + + switch(kob) + { + case 0b000: break; + case 0b001: stream << "4D "; break; + case 0b010: stream << "ZD "; break; + case 0b011: stream << "4Z "; break; + case 0b100: stream << "?R(17)==ACC "; break; + case 0b101: stream << "4K "; break; + case 0b110: break; // reserved + case 0b111: stream << "BRD "; break; + default: break; + } + } + + if (px | pz | py) + stream << "?:" << (px ? "PX " : "") << (pz ? "PZ " : "") << (py ? "PY " : ""); +} + +static const void mc(std::ostream &stream, u32 op) +{ + const u8 kop2 = BIT(op, 25, 3); + const u8 y = BIT(op, 20, 5); + const u8 x = BIT(op, 15, 5); + const u8 z = BIT(op, 7, 5); + const bool pz = BIT(op, 3); + const bool py = BIT(op, 2); + const bool px = BIT(op, 1); + + m_base(stream, op, 'C', kop2 << 1, r_name(x), kop2 ? r_name(y) : r_name(x), r_name(z)); + + if (px | pz | py) + stream << "?:" << (px ? "PX " : "") << (pz ? "PZ " : "") << (py ? "PY " : ""); +} + +static const u32 mk(std::ostream &stream, u32 op) +{ + const bool ret = BIT(op, 17); + if ((op & 0xfe000000) == 0xe0000000) + { + if (BIT(~op, 16)) // madr == 0 + { + const u16 addr = BIT(op, 2, 14); + util::stream_format(stream, "BP%s : ;A=%04X", ret ? " " : "B" ,addr); + } + else + { + stream << "??MK-2"; + } + } + else if ((op & 0xfe000000) == 0xe2000000) + { + stream << "??MK-3"; + } + + return ret ? 0 : kl1839vm1_disassembler::STEP_OVER; +} + +static const u32 yp(std::ostream &stream, u32 op) +{ + const bool uv = BIT(op, 28); + const bool n = BIT(op, 27); + const bool z = BIT(op, 26); + const bool v = BIT(op, 25); + const bool c = BIT(op, 24); + const bool fp = BIT(op, 23); + const bool fpd = BIT(op, 22); + const bool prb = BIT(op, 21); + const bool rts = BIT(op, 20); + const bool rd = BIT(op, 19); + const bool ret = BIT(op, 17); + const bool js = BIT(op, 16); + const u16 addr = BIT(op, 2, 14); + if (fp) + { + util::stream_format(stream, "YPF%s : ", uv); + } + else if (fpd) + util::stream_format(stream, "YPFPD :", uv); + else + { + util::stream_format(stream, "YP%s%s :", uv , (js ? "JS" : " ")); + stream << (n ? "N" : ""); + stream << (z ? "Z" : ""); + stream << (v ? "V" : ""); + stream << (c ? "C" : ""); + } + + util::stream_format(stream, " ;A=%04X", addr); + + if (prb | rts | rd) + stream << " ?:" << (prb ? "PRB " : "") << (rts ? "RTS " : "") << (rd ? "RD " : ""); + + return ret ? 0 : kl1839vm1_disassembler::STEP_OVER; +} + +static const void zsch(std::ostream &stream, u32 op) +{ + stream << "ZS4 :"; + if (BIT(~op, 16)) // mcc == 0 + { + const u8 cnst = BIT(op, 2, 8); + util::stream_format(stream, "S4=K(%02X) ;", cnst); + } + else + { + //const u8 cnst = BIT(op, 8, 2); + const u8 obb = BIT(op, 2, 6); + util::stream_format(stream, "S4=K(%04X) ;", obb); + } +} + +static const void psch(std::ostream &stream, u32 op) +{ + stream << "PS4 :"; + if (BIT(~op, 16)) // madr == 0 + { + const u8 addr = BIT(op, 2, 14); + util::stream_format(stream, " ;A=%04X", addr); + } + else + { + stream << "..."; + } +} + +static const void rts(std::ostream &stream, u32 op) +{ + stream << "RTS : ;"; +} + +static const void acc(std::ostream &stream, u32 op) +{ + stream << "ACC : ;"; +} + +static const void chka(std::ostream &stream, u32 op) +{ + stream << "4KA :"; + if (BIT(~op, 16)) // madr == 0 + { + const u16 addr = BIT(op, 2, 14); + util::stream_format(stream, " ;A=%04X", addr); + } + else + { + stream << "??"; + } +} + +static const void chlk(std::ostream &stream, u32 op) +{ + const bool sb = BIT(op, 1); + const u32 cnst = BIT(op, 2, 24); + util::stream_format(stream, "4LK :SB%X/K(%06X) ;", sb, cnst); +} + +static const void srf(std::ostream &stream, u32 op) +{ + if (!BIT(op, 1, 25)) + { + stream << "NOP : ;"; + } + else if (BIT(op, 4)) + { + stream << "OCT : ;"; + } + else + { + stream << "SRF : ;"; + stream << (BIT(op, 25) ? "WIMM " : ""); + stream << (BIT(op, 21) ? "SFP1 " : ""); + stream << (BIT(op, 20) ? "RFP1 " : ""); + stream << (BIT(op, 5) ? "DEC " : ""); + stream << (BIT(op, 2) ? "JDZRA " : ""); + stream << (BIT(op, 1) ? "INC " : ""); + } +} + +static const void flag(std::ostream &stream, u32 op) +{ + stream << "FLAG : ;"; + stream << (BIT(op, 23) ? "INTMS " : ""); + stream << (BIT(op, 22) ? "RCPU " : ""); + stream << (BIT(op, 21) ? "SIVV " : ""); + stream << (BIT(op, 20) ? "CCFPU " : ""); + stream << (BIT(op, 19) ? "PROB " : ""); + stream << (BIT(op, 17) ? "SIU " : ""); + stream << (BIT(op, 16) ? "TOU " : ""); + stream << (BIT(op, 15) ? "COPWT " : ""); +} + +static const void rest(std::ostream &stream, u32 op) +{ + stream << "REST : ;"; +} + +offs_t kl1839vm1_disassembler::disassemble(std::ostream &stream, offs_t pc, const kl1839vm1_disassembler::data_buffer &opcodes, const kl1839vm1_disassembler::data_buffer ¶ms) +{ + u32 op = opcodes.r32(pc); + u32 step = 0; + if ((op & 0xc0000000) == 0x00000000) // MA + { + if ((op & 0xff000000) == 0x01000000) + flag(stream, op); + else if ((op & 0xff000000) == 0x05000000) + rest(stream, op); + else + ma(stream, op); + } + else if ((op & 0xc0000000) == 0x40000000) // MB + { + mb(stream, op); + } + else if ((op & 0xc0000000) == 0x80000000) // MC + { + mc(stream, op); + } + else + { + if ((op & 0xfc000000) == 0xe0000000) + { + step |= mk(stream, op); + } + else if ((op & 0xe0000000) == 0xc0000000) + { + step |= yp(stream, op) | STEP_COND; + } + else if ((op & 0xfc000000) == 0xec000000) + zsch(stream, op); + else if ((op & 0xfc000000) == 0xe4000000) + { + psch(stream, op); + step |= STEP_COND; + } + else if ((op & 0xfc000000) == 0xf0000000) + { + rts(stream, op); + step |= STEP_OUT; + } + else if ((op & 0xfc000000) == 0xe8000000) + acc(stream, op); + else if ((op & 0xfc000000) == 0xf4000000) + chka(stream, op); + else if ((op & 0xfc000000) == 0xf8000000) + chlk(stream, op); + else if ((op & 0xfc000000) == 0xfc000000) + srf(stream, op); + else + stream << "<invalid>"; + } + + return 1 | SUPPORTED | step; +} diff --git a/src/devices/cpu/mpk1839/kl1839vm1dasm.h b/src/devices/cpu/mpk1839/kl1839vm1dasm.h new file mode 100644 index 00000000000..3d13d90a1ae --- /dev/null +++ b/src/devices/cpu/mpk1839/kl1839vm1dasm.h @@ -0,0 +1,25 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub + +#ifndef MAME_CPU_MPK1839_KL1839VM1DASM_H +#define MAME_CPU_MPK1839_KL1839VM1DASM_H + +#pragma once + +class kl1839vm1_disassembler : public util::disasm_interface +{ +public: + // construction/destruction + kl1839vm1_disassembler() = default; + virtual ~kl1839vm1_disassembler() = default; + +protected: + // disassembler overrides + virtual u32 opcode_alignment() const override { return 1; } + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + +private: + +}; + +#endif // MAME_CPU_MPK1839_KL1839VM1DASM_H |