ussr/pk32.cpp: Electronika PK-32 - not working (#12732)

mpl1839/kl1839vm1.cpp: MPL's l1839vm1 cpu device
This commit is contained in:
holub 2024-09-19 21:23:11 -04:00 committed by GitHub
parent d49d4e00c2
commit d8761b090c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1467 additions and 0 deletions

View File

@ -1413,6 +1413,23 @@ if opt_tool(CPUS, "DIABLO") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/diablo/diablo1300dasm.h")
end
--------------------------------------------------
-- KL1839VM1
--@src/devices/cpu/mpk1839/kl1839vm1.h,CPUS["KL1839VM1"] = true
--------------------------------------------------
if CPUS["KL1839VM1"] then
files {
MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1.cpp",
MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1.h",
}
end
if opt_tool(CPUS, "KL1839VM1") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1dasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1dasm.h")
end
--------------------------------------------------
-- Fujitsu MB88xx
--@src/devices/cpu/mb88xx/mb88xx.h,CPUS["MB88XX"] = true

View File

@ -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 &reg : 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>();
}

View File

@ -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

View File

@ -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 &params)
{
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;
}

View File

@ -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 &params) override;
private:
};
#endif // MAME_CPU_MPK1839_KL1839VM1DASM_H

View File

@ -46054,6 +46054,9 @@ orionzms //
@source:ussr/partner.cpp
partner //
@source:ussr/pk32.cpp
pk32 // (c) 1991 Elektronika, USSR
@source:ussr/pk8000.cpp
hobby //
pk8002 //

199
src/mame/ussr/pk32.cpp Normal file
View File

