mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
cpu/mpk1839/kl1839vm1.cpp: Improved VAX-11 code decoder in user space
This commit is contained in:
parent
38f49dbf31
commit
496d650c6b
@ -1424,6 +1424,8 @@ if CPUS["KL1839VM1"] then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/mpk1839/kl1839vm1.h",
|
||||
MAME_DIR .. "src/devices/cpu/vax/vaxdasm.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/vax/vaxdasm.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -5,22 +5,26 @@
|
||||
|
||||
#include "kl1839vm1.h"
|
||||
#include "kl1839vm1dasm.h"
|
||||
#include "cpu/vax/vaxdasm.h"
|
||||
#include <regex>
|
||||
|
||||
|
||||
#define VERBOSE ( LOG_GENERAL )
|
||||
#define LOG_VAX (1U << 1)
|
||||
|
||||
#define VERBOSE ( LOG_GENERAL | LOG_VAX )
|
||||
#include "logmacro.h"
|
||||
|
||||
#define UNIMPLEMENTED(msg) LOG("Unimplemented: %s\n", msg)
|
||||
#define LOGVAX(...) LOGMASKED(LOG_VAX, __VA_ARGS__)
|
||||
|
||||
#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 AMC m_amc.d // Microcode PC
|
||||
#define RV m_rv.d // Return Address
|
||||
#define SCH m_sch.b.l // Counter
|
||||
#define RSP m_rsp.b.l // Flags
|
||||
|
||||
#define K(x) m_consts[x & 0x0f]
|
||||
#define PCM K(5)
|
||||
#define RC K(6)
|
||||
#define RC K(6) // Constant
|
||||
|
||||
/* registers of various sizes */
|
||||
#define R(x) m_reg[x].d
|
||||
@ -65,8 +69,13 @@ device_memory_interface::space_config_vector kl1839vm1_device::memory_space_conf
|
||||
|
||||
void kl1839vm1_device::flag(u32 op)
|
||||
{
|
||||
const u8 copwt = BIT(op, 15, 1);
|
||||
const bool tou = BIT(op, 16);
|
||||
if (tou)
|
||||
{
|
||||
// TODO Stop BO till the end of DP (Memory Manager?)
|
||||
}
|
||||
|
||||
const bool copwt = BIT(op, 15);
|
||||
if (copwt)
|
||||
{
|
||||
RNK = PC;
|
||||
@ -94,7 +103,7 @@ u32 kl1839vm1_device::shr(u32 val, bool va, u8 fo, bool a_c, bool l_r)
|
||||
{
|
||||
case 0b00: left_bit = 31; break;
|
||||
case 0b01: left_bit = 15; break;
|
||||
case 0b10: left_bit = 31; break; // ??? dd
|
||||
case 0b10: left_bit = 31; break;
|
||||
case 0b11: left_bit = 7; break;
|
||||
}
|
||||
const u8 rd = l_r ? left_bit : 0;
|
||||
@ -105,14 +114,13 @@ u32 kl1839vm1_device::shr(u32 val, bool va, u8 fo, bool a_c, bool l_r)
|
||||
res &= ~(1 << wr);
|
||||
if (!a_c)
|
||||
{
|
||||
res |= (va ? (RSP & CF) : carry_out) << wr;
|
||||
res |= (va ? (PSW & 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)))
|
||||
{
|
||||
@ -121,23 +129,34 @@ u32 kl1839vm1_device::shr(u32 val, bool va, u8 fo, bool a_c, bool l_r)
|
||||
return res;
|
||||
}
|
||||
|
||||
void kl1839vm1_device::kop(u8 kop, u8 fd, u32 x, u32 y, u32 &z, u8 ps, bool va = false, u8 fo = 0)
|
||||
void kl1839vm1_device::kop(u8 kop, u8 fd, u32 x, u32 y, u8 rz, u8 ps, bool va = false, u8 fo = 0)
|
||||
{
|
||||
u32 res = 0;
|
||||
RSP &= ~(NF | ZF | VF);
|
||||
if ((kop & 0b1001) == 0b1001) // shr
|
||||
u64 res = 0;
|
||||
switch(fd)
|
||||
{
|
||||
RSP &= ~CF;
|
||||
case 0b11:
|
||||
x = s8(x);
|
||||
y = s8(y);
|
||||
break;
|
||||
case 0b01:
|
||||
x = s16(x);
|
||||
y = s16(y);
|
||||
break;
|
||||
case 0b00:
|
||||
default: // 0b10
|
||||
break;
|
||||
}
|
||||
|
||||
RSP &= ~(VF | CF);
|
||||
switch(kop)
|
||||
{
|
||||
case 0b0000: res = y; break;
|
||||
// 0b0001:
|
||||
case 0b0010: res = x + y; break;
|
||||
case 0b0010: res = u64(x) + y; break;
|
||||
case 0b0011: res = x; break;
|
||||
case 0b0100: res = x - y; break;
|
||||
case 0b0100: res = u64(x) - y; break;
|
||||
// 0b0101
|
||||
case 0b0110: res = y - x; break;
|
||||
case 0b0110: res = u64(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
|
||||
@ -150,40 +169,54 @@ void kl1839vm1_device::kop(u8 kop, u8 fd, u32 x, u32 y, u32 &z, u8 ps, bool va =
|
||||
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
|
||||
}
|
||||
// flags
|
||||
RSP &= ~(NF | ZF);
|
||||
RSP |= BIT(res, 31) ? NF : 0;
|
||||
RSP |= (res == 0) ? ZF : 0;
|
||||
if (kop && ((kop & 0b1001) == 0b0000)) // +/-
|
||||
{
|
||||
const bool sig_y = BIT(y, 31);
|
||||
const bool sig_x = BIT(x, 31);
|
||||
RSP |= (kop == 0b0010) // +
|
||||
? (((sig_y == sig_x) && (BIT(res, 31) != sig_y)) ? VF : 0)
|
||||
: (((sig_y != sig_x) && (BIT(res, 31) != ((kop == 0b0110) ? sig_y : sig_x))) ? VF : 0);
|
||||
|
||||
RSP |= (((kop & 0b1001) != 0b1001) && BIT(res, 32)) ? CF : 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;
|
||||
case 0b01: PSW = (PSW & ~0x0f) | (RSP & 0x0c); break;
|
||||
case 0b10: PSW = (PSW & ~0x0e) | (RSP & 0x0e); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch(fd)
|
||||
{
|
||||
case 0b11:
|
||||
res &= 0x000000ff;
|
||||
R(rz) &= 0xffffff00;
|
||||
break;
|
||||
case 0b01:
|
||||
res &= 0x0000ffff;
|
||||
R(rz) &= 0xffff0000;
|
||||
break;
|
||||
case 0b00:
|
||||
default: // 0b10
|
||||
R(rz) = 0;
|
||||
break;
|
||||
}
|
||||
R(rz) |= res;
|
||||
if (rz == 0x1f) mreg_w();
|
||||
}
|
||||
|
||||
void kl1839vm1_device::mreg_r()
|
||||
bool kl1839vm1_device::mreg_r()
|
||||
{
|
||||
const u8 kob_tmp = BIT(m_vma_tmp.d, 24, 3);
|
||||
if (kob_tmp == 0b001)
|
||||
const u8 kob = BIT(m_vma_tmp.d, 24, 3);
|
||||
if ((kob & 0b101) == 0b001)
|
||||
{
|
||||
const u8 no_tmp = BIT(m_vma_tmp.d, 30, 2);
|
||||
switch (no_tmp)
|
||||
const u8 no = BIT(m_vma_tmp.d, 30, 2);
|
||||
switch (no)
|
||||
{
|
||||
case 0b00:
|
||||
BO = m_ram.read_dword(m_vma_tmp.d);
|
||||
@ -198,16 +231,20 @@ void kl1839vm1_device::mreg_r()
|
||||
UNIMPLEMENTED("Read w/ catch BRA");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void kl1839vm1_device::mreg_w()
|
||||
{
|
||||
const u8 kob_tmp = BIT(m_vma_tmp.d, 24, 3);
|
||||
if (kob_tmp == 0b010)
|
||||
const u8 kob = BIT(m_vma_tmp.d, 24, 3);
|
||||
if ((kob & 0b110) == 0b010)
|
||||
{
|
||||
const u8 no_tmp = BIT(m_vma_tmp.d, 30, 2);
|
||||
switch (no_tmp)
|
||||
const u8 no = BIT(m_vma_tmp.d, 30, 2);
|
||||
switch (no)
|
||||
{
|
||||
case 0b00:
|
||||
m_ram.write_dword(m_vma_tmp.d, BO);
|
||||
@ -229,8 +266,8 @@ 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);
|
||||
u8 am = BIT(op, 20, 4);
|
||||
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);
|
||||
@ -241,28 +278,55 @@ void kl1839vm1_device::ma(u32 op)
|
||||
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 (am>=0xd)
|
||||
UNIMPLEMENTED("Read const with data mirror K>0x0d");
|
||||
else if (am == 8)
|
||||
UNIMPLEMENTED("Read const with data mirror K=8"); // CRM priveleges check
|
||||
|
||||
if (po | py | px)
|
||||
UNIMPLEMENTED("MA: P*");
|
||||
if (po)
|
||||
UNIMPLEMENTED("MA: PO");
|
||||
|
||||
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 (!m_pcm_queue.empty())
|
||||
{
|
||||
if (py)
|
||||
am = vax_pcm_pull();
|
||||
else if (am == 5) // PCM
|
||||
K(5) = vax_pcm_pull(1);
|
||||
else if (pd && (am == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
if (px)
|
||||
x = vax_pcm_pull();
|
||||
else if (pd && (x == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
}
|
||||
else if (pd)
|
||||
{
|
||||
mreg_r();
|
||||
}
|
||||
|
||||
kop(kop1, fd, R(x), K(am), x, ps, va, fo);
|
||||
if (va)
|
||||
{
|
||||
kob_data = R(x);
|
||||
}
|
||||
kob_process(no, fo, kob, kob_data);
|
||||
if (fd == 0b10)
|
||||
{
|
||||
RKA = m_sysram.read_dword(R(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
kob_process(no, fo, kob, kob_data, R(x));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
u8 y = BIT(op, 20, 5);
|
||||
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);
|
||||
@ -273,41 +337,70 @@ void kl1839vm1_device::mb(u32 op)
|
||||
const bool py = BIT(op, 2);
|
||||
const bool px = BIT(op, 1);
|
||||
|
||||
if (po | py | px)
|
||||
UNIMPLEMENTED("MB: P*");
|
||||
if (po)
|
||||
UNIMPLEMENTED("MB: PO");
|
||||
|
||||
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 (!m_pcm_queue.empty())
|
||||
{
|
||||
if (py)
|
||||
y = vax_pcm_pull();
|
||||
else if (pd && !mreg_r() && (y == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
if (px)
|
||||
x = vax_pcm_pull();
|
||||
else if (pd && (x == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
}
|
||||
else if (pd)
|
||||
{
|
||||
mreg_r();
|
||||
}
|
||||
|
||||
kop(kop2 << 1, fd, R(x), R(y), x, ps, va, fo);
|
||||
if (va)
|
||||
{
|
||||
kob_data = R(x);
|
||||
}
|
||||
kob_process(no, fo, kob, kob_data);
|
||||
kob_process(no, fo, kob, kob_data, R(x));
|
||||
}
|
||||
|
||||
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);
|
||||
u8 y = BIT(op, 20, 5);
|
||||
u8 x = BIT(op, 15, 5);
|
||||
const u8 ps = BIT(op, 13, 2);
|
||||
|
||||
const u8 z = BIT(op, 7, 5);
|
||||
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 (!m_pcm_queue.empty())
|
||||
{
|
||||
if (py)
|
||||
y = vax_pcm_pull();
|
||||
else if (pd && !mreg_r() && (y == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
if (px)
|
||||
x = vax_pcm_pull();
|
||||
else if (pd && !mreg_r() && (x == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
if (pz)
|
||||
z = vax_pcm_pull();
|
||||
else if (pd && (z == 0x1f))
|
||||
BO = vax_pcm_pull(1);
|
||||
}
|
||||
else if (pd)
|
||||
{
|
||||
mreg_r();
|
||||
}
|
||||
|
||||
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();
|
||||
kop(kop2 << 1, fd, R(x), kop2 ? R(y) : R(x), z, ps);
|
||||
}
|
||||
|
||||
void kl1839vm1_device::mk(u32 op)
|
||||
@ -315,7 +408,7 @@ void kl1839vm1_device::mk(u32 op)
|
||||
const bool ret = BIT(op, 17);
|
||||
if (!ret)
|
||||
{
|
||||
RV = MCA;
|
||||
RV = AMC;
|
||||
}
|
||||
|
||||
if ((op & 0xfe000000) == 0xe0000000)
|
||||
@ -323,19 +416,19 @@ void kl1839vm1_device::mk(u32 op)
|
||||
if (BIT(~op, 16)) // madr == 0
|
||||
{
|
||||
const u16 addr = BIT(op, 2, 14);
|
||||
MCA = addr;
|
||||
AMC = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 addr_hi = BIT(op, 8, 8) << 6;
|
||||
MCA = addr_hi | (R(0x18) & 0x3f);
|
||||
AMC = 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;
|
||||
AMC = addr_hi;
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +440,7 @@ void kl1839vm1_device::yp(u32 op)
|
||||
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 fpd = BIT(op, 22);
|
||||
//const bool prb = BIT(op, 21);
|
||||
//const bool rst = BIT(op, 20);
|
||||
//const bool rd = BIT(op, 19);
|
||||
@ -358,10 +451,16 @@ void kl1839vm1_device::yp(u32 op)
|
||||
bool jump = false;
|
||||
if (fp)
|
||||
{
|
||||
// Jump based on SRF flags
|
||||
jump = uv == m_fp;
|
||||
}
|
||||
else if (fpd)
|
||||
{
|
||||
jump = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// zhs=1 - don't wait for the state completed
|
||||
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);
|
||||
@ -371,49 +470,56 @@ void kl1839vm1_device::yp(u32 op)
|
||||
{
|
||||
if (!ret)
|
||||
{
|
||||
RV = MCA;
|
||||
RV = AMC;
|
||||
}
|
||||
MCA = addr;
|
||||
AMC = addr;
|
||||
}
|
||||
}
|
||||
|
||||
void kl1839vm1_device::zsch(u32 op)
|
||||
{
|
||||
const bool madr = BIT(op, 16);
|
||||
if (madr)
|
||||
if (m_jzdra_waiting)
|
||||
{
|
||||
const u8 cnst_hi = BIT(op, 8, 2) << 6;
|
||||
SCH = cnst_hi | (R(0x18) & 0x3f);
|
||||
SCH = R(0x19);
|
||||
m_jzdra_waiting = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8 cnst = BIT(op, 2, 8);
|
||||
SCH = cnst;
|
||||
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)
|
||||
if (SCH--)
|
||||
{
|
||||
const u16 addr_hi = BIT(op, 8, 8) << 6;
|
||||
MCA = addr_hi | (R(0x18) & 0x3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SCH--)
|
||||
const bool madr = BIT(op, 16);
|
||||
if (madr)
|
||||
{
|
||||
const u16 addr_hi = BIT(op, 8, 8) << 6;
|
||||
AMC = addr_hi | (R(0x18) & 0x3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
const u16 addr = BIT(op, 2, 14);
|
||||
MCA = addr;
|
||||
AMC = addr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void kl1839vm1_device::rts(u32 op)
|
||||
{
|
||||
MCA = RV;
|
||||
AMC = RV;
|
||||
}
|
||||
|
||||
void kl1839vm1_device::acc(u32 op)
|
||||
@ -463,11 +569,10 @@ void kl1839vm1_device::srf(u32 op)
|
||||
}
|
||||
if (BIT(op, 4)) // OCT
|
||||
{
|
||||
--MCA;
|
||||
}
|
||||
if (BIT(op, 2)) // JDZRA
|
||||
{
|
||||
UNIMPLEMENTED("SRF: JDZRA");
|
||||
m_jzdra_waiting = true;
|
||||
}
|
||||
if (BIT(op, 1)) // INC
|
||||
{
|
||||
@ -479,23 +584,31 @@ void kl1839vm1_device::invalid(u32 op)
|
||||
{
|
||||
}
|
||||
|
||||
void kl1839vm1_device::kob_process(u8 no, u8 fo, u8 kob, u32 data)
|
||||
void kl1839vm1_device::kob_process(u8 no, u8 fo, u8 kob, u32 kob_data, u32 data)
|
||||
{
|
||||
switch (kob) {
|
||||
case 0b000: // NOP
|
||||
break;
|
||||
case 0b001: // Data Read
|
||||
case 0b010: // Data Write
|
||||
case 0b011: // Read-Modify-Write
|
||||
m_vma_tmp.d = (no << 30) | (fo << 28) | (kob << 24) | data;
|
||||
m_vma_tmp.d = (no << 30) | (fo << 28) | (kob << 24) | kob_data;
|
||||
break;
|
||||
case 0b100: // Write Accum R(17)
|
||||
R(0x17) = data;
|
||||
break;
|
||||
case 0b101: // Read Command
|
||||
m_vma_tmp.d = 0;
|
||||
PC = data;
|
||||
break;
|
||||
case 0b110: // Offset Write
|
||||
UNIMPLEMENTED("KOB");
|
||||
break;
|
||||
|
||||
case 0b000: // NOP
|
||||
case 0b111: // Reserve
|
||||
default: break;
|
||||
default:
|
||||
m_vma_tmp.d = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,43 +652,289 @@ void kl1839vm1_device::decode_op(u32 op)
|
||||
else if ((op & 0xfc000000) == 0xfc000000)
|
||||
srf(op);
|
||||
else
|
||||
invalid(op);
|
||||
UNIMPLEMENTED(op);
|
||||
}
|
||||
}
|
||||
|
||||
void kl1839vm1_device::vax_decode_pc()
|
||||
{
|
||||
if (!m_pcm_queue.empty())
|
||||
{
|
||||
LOGVAX("Unused decoded data\n");
|
||||
}
|
||||
m_vma_tmp.d = 0;
|
||||
|
||||
const u8 op = m_ram.read_byte(PC);
|
||||
m_op_size = 1;
|
||||
AMC = op << 4;
|
||||
|
||||
m_pcm_queue.clear();
|
||||
const vax_disassembler::mode* args = vax_disassembler::get_operands(op);
|
||||
u8 arg_n = 0;
|
||||
do
|
||||
{
|
||||
m_mem_reg[arg_n] = ~0; // Default to unknown
|
||||
|
||||
const vax_disassembler::mode mode = args[arg_n];
|
||||
switch (mode)
|
||||
{
|
||||
case vax_disassembler::mode::none:
|
||||
break;
|
||||
|
||||
// byte
|
||||
case vax_disassembler::mode::bb:
|
||||
m_pcm_queue.push_back(s8(m_ram.read_byte(PC + m_op_size)));
|
||||
m_mem_reg[arg_n] = 0x8f;
|
||||
m_op_size += 1;
|
||||
break;
|
||||
|
||||
case vax_disassembler::mode::cntb:
|
||||
case vax_disassembler::mode::mb:
|
||||
case vax_disassembler::mode::urb:
|
||||
case vax_disassembler::mode::srb:
|
||||
case vax_disassembler::mode::wb:
|
||||
{
|
||||
u8 p = m_ram.read_byte(PC + m_op_size);
|
||||
if (p == 0x8f) // M
|
||||
{
|
||||
m_pcm_queue.push_back(m_ram.read_byte(PC + m_op_size + 1));
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 2;
|
||||
}
|
||||
else if ((p & 0xf0) == 0x80) // M = R(n)+
|
||||
{
|
||||
m_pcm_queue.push_back(p & 0x0f);
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 1;
|
||||
}
|
||||
else if ((p & 0xf0) == 0x50) // R
|
||||
{
|
||||
m_pcm_queue.push_back(p & 0x0f);
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 1;
|
||||
}
|
||||
else // ?
|
||||
{
|
||||
LOGVAX("OP=%02x unknown prefix %02x in operand mode::%02d\n", op, p, u8(mode));
|
||||
m_op_size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// word
|
||||
case vax_disassembler::mode::bw:
|
||||
m_pcm_queue.push_back(s16(m_ram.read_word(PC + m_op_size)));
|
||||
m_mem_reg[arg_n] = 0x8f;
|
||||
m_op_size += 2;
|
||||
break;
|
||||
|
||||
// dword
|
||||
case vax_disassembler::mode::rl:
|
||||
case vax_disassembler::mode::url:
|
||||
case vax_disassembler::mode::ml:
|
||||
case vax_disassembler::mode::prl:
|
||||
case vax_disassembler::mode::srl:
|
||||
case vax_disassembler::mode::wl:
|
||||
{
|
||||
u8 p = m_ram.read_byte(PC + m_op_size);
|
||||
if (p == 0x8f) // M
|
||||
{
|
||||
m_pcm_queue.push_back(m_ram.read_dword(PC + m_op_size + 1));
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 5;
|
||||
}
|
||||
else if ((p & 0xf0) == 0x80) // M = R(n)+
|
||||
{
|
||||
m_pcm_queue.push_back(p & 0x0f);
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 1;
|
||||
}
|
||||
else if ((p & 0xf0) == 0x50) // R
|
||||
{
|
||||
m_pcm_queue.push_back(p & 0x0f);
|
||||
m_mem_reg[arg_n] = p;
|
||||
m_op_size += 1;
|
||||
}
|
||||
else // ?
|
||||
{
|
||||
LOGVAX("OP=%02x unknown prefix %02x in operand mode::%02d\n", op, p, u8(mode));
|
||||
m_op_size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOGVAX("(%x): unknown operand mode %02d in OP=%02x (n=%d)\n", PC, u8(mode), op, arg_n + 1);
|
||||
m_pcm_queue.clear();
|
||||
m_op_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
++arg_n;
|
||||
} while ((arg_n < 6) && (args[arg_n] != vax_disassembler::mode::none));
|
||||
|
||||
if (m_op_size > 0) // above completed without failure
|
||||
{
|
||||
u8 args_type = 0;
|
||||
if (!m_pcm_queue.empty())
|
||||
{
|
||||
for (u8 i = 0; i < arg_n; ++i)
|
||||
{
|
||||
args_type <<= 1;
|
||||
if ((m_mem_reg[i] & 0xf0) == 0x80)
|
||||
args_type |= 1;
|
||||
else if ((m_mem_reg[i] & 0xf0) == 0x50)
|
||||
args_type |= 0;
|
||||
else
|
||||
LOGVAX("Unknown argument type: %02x\n", m_mem_reg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
|
||||
assert(m_op_size == 1); // no operands
|
||||
break;
|
||||
|
||||
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
|
||||
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
case 0x30: case 0x31:
|
||||
assert(arg_n == 1);
|
||||
break;
|
||||
|
||||
case 0x94: case 0x95: case 0x96: case 0x97:
|
||||
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
|
||||
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
||||
assert(arg_n == 1);
|
||||
AMC += 0x0c * args_type;
|
||||
break;
|
||||
|
||||
case 0xda:
|
||||
case 0xe8: case 0xe9:
|
||||
assert(arg_n == 2);
|
||||
break;
|
||||
|
||||
case 0xdb:
|
||||
assert(arg_n == 2);
|
||||
AMC += BIT(args_type, 0) ? 0x0 : 0x2;
|
||||
break;
|
||||
|
||||
case 0x80: case 0x82: case 0x84: case 0x86: case 0x88: case 0x8a: case 0x8c:
|
||||
case 0x90: case 0x92:
|
||||
case 0xa0: case 0xa2: case 0xa4: case 0xa6: case 0xa8: case 0xaa: case 0xac:
|
||||
case 0xb0: case 0xb2:
|
||||
case 0xc0: case 0xc2: case 0xc4: case 0xc6: case 0xc8: case 0xca: case 0xcc:
|
||||
case 0xd0: case 0xd2:
|
||||
assert(arg_n == 2);
|
||||
switch (args_type)
|
||||
{
|
||||
case 0b00: AMC += 0x0; break; // RR
|
||||
case 0b01: AMC += 0x4; break; // RM
|
||||
case 0b10: AMC += 0xe; break; // MR
|
||||
case 0b11: AMC += 0xc; break; // MM
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x91: case 0x93:
|
||||
case 0xb1: case 0xb3:
|
||||
case 0xd1: case 0xd3:
|
||||
assert(arg_n == 2);
|
||||
switch (args_type)
|
||||
{
|
||||
case 0b00: AMC += 0x0; break; // RR
|
||||
case 0b01: AMC += 0x4; break; // RM
|
||||
case 0b10:
|
||||
case 0b11: AMC += 0xc; break; // MM, MR
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x78:
|
||||
assert(arg_n == 3);
|
||||
AMC += BIT(args_type, 0) ? 0x0 : 0x2;
|
||||
break;
|
||||
|
||||
case 0x81: case 0x83: case 0x85: case 0x87: case 0x89: case 0x8b: case 0x8d:
|
||||
case 0xa1: case 0xa3: case 0xa5: case 0xa7: case 0xa9: case 0xab: case 0xad:
|
||||
case 0xc1: case 0xc3: case 0xc5: case 0xc7: case 0xc9: case 0xcb: case 0xcd:
|
||||
assert(arg_n == 3);
|
||||
switch (args_type)
|
||||
{
|
||||
case 0b000: AMC += 0x0; break; // RRR
|
||||
case 0b011: AMC += 0x4; break; // RMM
|
||||
case 0b010: AMC += 0x6; break; // RMR
|
||||
case 0b001: AMC += 0x8; break; // RRM
|
||||
case 0b110: AMC += 0xe; break; // MMR
|
||||
case 0b111: AMC += 0xc; break; // MMM
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGVAX("(%x): OP=%02x with %d operands is not implemented or supported\n", PC, op, arg_n);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_op_size)
|
||||
LOGVAX("(%x): undecoded OP=%02x .. EXIT\n", PC, op);
|
||||
else
|
||||
PC += m_op_size; // move to a next op
|
||||
;//LOGVAX("(%x): Decoded: OP=%02x args:%d \n", PC, op, m_pcm_queue.size());
|
||||
}
|
||||
|
||||
u32 kl1839vm1_device::vax_pcm_pull(bool is_bo)
|
||||
{
|
||||
if (m_pcm_queue.empty())
|
||||
{
|
||||
LOGVAX("Pooling empty decoder queue\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
PCM = m_pcm_queue.front();
|
||||
m_pcm_queue.pop_front();
|
||||
|
||||
bool is_mem = (m_mem_reg[0] & 0xf0) == 0x80;
|
||||
if (is_bo && !is_mem)
|
||||
{
|
||||
PCM = R(PCM);
|
||||
}
|
||||
else if (is_mem && ((m_mem_reg[0] & 0x0f) != 0x0f))
|
||||
{
|
||||
u8 r = PCM;
|
||||
PCM = R(PCM);
|
||||
R(r) = PCM + 1;
|
||||
}
|
||||
std::copy(std::begin(m_mem_reg) + 1, std::end(m_mem_reg), std::begin(m_mem_reg));
|
||||
}
|
||||
|
||||
return PCM;
|
||||
}
|
||||
|
||||
|
||||
void kl1839vm1_device::device_start()
|
||||
{
|
||||
m_vax_dasm = std::make_unique<vax_disassembler>();
|
||||
|
||||
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_amc));
|
||||
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(KL1839_AMC, "AMC", AMC).formatstr("%08X");
|
||||
state_add(KL1839_PSW, "PSW", PSW).formatstr("%08s");
|
||||
state_add(KL1839_IF, "cond", m_fp).formatstr("%08s");
|
||||
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_R0, "R0", R(0)).formatstr("%08X");
|
||||
state_add(VAX_R1, "R1", R(1)).formatstr("%08X");
|
||||
@ -587,8 +946,15 @@ void kl1839vm1_device::device_start()
|
||||
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(VAX_R10, "R10", R(10)).formatstr("%08X");
|
||||
state_add(VAX_R11, "R11", R(11)).formatstr("%08X");
|
||||
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_INST, "INST", PC).formatstr("%20s");
|
||||
state_add_divider(-1);
|
||||
state_add(VAX_AK0, "AK0", R(0x14)).formatstr("%08X");
|
||||
state_add(VAX_AK1, "AK1", R(0x15)).formatstr("%08X");
|
||||
@ -605,9 +971,9 @@ void kl1839vm1_device::device_start()
|
||||
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();
|
||||
state_add(STATE_GENPC, "GENPC", AMC).noshow();
|
||||
state_add(STATE_GENPCBASE, "CURPC", m_ppc.d).noshow();
|
||||
state_add(STATE_GENFLAGS, "GENFLAGS", RSP).formatstr("%8s").noshow();
|
||||
|
||||
set_icountptr(m_icount);
|
||||
}
|
||||
@ -617,18 +983,6 @@ void kl1839vm1_device::state_string_export(const device_state_entry &entry, std:
|
||||
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 ? '?' : '.',
|
||||
@ -640,9 +994,37 @@ void kl1839vm1_device::state_string_export(const device_state_entry &entry, std:
|
||||
RSP & CF ? 'C' : '.'
|
||||
);
|
||||
break;
|
||||
case KL1839_PSW:
|
||||
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_IF:
|
||||
str = string_format("FP%d", m_fp);
|
||||
break;
|
||||
case VAX_INST:
|
||||
if (m_op_size)
|
||||
{
|
||||
address_space &space_prg = space(AS_PROGRAM);
|
||||
std::ostringstream buffer;
|
||||
disasm_data_buffer databuf(space_prg);
|
||||
m_vax_dasm->disassemble(buffer, PC - m_op_size, databuf, databuf);
|
||||
|
||||
const std::regex reg("\\s+");
|
||||
str = regex_replace(buffer.str(), reg, " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "--------";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,13 +1033,15 @@ void kl1839vm1_device::device_reset()
|
||||
for (auto ® : m_reg)
|
||||
reg.d = 0;
|
||||
|
||||
m_ppc.d = MCA = 0x2000;
|
||||
VMA = 0;
|
||||
m_ppc.d = AMC = 0x2000;
|
||||
m_fp = false;
|
||||
m_jzdra_waiting = false;
|
||||
RSP = 0;
|
||||
m_vma_tmp.d = 0;
|
||||
RV = 0;
|
||||
SCH = 0;
|
||||
m_pcm_queue.clear();
|
||||
m_op_size = 0;
|
||||
}
|
||||
|
||||
void kl1839vm1_device::execute_set_input(int irqline, int state)
|
||||
@ -668,14 +1052,19 @@ void kl1839vm1_device::execute_run()
|
||||
{
|
||||
do
|
||||
{
|
||||
m_ppc.d = MCA;
|
||||
m_ppc.d = AMC;
|
||||
debugger_instruction_hook(m_ppc.d);
|
||||
|
||||
u32 op = m_microcode.read_dword(MCA);
|
||||
u32 op = m_microcode.read_dword(AMC);
|
||||
m_icount -= 2;
|
||||
++MCA &= 0x3fff;
|
||||
++AMC &= 0x3fff;
|
||||
|
||||
decode_op(op);
|
||||
|
||||
if (op & 1) // S-bit
|
||||
{
|
||||
vax_decode_pc();
|
||||
}
|
||||
} while (m_icount > 0);
|
||||
}
|
||||
|
||||
@ -683,4 +1072,3 @@ std::unique_ptr<util::disasm_interface> kl1839vm1_device::create_disassembler()
|
||||
{
|
||||
return std::make_unique<kl1839vm1_disassembler>();
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
|
||||
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,
|
||||
KL1839_AMC = STATE_GENPC, KL1839_IF, KL1839_PSW, 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_R10, VAX_R11,
|
||||
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
|
||||
VAX_RNK, VAX_RKA, VAX_PSL, VAX_BO, VAX_INST
|
||||
};
|
||||
|
||||
|
||||
@ -43,6 +44,22 @@ protected:
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
private:
|
||||
class disasm_data_buffer : public util::disasm_interface::data_buffer
|
||||
{
|
||||
public:
|
||||
disasm_data_buffer(address_space &space) : m_space(space)
|
||||
{
|
||||
}
|
||||
|
||||
virtual u8 r8(offs_t pc) const override { return m_space.read_byte(pc); }
|
||||
virtual u16 r16(offs_t pc) const override { return m_space.read_word(pc); }
|
||||
virtual u32 r32(offs_t pc) const override { return m_space.read_dword(pc); }
|
||||
virtual u64 r64(offs_t pc) const override { return m_space.read_qword(pc); }
|
||||
|
||||
private:
|
||||
address_space &m_space;
|
||||
};
|
||||
|
||||
void flag(u32 op);
|
||||
void rest(u32 op);
|
||||
void ma(u32 op);
|
||||
@ -60,12 +77,15 @@ private:
|
||||
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 kob_process(u8 no, u8 fd, u8 kob, u32 kob_data, u32 data);
|
||||
void kop(u8 kop, u8 fd, u32 x, u32 y, u8 rz, u8 ps, bool va, u8 fo);
|
||||
void mreg_w();
|
||||
void mreg_r();
|
||||
bool mreg_r();
|
||||
void decode_op(u32 op);
|
||||
|
||||
void vax_decode_pc();
|
||||
u32 vax_pcm_pull(bool is_bo = 0);
|
||||
|
||||
address_space_config m_microcode_config;
|
||||
address_space_config m_sysram_config;
|
||||
address_space_config m_ram_config;
|
||||
@ -75,17 +95,24 @@ private:
|
||||
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;
|
||||
|
||||
std::unique_ptr<util::disasm_interface> m_vax_dasm;
|
||||
|
||||
PAIR m_vma_tmp; // do we have int reg for this?
|
||||
PAIR m_rv;
|
||||
PAIR m_sch;
|
||||
PAIR m_rsp;
|
||||
PAIR m_amc; // Microdode PC
|
||||
PAIR m_ppc; // previous program counter
|
||||
bool m_fp;
|
||||
bool m_jzdra_waiting;
|
||||
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;
|
||||
u32 m_op_size;
|
||||
|
||||
std::deque<u32> m_pcm_queue;
|
||||
u8 m_mem_reg[6];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(KL1839VM1, kl1839vm1_device)
|
||||
|
@ -12,6 +12,7 @@ static const std::string r_name(u8 id)
|
||||
std::ostringstream ss;
|
||||
switch (id)
|
||||
{
|
||||
case 0x0f: ss << "PC"; break;
|
||||
case 0x14: ss << "AK0"; break;
|
||||
case 0x15: ss << "AK1"; break;
|
||||
case 0x16: ss << "AK2"; break;
|
||||
@ -98,7 +99,7 @@ static const void ma(std::ostream &stream, u32 op)
|
||||
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));
|
||||
m_base(stream, op, 'A', kop1, px ? "RX" : r_name(x), py ? "RY" : k_name(am), px ? "RX" : r_name(x));
|
||||
|
||||
if (kob)
|
||||
{
|
||||
@ -128,7 +129,7 @@ static const void ma(std::ostream &stream, u32 op)
|
||||
case 0b001: stream << "4D "; break;
|
||||
case 0b010: stream << "ZD "; break;
|
||||
case 0b011: stream << "4Z "; break;
|
||||
case 0b100: stream << "?R(17)==ACC "; break;
|
||||
case 0b100: stream << "WDAK "; break;
|
||||
case 0b101: stream << "4K "; break;
|
||||
case 0b110: break; // reserved
|
||||
case 0b111: stream << "BRD "; break;
|
||||
@ -136,8 +137,8 @@ static const void ma(std::ostream &stream, u32 op)
|
||||
}
|
||||
}
|
||||
|
||||
if (px | po | py)
|
||||
stream << "?:" << (px ? "PX " : "") << (po ? "PO " : "") << (py ? "PY " : "");
|
||||
if (po)
|
||||
stream << "?:" << (po ? "RO" : "");
|
||||
}
|
||||
|
||||
static const void mb(std::ostream &stream, u32 op)
|
||||
@ -150,11 +151,11 @@ static const void mb(std::ostream &stream, u32 op)
|
||||
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 po = 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));
|
||||
m_base(stream, op, 'B', kop2 << 1, px ? "RX" : r_name(x), py ? "RY" : r_name(y), px ? "RX" : r_name(x));
|
||||
|
||||
if (kob)
|
||||
{
|
||||
@ -192,7 +193,7 @@ static const void mb(std::ostream &stream, u32 op)
|
||||
case 0b001: stream << "4D "; break;
|
||||
case 0b010: stream << "ZD "; break;
|
||||
case 0b011: stream << "4Z "; break;
|
||||
case 0b100: stream << "?R(17)==ACC "; break;
|
||||
case 0b100: stream << "WDAK "; break;
|
||||
case 0b101: stream << "4K "; break;
|
||||
case 0b110: break; // reserved
|
||||
case 0b111: stream << "BRD "; break;
|
||||
@ -200,8 +201,8 @@ static const void mb(std::ostream &stream, u32 op)
|
||||
}
|
||||
}
|
||||
|
||||
if (px | pz | py)
|
||||
stream << "?:" << (px ? "PX " : "") << (pz ? "PZ " : "") << (py ? "PY " : "");
|
||||
if (po)
|
||||
stream << "?:" << (po ? "RO" : "");
|
||||
}
|
||||
|
||||
static const void mc(std::ostream &stream, u32 op)
|
||||
@ -214,10 +215,7 @@ static const void mc(std::ostream &stream, u32 op)
|
||||
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 " : "");
|
||||
m_base(stream, op, 'C', kop2 << 1, px ? "RX" : r_name(x), kop2 ? (py ? "RY" : r_name(y)) : (px ? "RX" : r_name(x)), pz ? "RZ" : r_name(z));
|
||||
}
|
||||
|
||||
static const u32 mk(std::ostream &stream, u32 op)
|
||||
@ -228,11 +226,12 @@ static const u32 mk(std::ostream &stream, u32 op)
|
||||
if (BIT(~op, 16)) // madr == 0
|
||||
{
|
||||
const u16 addr = BIT(op, 2, 14);
|
||||
util::stream_format(stream, "BP%s : ;A=%04X", ret ? " " : "B" ,addr);
|
||||
util::stream_format(stream, "BP%s : ;A=(%04X)", ret ? " " : "B" , addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "??MK-2";
|
||||
u16 addr_hi = BIT(op, 8, 8) << 6;
|
||||
util::stream_format(stream, "BPV%s : ;A=(%04X+%s)", ret ? " " : "D" , addr_hi, r_name(0x18));
|
||||
}
|
||||
}
|
||||
else if ((op & 0xfe000000) == 0xe2000000)
|
||||
@ -437,5 +436,10 @@ offs_t kl1839vm1_disassembler::disassemble(std::ostream &stream, offs_t pc, cons
|
||||
stream << "<invalid>";
|
||||
}
|
||||
|
||||
if (op & 1)
|
||||
{
|
||||
stream << "S";
|
||||
}
|
||||
|
||||
return 1 | SUPPORTED | step;
|
||||
}
|
||||
|
@ -23,37 +23,11 @@ u32 vax_disassembler::opcode_alignment() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum class vax_disassembler::mode : u8
|
||||
{
|
||||
none,
|
||||
rb, srb, urb, cntb, rw, srw, urw, mskw, rl, srl, url, posl, prl, rq, srq, urq, ro, uro,
|
||||
mb, mw, ml, mq, mo,
|
||||
wb, ww, wl, wq, wo,
|
||||
ab, aw, al, aq, ao,
|
||||
bb, bw,
|
||||
vb
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std::literals;
|
||||
using mode = vax_disassembler::mode;
|
||||
|
||||
static constexpr bool is_read_mode(mode m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case mode::rb: case mode::srb: case mode::urb: case mode::cntb:
|
||||
case mode::rw: case mode::srw: case mode::urw: case mode::mskw:
|
||||
case mode::rl: case mode::srl: case mode::url: case mode::posl: case mode::prl:
|
||||
case mode::rq: case mode::urq:
|
||||
case mode::ro: case mode::uro:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool is_address_mode(mode m)
|
||||
{
|
||||
return m == mode::ab || m == mode::aw || m == mode::al || m == mode::aq || m == mode::ao;
|
||||
@ -1119,3 +1093,23 @@ offs_t vax_disassembler::disassemble(std::ostream &stream, offs_t pc, const vax_
|
||||
else
|
||||
return disassemble_inst(stream, s_nonprefix_ops[op], pc, ppc, opcodes);
|
||||
}
|
||||
|
||||
bool vax_disassembler::is_read_mode(vax_disassembler::mode m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case mode::rb: case mode::srb: case mode::urb: case mode::cntb:
|
||||
case mode::rw: case mode::srw: case mode::urw: case mode::mskw:
|
||||
case mode::rl: case mode::srl: case mode::url: case mode::posl: case mode::prl:
|
||||
case mode::rq: case mode::urq:
|
||||
case mode::ro: case mode::uro:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const vax_disassembler::mode* vax_disassembler::get_operands(u8 op)
|
||||
{
|
||||
return s_nonprefix_ops[op].operand;
|
||||
}
|
||||
|
@ -9,7 +9,16 @@
|
||||
class vax_disassembler : public util::disasm_interface
|
||||
{
|
||||
public:
|
||||
enum class mode : u8;
|
||||
enum class mode : u8
|
||||
{
|
||||
none,
|
||||
rb, srb, urb, cntb, rw, srw, urw, mskw, rl, srl, url, posl, prl, rq, srq, urq, ro, uro,
|
||||
mb, mw, ml, mq, mo,
|
||||
wb, ww, wl, wq, wo,
|
||||
ab, aw, al, aq, ao,
|
||||
bb, bw,
|
||||
vb
|
||||
};
|
||||
|
||||
struct opdef
|
||||
{
|
||||
@ -21,6 +30,9 @@ public:
|
||||
// construction/destruction
|
||||
vax_disassembler();
|
||||
|
||||
static bool is_read_mode(mode m);
|
||||
static const mode* get_operands(u8 op);
|
||||
|
||||
protected:
|
||||
// disassembler overrides
|
||||
virtual u32 opcode_alignment() const override;
|
||||
|
@ -2,6 +2,57 @@
|
||||
// copyright-holders:Andrei I. Holub
|
||||
/**********************************************************************
|
||||
Elektronika PK-32
|
||||
|
||||
* Terminal Commands:
|
||||
E <memoryType> <address> (E)xamine
|
||||
<memoryType>: /G - General purpose reg, /S - System mem, /I - Internal reg, /P - Phisical mem, /V - Virtual mem
|
||||
Example: E /S 0
|
||||
D <memoryType> <address> <value> (D)eposit
|
||||
<memoryType>: see E
|
||||
Example: D /S 0 44332211
|
||||
C (C)ontinue user programm
|
||||
B (B)oot
|
||||
T [<num>] (T)est All or <num>=1-6
|
||||
I (I)nit
|
||||
|
||||
|
||||
* Sample User Program:
|
||||
2000: MOVB #20,R0 | 908f2050
|
||||
2004: MOVL #23,R6 | d08f2300000056
|
||||
200B: MOVL #22,R7 | d08f2200000057
|
||||
2012: MFPR R7,R8 | db5758
|
||||
2015: BITB #80,R8 | 938f8058
|
||||
2019: BEQL 2012 | 13f7
|
||||
201B: NOP | 01
|
||||
201C: NOP | 01
|
||||
201D: NOP | 01
|
||||
201E: MTPR R0,R6 | da5056
|
||||
2021: INCB R0 | 9650
|
||||
2023: BICB2 #C0,R0 | 8a8fc050
|
||||
2027: BISB2 #30,R0 | 888f3050
|
||||
202B: BRB 2012 | 11e5
|
||||
|
||||
** Use terminal:
|
||||
D 2000 50208F90
|
||||
D 2004 00238FD0
|
||||
D 2008 D0560000
|
||||
D 200C 0000228F
|
||||
D 2010 57DB5700
|
||||
D 2014 808F9358
|
||||
D 2018 01f71358
|
||||
D 201C 50DA0101
|
||||
D 2020 8A509656
|
||||
D 2024 8850C08f
|
||||
D 2028 1150308f
|
||||
D 202C 010101E5
|
||||
D /G F 2000
|
||||
C
|
||||
|
||||
** Or MAME debugger:
|
||||
d@2000=50208F90
|
||||
...
|
||||
pc=2000
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
@ -48,6 +99,7 @@ private:
|
||||
void pk32_map_ram(address_map &map) ATTR_COLD;
|
||||
void pk32_map_io(address_map &map) ATTR_COLD;
|
||||
|
||||
memory_access<24, 0, 0, ENDIANNESS_LITTLE>::specific m_program;
|
||||
required_device<kl1839vm1_device> m_maincpu;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<generic_terminal_device> m_terminal;
|
||||
@ -64,6 +116,7 @@ private:
|
||||
|
||||
u8 m_term_data = 0;
|
||||
u16 m_term_status = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -104,6 +157,13 @@ void pk32_state::term_tx_cs_w(u32 data)
|
||||
LOGTERM("TX CS <- %X\n", data);
|
||||
}
|
||||
|
||||
void pk32_state::kbd_put(u8 data)
|
||||
{
|
||||
m_term_data = data;
|
||||
m_term_status = 0xff;
|
||||
}
|
||||
|
||||
|
||||
void pk32_state::pk32_map_microcode(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x3fff).rom().region("microcode", 0);
|
||||
@ -145,15 +205,11 @@ static INPUT_PORTS_START( pk32 )
|
||||
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()
|
||||
{
|
||||
m_maincpu->space(AS_PROGRAM).specific(m_program);
|
||||
|
||||
save_item(NAME(m_term_data));
|
||||
save_item(NAME(m_term_status));
|
||||
}
|
||||
@ -182,14 +238,14 @@ 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(0, "v1", "1839src")
|
||||
ROMX_LOAD("fw-1839-src.bin", 0x00000, 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))
|
||||
ROMX_LOAD("fw-1839-isa.bin", 0x00000, 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))
|
||||
ROMX_LOAD("fw-1839pe1-006.bin", 0x00000, 0x10000, CRC(e6bb7639) SHA1(759993afc9b61d9cf83acf3e361dcec571beccf1), ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user