@ -0,0 +1,199 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
/**********************************************************************
Elektronika PK-32
**********************************************************************/
#include "emu.h"
#include "cpu/mpk1839/kl1839vm1.h"
#include "machine/ram.h"
#include "machine/terminal.h"
#define LOG_IO (1U << 1)
#define LOG_MEM (1U << 2)
#define LOG_TERM (1U << 3)
#define VERBOSE ( LOG_GENERAL /*| LOG_IO | LOG_MEM | LOG_TERM*/ )
#include "logmacro.h"
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
#define LOGMEM(...) LOGMASKED(LOG_MEM, __VA_ARGS__)
#define LOGTERM(...) LOGMASKED(LOG_TERM, __VA_ARGS__)
namespace {
class pk32_state : public driver_device
{
public:
pk32_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_terminal(*this, "terminal")
, m_io_rnp(*this, "RNP")
{}
void pk32(machine_config &config);
protected:
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
private:
void pk32_map_microcode(address_map &map);
void pk32_map_sysram(address_map &map);
void pk32_map_ram(address_map &map);
void pk32_map_io(address_map &map);
required_device<kl1839vm1_device> m_maincpu;
required_device<ram_device> m_ram;
required_device<generic_terminal_device> m_terminal;
required_ioport m_io_rnp; // Initial Start Register
u32 term_rx_db_r();
void term_tx_db_w(u32 data);
u32 term_rx_cs_r();
void term_rx_cs_w(u32 data);
u32 term_tx_cs_r();
void term_tx_cs_w(u32 data);
void kbd_put(u8 data);
u8 m_term_data = 0;
u16 m_term_status = 0;
};
u32 pk32_state::term_rx_db_r()
{
LOGTERM("RX DB -> %X\n", m_term_data);
m_term_status = 0x00;
return m_term_data;
}
void pk32_state::term_tx_db_w(u32 data)
{
LOGTERM("RX DB <- %X\n", data);
m_terminal->write(data);
}
u32 pk32_state::term_rx_cs_r()
{
//LOGTERM("RX CS -> %X\n", m_term_status);
return m_term_status;
}
void pk32_state::term_rx_cs_w(u32 data)
{
LOGTERM("RX CS <- %X\n", data);
m_term_status = data;
}
u32 pk32_state::term_tx_cs_r()
{
LOGTERM("TX CS -> %X\n", 0xff);
// always ready
return 0xff;
}
void pk32_state::term_tx_cs_w(u32 data)
{
LOGTERM("TX CS <- %X\n", data);
}
void pk32_state::pk32_map_microcode(address_map &map)
{
map(0x0000, 0x3fff).rom().region("microcode", 0);
}
void pk32_state::pk32_map_sysram(address_map &map)
{
map(0x000000, 0x001fff).ram();
map(0x800000, 0x800000).lr8(NAME([this](offs_t offset) { return m_io_rnp->read() | ((m_ram->size() >> 20) - 1); }));
}
void pk32_state::pk32_map_ram(address_map &map)
{
map(0x000000, 0xffffff).ram();
}
void pk32_state::pk32_map_io(address_map &map)
{
map.unmap_value_high();
map(0x00, 0x3f).unmaprw();
map(0x20, 0x20).r(FUNC(pk32_state::term_rx_cs_r)).w(FUNC(pk32_state::term_rx_cs_w));
map(0x21, 0x21).r(FUNC(pk32_state::term_rx_db_r));
map(0x22, 0x22).r(FUNC(pk32_state::term_tx_cs_r)).w(FUNC(pk32_state::term_tx_cs_w));
map(0x23, 0x23).w(FUNC(pk32_state::term_tx_db_w));
}
/* Input ports */
static INPUT_PORTS_START( pk32 )
PORT_START("RNP")
PORT_CONFNAME( 0xf0, 0x10, "Boot" )
PORT_CONFSETTING(0x00, "Terminal w/ test")
PORT_CONFSETTING(0x10, "Terminal w/o test")
PORT_CONFSETTING(0x20, "OS from MSCP w/ test")
PORT_CONFSETTING(0x30, "OS from MSCP w/o test")
PORT_CONFSETTING(0x40, "OS from user's device w/ test")
PORT_CONFSETTING(0x50, "User's program from 0")
PORT_CONFSETTING(0x60, "Resident devices")
PORT_CONFSETTING(0x80, "Accelerator ON")
INPUT_PORTS_END
void pk32_state::kbd_put(u8 data)
{
m_term_data = data;
m_term_status = 0xff;
}
void pk32_state::machine_start()
{
save_item(NAME(m_term_data));
save_item(NAME(m_term_status));
}
void pk32_state::machine_reset()
{
}
void pk32_state::pk32(machine_config &config)
{
/* basic machine hardware */
KL1839VM1(config, m_maincpu, XTAL(10'000'000));
m_maincpu->set_addrmap(AS_OPCODES, &pk32_state::pk32_map_microcode);
m_maincpu->set_addrmap(AS_DATA, &pk32_state::pk32_map_sysram);
m_maincpu->set_addrmap(AS_PROGRAM, &pk32_state::pk32_map_ram);
m_maincpu->set_addrmap(AS_IO, &pk32_state::pk32_map_io);
RAM(config, m_ram).set_default_size("16M").set_extra_options("8M,4M");
/* video hardware */
GENERIC_TERMINAL(config, m_terminal, 0);
m_terminal->set_keyboard_callback(FUNC(pk32_state::kbd_put));
}
ROM_START(pk32)
ROM_REGION32_BE(0x10000, "microcode", ROMREGION_ERASE00)
ROM_DEFAULT_BIOS("v1")
ROM_SYSTEM_BIOS(0, "v1", "1839src)")
ROMX_LOAD("fw-1839-src.bin", 0x0000, 0x10000, CRC(78c4d298) SHA1(eb3828718991968b4121e6819ae4c6859a8a3a5a), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v2", "1839isa")
ROMX_LOAD("fw-1839-isa.bin", 0x0000, 0x10000, CRC(180930a7) SHA1(dbcc7d665d28011b9c2beba3cc0e4073f34d7fc6), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "v3", "1839pe1")
ROMX_LOAD("fw-1839pe1-006.bin", 0x0000, 0x10000, CRC(e6bb7639) SHA1(759993afc9b61d9cf83acf3e361dcec571beccf1), ROM_BIOS(2))
ROM_END
} // Anonymous namespace
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1991, pk32, 0, 0, pk32, pk32, pk32_state, empty_init, "Elektronika", "PK-32", MACHINE_NOT_WORKING)

View File

@ -129,6 +129,7 @@ using util::BIT;
#include "cpu/mn1610/mn1610d.h"
#include "cpu/mn1880/mn1880d.h"
#include "cpu/mn10200/mn102dis.h"
#include "cpu/mpk1839/kl1839vm1dasm.h"
#include "cpu/msm65x2/msm65x2d.h"
#include "cpu/nanoprocessor/nanoprocessor_dasm.h"
#include "cpu/nec/necdasm.h"
@ -508,6 +509,7 @@ static const dasm_table_entry dasm_table[] =
{ "jaguargpu", be, 0, []() -> util::disasm_interface * { return new jaguar_disassembler(jaguar_disassembler::variant::GPU); } },
{ "konami", be, 0, []() -> util::disasm_interface * { return new konami_disassembler; } },
{ "ks0164", be, 0, []() -> util::disasm_interface * { return new ks0164_disassembler; } },
{ "kl1839vm1", be, 0, []() -> util::disasm_interface * { return new kl1839vm1_disassembler; } },
{ "lc57", be, 0, []() -> util::disasm_interface * { return new lc57_disassembler; } },
{ "lc58", be, -1, []() -> util::disasm_interface * { return new lc58_disassembler; } },
{ "lc8670", be, 0, []() -> util::disasm_interface * { return new lc8670_disassembler; } },