mirror of
https://github.com/simh/simh.git
synced 2026-01-11 23:52:58 +00:00
ND100: MMS-1 support (Memory Management 1) + other fixes for Nord-100.
Can now boot the last test programs from floppy, and runs INSTRUCTION-C and PAGING-C without errors.
This commit is contained in:
parent
d57c67c4f5
commit
22e33dd3d4
@ -30,12 +30,6 @@
|
|||||||
#include "nd100_defs.h"
|
#include "nd100_defs.h"
|
||||||
|
|
||||||
#define MAXMEMSIZE 512*1024
|
#define MAXMEMSIZE 512*1024
|
||||||
#undef TIMERHACK
|
|
||||||
|
|
||||||
#ifdef TIMERHACK
|
|
||||||
int rtc_int_enabled, rtc_dev_ready, rtccnt;
|
|
||||||
void chkrtc(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int ir;
|
int ir;
|
||||||
@ -59,11 +53,11 @@ static Hist_entry *hist = NULL;
|
|||||||
static struct intr *ilnk[4]; /* level 10-13 */
|
static struct intr *ilnk[4]; /* level 10-13 */
|
||||||
jmp_buf env;
|
jmp_buf env;
|
||||||
|
|
||||||
uint16 R[8], RBLK[16][8], regSTH;
|
uint16 R[8], RBLK[16][8], regSTH, oregP;
|
||||||
int curlvl; /* current interrupt level */
|
int curlvl; /* current interrupt level */
|
||||||
int iic, iie, iid; /* IIC/IIE/IID register */
|
int iic, iie, iid; /* IIC/IIE/IID register */
|
||||||
int pid, pie; /* PID/PIE register */
|
int pid, pie; /* PID/PIE register */
|
||||||
int ald, eccr, pvl, lmp;
|
int ald, eccr, pvl, lmp, opr;
|
||||||
|
|
||||||
#define SETC() (regSTL |= STS_C)
|
#define SETC() (regSTL |= STS_C)
|
||||||
#define CLRC() (regSTL &= ~STS_C)
|
#define CLRC() (regSTL &= ~STS_C)
|
||||||
@ -88,12 +82,10 @@ static int nd_tra(int reg);
|
|||||||
static int nd_mcl(int reg);
|
static int nd_mcl(int reg);
|
||||||
static int nd_mst(int reg);
|
static int nd_mst(int reg);
|
||||||
static int highest_level(void);
|
static int highest_level(void);
|
||||||
static void intrpt14(int);
|
|
||||||
static void identrm(int);
|
static void identrm(int);
|
||||||
static uint16 add3(uint16 a, uint16 d, uint16 c);
|
static uint16 add3(uint16 a, uint16 d, uint16 c);
|
||||||
int fls(int);
|
int fls(int);
|
||||||
|
|
||||||
|
|
||||||
int ins_store(int ir, int addr);
|
int ins_store(int ir, int addr);
|
||||||
int ins_stdf(int ir, int addr);
|
int ins_stdf(int ir, int addr);
|
||||||
int ins_lddf(int ir, int addr);
|
int ins_lddf(int ir, int addr);
|
||||||
@ -144,6 +136,7 @@ REG cpu_reg[] = {
|
|||||||
{ ORDATA(A, regA, 16) },
|
{ ORDATA(A, regA, 16) },
|
||||||
{ ORDATA(T, regT, 16) },
|
{ ORDATA(T, regT, 16) },
|
||||||
{ ORDATA(X, regX, 16) },
|
{ ORDATA(X, regX, 16) },
|
||||||
|
{ ORDATA(oldP, oregP, 16) },
|
||||||
{ DRDATA(LVL, curlvl, 4) },
|
{ DRDATA(LVL, curlvl, 4) },
|
||||||
{ DRDATA(LMP, lmp, 16) },
|
{ DRDATA(LMP, lmp, 16) },
|
||||||
{ DRDATA(PVL, pvl, 4) },
|
{ DRDATA(PVL, pvl, 4) },
|
||||||
@ -151,6 +144,7 @@ REG cpu_reg[] = {
|
|||||||
{ ORDATA(PIE, pie, 16) },
|
{ ORDATA(PIE, pie, 16) },
|
||||||
{ ORDATA(IIC, iic, 4) },
|
{ ORDATA(IIC, iic, 4) },
|
||||||
{ ORDATA(IIE, iie, 10) },
|
{ ORDATA(IIE, iie, 10) },
|
||||||
|
{ ORDATA(OPR, opr, 16) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,16 +170,16 @@ sim_instr(void)
|
|||||||
int first = 1;
|
int first = 1;
|
||||||
uint16 off;
|
uint16 off;
|
||||||
|
|
||||||
reason = setjmp(env);
|
(void)setjmp(env);
|
||||||
|
reason = 0;
|
||||||
|
|
||||||
while (reason == 0) {
|
while (reason == 0) {
|
||||||
if (sim_interval <= 0)
|
if (sim_interval <= 0)
|
||||||
if ((reason = sim_process_event ()))
|
if ((reason = sim_process_event ()))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef TIMERHACK
|
if (regSTL & STS_Z)
|
||||||
chkrtc();
|
intrpt14(IIE_V, PM_DMA); /* no longjmp here */
|
||||||
#endif
|
|
||||||
if ((pid & pie) > (0177777 >> (15-curlvl)) && ISION()) {
|
if ((pid & pie) > (0177777 >> (15-curlvl)) && ISION()) {
|
||||||
/* need to interrupt */
|
/* need to interrupt */
|
||||||
pvl = curlvl;
|
pvl = curlvl;
|
||||||
@ -199,10 +193,21 @@ while (reason == 0) {
|
|||||||
regT = SEXT8(IR);
|
regT = SEXT8(IR);
|
||||||
}
|
}
|
||||||
|
|
||||||
IR = rdmem(regP);
|
/*
|
||||||
|
* ND100 manual clause 2.3.8.3 says that the instruction faults happens
|
||||||
|
* after the P reg is incremented, hence will point to one instruction
|
||||||
|
* past the instruction causing the fault.
|
||||||
|
* But; if the fault is during fetch, P will not be incremented.
|
||||||
|
*/
|
||||||
|
IR = rdmem(regP, M_FETCH);
|
||||||
|
oregP = regP++;
|
||||||
|
|
||||||
sim_interval--;
|
sim_interval--;
|
||||||
|
|
||||||
if (first == 0 && sim_brk_summ && sim_brk_test (regP, SWMASK ('E'))) {
|
if (regSTH & STS_TG)
|
||||||
|
return STOP_BP;
|
||||||
|
|
||||||
|
if (first == 0 && sim_brk_summ && sim_brk_test(oregP, SWMASK ('E'))) {
|
||||||
reason = STOP_BP;
|
reason = STOP_BP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -229,8 +234,6 @@ while (reason == 0) {
|
|||||||
off = getoff(IR);
|
off = getoff(IR);
|
||||||
|
|
||||||
reason = (*ins_table[ID(IR)])(IR, off);
|
reason = (*ins_table[ID(IR)])(IR, off);
|
||||||
if (reason == 0)
|
|
||||||
regP++;
|
|
||||||
}
|
}
|
||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
@ -248,7 +251,7 @@ cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
|||||||
{
|
{
|
||||||
if (addr >= MAXMEMSIZE)
|
if (addr >= MAXMEMSIZE)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
*vptr = rdmem(addr);
|
*vptr = rdmem(addr, M_PT); /* XXX */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +282,7 @@ int
|
|||||||
ins_store(int IR, int off)
|
ins_store(int IR, int off)
|
||||||
{
|
{
|
||||||
int n = ((IR >> 11) & 03) + 4;
|
int n = ((IR >> 11) & 03) + 4;
|
||||||
wrmem(off, n == 4 ? 0 : R[n]);
|
wrmem(off, n == 4 ? 0 : R[n], SELPT2(IR));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,10 +292,12 @@ ins_store(int IR, int off)
|
|||||||
int
|
int
|
||||||
ins_stdf(int IR, int off)
|
ins_stdf(int IR, int off)
|
||||||
{
|
{
|
||||||
|
int pt = SELPT2(IR);
|
||||||
|
|
||||||
if (ID(IR) == ID(ND_STF) /* && 48-bit */)
|
if (ID(IR) == ID(ND_STF) /* && 48-bit */)
|
||||||
wrmem(off++, regT);
|
wrmem(off++, regT, pt);
|
||||||
wrmem(off++, regA);
|
wrmem(off++, regA, pt);
|
||||||
wrmem(off, regD);
|
wrmem(off, regD, pt);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,10 +307,11 @@ ins_stdf(int IR, int off)
|
|||||||
int
|
int
|
||||||
ins_lddf(int IR, int off)
|
ins_lddf(int IR, int off)
|
||||||
{
|
{
|
||||||
|
int pt = SELPT2(IR);
|
||||||
if (ID(IR) == ID(ND_LDF) /* && 48-bit */)
|
if (ID(IR) == ID(ND_LDF) /* && 48-bit */)
|
||||||
regT = rdmem(off++);
|
regT = rdmem(off++, pt);
|
||||||
regA = rdmem(off++);
|
regA = rdmem(off++, pt);
|
||||||
regD = rdmem(off);
|
regD = rdmem(off, pt);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +321,7 @@ ins_lddf(int IR, int off)
|
|||||||
int
|
int
|
||||||
ins_load(int IR, int off)
|
ins_load(int IR, int off)
|
||||||
{
|
{
|
||||||
R[((IR&014000) >> 11) + 4] = rdmem(off);
|
R[((IR&014000) >> 11) + 4] = rdmem(off, SELPT2(IR));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,8 +332,9 @@ int
|
|||||||
ins_min(int IR, int off)
|
ins_min(int IR, int off)
|
||||||
{
|
{
|
||||||
uint16 s;
|
uint16 s;
|
||||||
|
int pt = SELPT2(IR);
|
||||||
|
|
||||||
wrmem(off, s = rdmem(off) + 1);
|
wrmem(off, s = rdmem(off, pt) + 1, pt);
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
regP++;
|
regP++;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
@ -339,7 +346,7 @@ ins_min(int IR, int off)
|
|||||||
int
|
int
|
||||||
ins_add(int IR, int off)
|
ins_add(int IR, int off)
|
||||||
{
|
{
|
||||||
uint16 d = rdmem(off);
|
uint16 d = rdmem(off, SELPT2(IR));
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (ID(IR) == ID(ND_SUB))
|
if (ID(IR) == ID(ND_SUB))
|
||||||
@ -354,7 +361,7 @@ ins_add(int IR, int off)
|
|||||||
int
|
int
|
||||||
ins_andor(int IR, int off)
|
ins_andor(int IR, int off)
|
||||||
{
|
{
|
||||||
uint16 s = rdmem(off);
|
uint16 s = rdmem(off, SELPT2(IR));
|
||||||
|
|
||||||
regA = BIT11(IR) ? (regA | s) : (regA & s);
|
regA = BIT11(IR) ? (regA | s) : (regA & s);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
@ -394,7 +401,7 @@ static void
|
|||||||
ins_bfill(int IR)
|
ins_bfill(int IR)
|
||||||
{
|
{
|
||||||
while (regT & 07777) {
|
while (regT & 07777) {
|
||||||
wrbyte(regX, regA, BIT15(regT));
|
wrbyte(regX, regA, BIT15(regT), M_APT);
|
||||||
regT--;
|
regT--;
|
||||||
regT ^= 0100000;
|
regT ^= 0100000;
|
||||||
if (BIT15(regT) == 0)
|
if (BIT15(regT) == 0)
|
||||||
@ -442,8 +449,8 @@ ins_movb(int IR)
|
|||||||
|
|
||||||
if (regX > regA) { /* copy bottom-top */
|
if (regX > regA) { /* copy bottom-top */
|
||||||
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
||||||
int8 w = rdbyte(regA, BIT15(regD));
|
int8 w = rdbyte(regA, BIT15(regD), M_APT);
|
||||||
wrbyte(regX, w, BIT15(regT));
|
wrbyte(regX, w, BIT15(regT), M_APT);
|
||||||
regD ^= 0100000;
|
regD ^= 0100000;
|
||||||
if (BIT15(regD) == 0) regA++;
|
if (BIT15(regD) == 0) regA++;
|
||||||
regT ^= 0100000;
|
regT ^= 0100000;
|
||||||
@ -494,8 +501,8 @@ ins_movbf(int IR)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
||||||
int8 w = rdbyte(regA, BIT15(regD));
|
int8 w = rdbyte(regA, BIT15(regD), M_APT);
|
||||||
wrbyte(regX, w, BIT15(regT));
|
wrbyte(regX, w, BIT15(regT), M_APT);
|
||||||
regD ^= 0100000;
|
regD ^= 0100000;
|
||||||
if (BIT15(regD) == 0) regA++;
|
if (BIT15(regD) == 0) regA++;
|
||||||
regT ^= 0100000;
|
regT ^= 0100000;
|
||||||
@ -515,11 +522,41 @@ ins_skip_ext(int IR)
|
|||||||
uint16 d;
|
uint16 d;
|
||||||
int16 ss, sd;
|
int16 ss, sd;
|
||||||
int32 shc;
|
int32 shc;
|
||||||
int reason = 0;
|
int paddr, reason = 0;
|
||||||
|
|
||||||
if ((IR & 0177707) == ND_SKP_CLEPT) {
|
if ((IR & 0177707) == ND_SKP_CLEPT) {
|
||||||
intrpt14(IIE_II);
|
intrpt14(IIE_II, PM_CPU);
|
||||||
regP--;
|
} else if ((IR & 0177700) == ND_SKP_LDATX) {
|
||||||
|
/* Special physmem instructions */
|
||||||
|
d = regX + ((IR & 070) >> 3);
|
||||||
|
paddr = ((unsigned int)regT << 16) | (unsigned int)d;
|
||||||
|
switch (IR & ~070) {
|
||||||
|
case ND_SKP_LDATX:
|
||||||
|
regA = prdmem(paddr, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_STZTX:
|
||||||
|
pwrmem(paddr, 0, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_STATX:
|
||||||
|
pwrmem(paddr, regA, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_STDTX:
|
||||||
|
pwrmem(paddr++, regA, PM_CPU);
|
||||||
|
pwrmem(paddr, regD, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_LDXTX:
|
||||||
|
regX = prdmem(paddr, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_LDDTX:
|
||||||
|
regA = prdmem(paddr++, PM_CPU);
|
||||||
|
regD = prdmem(paddr, PM_CPU);
|
||||||
|
break;
|
||||||
|
case ND_SKP_LDBTX:
|
||||||
|
regB = (prdmem(paddr, PM_CPU) << 1) | 0177000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
intrpt14(IIE_II, PM_CPU);
|
||||||
|
}
|
||||||
} else if (IR == ND_SKP_MIX3) {
|
} else if (IR == ND_SKP_MIX3) {
|
||||||
/* X = (A-1)*3 */
|
/* X = (A-1)*3 */
|
||||||
regX = (regA-1)*3;
|
regX = (regA-1)*3;
|
||||||
@ -531,14 +568,22 @@ ins_skip_ext(int IR)
|
|||||||
identrm(12);
|
identrm(12);
|
||||||
} else if (IR == ND_SKP_IDENT13) {
|
} else if (IR == ND_SKP_IDENT13) {
|
||||||
identrm(13);
|
identrm(13);
|
||||||
} else if (IR == ND_SKP_BFILL)
|
} else if (IR == ND_SKP_ADDD) {
|
||||||
|
intrpt14(IIE_II, PM_CPU);
|
||||||
|
} else if (IR == ND_SKP_BFILL) {
|
||||||
ins_bfill(IR);
|
ins_bfill(IR);
|
||||||
else if (IR == ND_SKP_MOVB)
|
} else if (IR == ND_SKP_MOVB) {
|
||||||
ins_movb(IR);
|
ins_movb(IR);
|
||||||
else if (IR == ND_SKP_MOVBF)
|
} else if (IR == ND_SKP_MOVBF) {
|
||||||
ins_movbf(IR);
|
ins_movbf(IR);
|
||||||
else if (IR == ND_SKP_LBYT) {
|
} else if (IR == ND_SKP_LWCS) {
|
||||||
d = rdmem(regT + (regX >> 1));
|
;
|
||||||
|
} else if (IR == 0140127) { /* XXX */
|
||||||
|
intrpt14(IIE_II, PM_CPU);
|
||||||
|
} else if (IR == ND_SKP_VERSN) {
|
||||||
|
intrpt14(IIE_II, PM_CPU);
|
||||||
|
} else if (IR == ND_SKP_LBYT) {
|
||||||
|
d = rdmem(regT + (regX >> 1), M_APT);
|
||||||
if (regX & 1)
|
if (regX & 1)
|
||||||
regA = d & 0377;
|
regA = d & 0377;
|
||||||
else
|
else
|
||||||
@ -546,9 +591,9 @@ ins_skip_ext(int IR)
|
|||||||
} else if (IR == ND_SKP_SBYT) {
|
} else if (IR == ND_SKP_SBYT) {
|
||||||
d = regT + (regX >> 1);
|
d = regT + (regX >> 1);
|
||||||
if (regX & 1)
|
if (regX & 1)
|
||||||
wrmem(d, (rdmem(d) & 0xff00) | (regA & 0xff));
|
wrmem(d, (rdmem(d, M_APT) & 0xff00) | (regA & 0xff), M_APT);
|
||||||
else
|
else
|
||||||
wrmem(d, (rdmem(d) & 0xff) | (regA << 8));
|
wrmem(d, (rdmem(d, M_APT) & 0xff) | (regA << 8), M_APT);
|
||||||
} else if ((IR & 0177700) == ND_SKP_RMPY) {
|
} else if ((IR & 0177700) == ND_SKP_RMPY) {
|
||||||
ss = R[(IR & 070) >> 3];
|
ss = R[(IR & 070) >> 3];
|
||||||
sd = R[IR & 07];
|
sd = R[IR & 07];
|
||||||
@ -560,10 +605,9 @@ ins_skip_ext(int IR)
|
|||||||
shc = (regA << 16) | regD;
|
shc = (regA << 16) | regD;
|
||||||
regA = shc / ss;
|
regA = shc / ss;
|
||||||
regD = shc % ss;
|
regD = shc % ss;
|
||||||
} else if (IR == 0142700) {
|
} else if (IR == 0142700 || IR == 0143700) {
|
||||||
/* ??? what is this? */
|
/* ??? what is this? */
|
||||||
intrpt14(IIE_II);
|
intrpt14(IIE_II, PM_CPU);
|
||||||
regP--;
|
|
||||||
} else
|
} else
|
||||||
reason = STOP_UNHINS;
|
reason = STOP_UNHINS;
|
||||||
return reason;
|
return reason;
|
||||||
@ -590,11 +634,10 @@ ins_srb(int IR)
|
|||||||
/* Save current level (maybe used) to reg block */
|
/* Save current level (maybe used) to reg block */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
RBLK[curlvl][i] = R[i];
|
RBLK[curlvl][i] = R[i];
|
||||||
RBLK[curlvl][rnP]++; /* following insn */
|
|
||||||
|
|
||||||
/* store requested block to memory */
|
/* store requested block to memory */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
wrmem(regX+i, RBLK[n][s2r[i]]);
|
wrmem(regX+i, RBLK[n][s2r[i]], M_APT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -614,7 +657,7 @@ ins_lrb(int IR)
|
|||||||
|
|
||||||
/* fetch from memory */
|
/* fetch from memory */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
RBLK[n][s2r[i]] = rdmem(regX+i);
|
RBLK[n][s2r[i]] = rdmem(regX+i, M_APT);
|
||||||
RBLK[n][rnSTS] &= 0377;
|
RBLK[n][rnSTS] &= 0377;
|
||||||
|
|
||||||
if (n == curlvl)
|
if (n == curlvl)
|
||||||
@ -623,6 +666,56 @@ ins_lrb(int IR)
|
|||||||
R[i] = RBLK[n][i];
|
R[i] = RBLK[n][i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Priv instructions, mostly for handling status reg.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nd_mis_opc(int IR)
|
||||||
|
{
|
||||||
|
static int srbits[] = { 0, STS_IONI, STS_IONI, 0,
|
||||||
|
STS_PONI, (STS_PONI|STS_IONI), STS_SEXI, STS_SEXI,
|
||||||
|
STS_PONI, 0, (STS_PONI|STS_IONI) };
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
mm_privcheck();
|
||||||
|
switch (IR) {
|
||||||
|
/* case ND_MIS_OPCOM: */
|
||||||
|
/* break; */
|
||||||
|
|
||||||
|
case ND_MIS_IOF:
|
||||||
|
case ND_MIS_POF:
|
||||||
|
case ND_MIS_PIOF:
|
||||||
|
case ND_MIS_REX:
|
||||||
|
regSTH &= ~srbits[IR & 017];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_MIS_ION:
|
||||||
|
case ND_MIS_SEX:
|
||||||
|
case ND_MIS_PON:
|
||||||
|
case ND_MIS_PION:
|
||||||
|
regSTH |= srbits[IR & 017];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_MIS_IOXT:
|
||||||
|
rv = iox_check(regT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_MIS_EXAM:
|
||||||
|
regT = prdmem((regA << 16) | regD, M_FETCH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_MIS_DEPO:
|
||||||
|
pwrmem((regA << 16) | regD, regT, M_FETCH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rv = STOP_UNHINS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Miscellaneous instructions.
|
* Miscellaneous instructions.
|
||||||
*/
|
*/
|
||||||
@ -632,29 +725,9 @@ ins_mis(int IR, int off)
|
|||||||
int reason = 0;
|
int reason = 0;
|
||||||
int n, i;
|
int n, i;
|
||||||
|
|
||||||
if (IR == ND_MIS_SEX)
|
if ((IR & 0177760) == ND_MIS_OPCOM)
|
||||||
regSTH |= STS_SEXI;
|
reason = nd_mis_opc(IR);
|
||||||
else if (IR == ND_MIS_DEPO) {
|
else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRA)
|
||||||
if ((n = ((regA << 16) | regD)) <= MAXMEMSIZE)
|
|
||||||
PM[n] = regT;
|
|
||||||
} else if (IR == ND_MIS_EXAM) {
|
|
||||||
if ((n = ((regA << 16) | regD)) <= MAXMEMSIZE)
|
|
||||||
regT = PM[n];
|
|
||||||
} else if (IR == ND_MIS_REX) {
|
|
||||||
regSTH &= ~STS_SEXI;
|
|
||||||
} else if (IR == ND_MIS_PON) {
|
|
||||||
regSTH |= STS_PONI;
|
|
||||||
} else if (IR == ND_MIS_POF) {
|
|
||||||
regSTH &= ~STS_PONI;
|
|
||||||
} else if (IR == ND_MIS_ION) {
|
|
||||||
regSTH |= STS_IONI;
|
|
||||||
} else if (IR == ND_MIS_IOF) {
|
|
||||||
regSTH &= ~STS_IONI;
|
|
||||||
} else if (IR == ND_MIS_PIOF) {
|
|
||||||
regSTH &= ~(STS_IONI|STS_PONI);
|
|
||||||
} else if (IR == ND_MIS_IOXT) {
|
|
||||||
reason = iox_check(regT);
|
|
||||||
} else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRA)
|
|
||||||
reason = nd_tra(IR & ~ND_MIS_TRMSK);
|
reason = nd_tra(IR & ~ND_MIS_TRMSK);
|
||||||
else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRR)
|
else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRR)
|
||||||
reason = nd_trr(IR & ~ND_MIS_TRMSK);
|
reason = nd_trr(IR & ~ND_MIS_TRMSK);
|
||||||
@ -663,12 +736,14 @@ ins_mis(int IR, int off)
|
|||||||
else if ((IR & ND_MIS_TRMSK) == ND_MIS_MCL)
|
else if ((IR & ND_MIS_TRMSK) == ND_MIS_MCL)
|
||||||
reason = nd_mcl(IR & ~ND_MIS_TRMSK);
|
reason = nd_mcl(IR & ~ND_MIS_TRMSK);
|
||||||
else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRR) {
|
else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRR) {
|
||||||
|
mm_privcheck();
|
||||||
n = (IR >> 3) & 017;
|
n = (IR >> 3) & 017;
|
||||||
if (n == curlvl)
|
if (n == curlvl)
|
||||||
regA = R[IR & 07];
|
regA = R[IR & 07];
|
||||||
else
|
else
|
||||||
regA = RBLK[n][IR & 07];
|
regA = RBLK[n][IR & 07];
|
||||||
} else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRW) {
|
} else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRW) {
|
||||||
|
mm_privcheck();
|
||||||
n = (IR >> 3) & 017;
|
n = (IR >> 3) & 017;
|
||||||
RBLK[n][IR & 07] = regA;
|
RBLK[n][IR & 07] = regA;
|
||||||
if (n == curlvl && (IR & 07) != rnP)
|
if (n == curlvl && (IR & 07) != rnP)
|
||||||
@ -679,21 +754,18 @@ ins_mis(int IR, int off)
|
|||||||
ins_lrb(IR);
|
ins_lrb(IR);
|
||||||
} else if ((IR & ND_MONMSK) == ND_MON) {
|
} else if ((IR & ND_MONMSK) == ND_MON) {
|
||||||
RBLK[14][rnT] = SEXT8(IR);
|
RBLK[14][rnT] = SEXT8(IR);
|
||||||
intrpt14(IIE_MC);
|
intrpt14(IIE_MC, PM_CPU);
|
||||||
} else if ((IR & ND_MONMSK) == ND_WAIT) {
|
} else if ((IR & ND_MONMSK) == ND_WAIT) {
|
||||||
if (ISION() == 0) {
|
if (ISION() == 0) {
|
||||||
regP++;
|
|
||||||
reason = STOP_WAIT;
|
reason = STOP_WAIT;
|
||||||
} else if (curlvl > 0) {
|
} else if (curlvl > 0) {
|
||||||
pid &= ~(1 << curlvl);
|
pid &= ~(1 << curlvl);
|
||||||
n = highest_level();
|
n = highest_level();
|
||||||
if (curlvl != n) {
|
if (curlvl != n) {
|
||||||
regP++;
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
RBLK[curlvl][i] = R[i];
|
RBLK[curlvl][i] = R[i];
|
||||||
R[i] = RBLK[n][i];
|
R[i] = RBLK[n][i];
|
||||||
}
|
}
|
||||||
regP--;
|
|
||||||
}
|
}
|
||||||
curlvl = n;
|
curlvl = n;
|
||||||
}
|
}
|
||||||
@ -794,6 +866,7 @@ ins_bop(int IR, int addr)
|
|||||||
|
|
||||||
int rd, n, reason = 0;
|
int rd, n, reason = 0;
|
||||||
|
|
||||||
|
regSTL = (regSTL & 0377) | regSTH; /* Hack for bskp */
|
||||||
rd = IR & 7;
|
rd = IR & 7;
|
||||||
n = (IR >> 3) & 017;
|
n = (IR >> 3) & 017;
|
||||||
switch ((IR >> 7) & 017) {
|
switch ((IR >> 7) & 017) {
|
||||||
@ -826,7 +899,6 @@ ins_bop(int IR, int addr)
|
|||||||
regP++;
|
regP++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 010: /* BSTA store ~K and set K */
|
case 010: /* BSTA store ~K and set K */
|
||||||
R[rd] &= ~(1 << n);
|
R[rd] &= ~(1 << n);
|
||||||
if ((regSTL & STS_K) == 0)
|
if ((regSTL & STS_K) == 0)
|
||||||
@ -885,6 +957,7 @@ ins_bop(int IR, int addr)
|
|||||||
reason = STOP_UNHINS;
|
reason = STOP_UNHINS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
regSTL &= 0377;
|
||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,11 +1073,11 @@ int
|
|||||||
ins_fmu(int IR, int addr)
|
ins_fmu(int IR, int addr)
|
||||||
{
|
{
|
||||||
struct fp f1, f2;
|
struct fp f1, f2;
|
||||||
int s3, e3;
|
int s3, e3, pt = SELPT2(IR);
|
||||||
t_uint64 m3;
|
t_uint64 m3;
|
||||||
|
|
||||||
/* Fetch from memory */
|
/* Fetch from memory */
|
||||||
mkfp48(&f1, rdmem(addr), rdmem(addr+1), rdmem(addr+2));
|
mkfp48(&f1, rdmem(addr, pt), rdmem(addr+1, pt), rdmem(addr+2, pt));
|
||||||
|
|
||||||
/* From registers */
|
/* From registers */
|
||||||
mkfp48(&f2, regT, regA, regD);
|
mkfp48(&f2, regT, regA, regD);
|
||||||
@ -1044,11 +1117,12 @@ int
|
|||||||
ins_fdv(int IR, int addr)
|
ins_fdv(int IR, int addr)
|
||||||
{
|
{
|
||||||
struct fp f1, f2;
|
struct fp f1, f2;
|
||||||
int s3, e3;
|
int s3, e3, pt;
|
||||||
t_uint64 m3;
|
t_uint64 m3;
|
||||||
|
|
||||||
/* Fetch from memory */
|
/* Fetch from memory */
|
||||||
mkfp48(&f1, rdmem(addr), rdmem(addr+1), rdmem(addr+2));
|
pt = SELPT2(IR);
|
||||||
|
mkfp48(&f1, rdmem(addr, pt), rdmem(addr+1, pt), rdmem(addr+2, pt));
|
||||||
|
|
||||||
/* From registers */
|
/* From registers */
|
||||||
mkfp48(&f2, regT, regA, regD);
|
mkfp48(&f2, regT, regA, regD);
|
||||||
@ -1059,7 +1133,7 @@ ins_fdv(int IR, int addr)
|
|||||||
regSTL |= STS_Z;
|
regSTL |= STS_Z;
|
||||||
regT |= 077777;
|
regT |= 077777;
|
||||||
regA = regD = 0177777;
|
regA = regD = 0177777;
|
||||||
intrpt14(IIE_V);
|
intrpt14(IIE_V, PM_CPU);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,8 +1251,9 @@ int
|
|||||||
ins_fad(int IR, int addr)
|
ins_fad(int IR, int addr)
|
||||||
{
|
{
|
||||||
struct fp f1, f2;
|
struct fp f1, f2;
|
||||||
|
int pt = SELPT2(IR);
|
||||||
|
|
||||||
mkfp48(&f1, rdmem(addr), rdmem(addr+1), rdmem(addr+2));
|
mkfp48(&f1, rdmem(addr, pt), rdmem(addr+1, pt), rdmem(addr+2, pt));
|
||||||
mkfp48(&f2, regT, regA, regD);
|
mkfp48(&f2, regT, regA, regD);
|
||||||
|
|
||||||
if (f1.s ^ f2.s)
|
if (f1.s ^ f2.s)
|
||||||
@ -1192,8 +1267,9 @@ int
|
|||||||
ins_fsb(int IR, int addr)
|
ins_fsb(int IR, int addr)
|
||||||
{
|
{
|
||||||
struct fp f1, f2;
|
struct fp f1, f2;
|
||||||
|
int pt = SELPT2(IR);
|
||||||
|
|
||||||
mkfp48(&f1, rdmem(addr), rdmem(addr+1), rdmem(addr+2));
|
mkfp48(&f1, rdmem(addr, pt), rdmem(addr+1, pt), rdmem(addr+2, pt));
|
||||||
mkfp48(&f2, regT, regA, regD);
|
mkfp48(&f2, regT, regA, regD);
|
||||||
|
|
||||||
f1.s ^= 1; /* swap sign of right op */
|
f1.s ^= 1; /* swap sign of right op */
|
||||||
@ -1233,7 +1309,7 @@ add3(uint16 a, uint16 d, uint16 c)
|
|||||||
int
|
int
|
||||||
ins_mpy(int IR, int off)
|
ins_mpy(int IR, int off)
|
||||||
{
|
{
|
||||||
int res = (int)(int16)regA * (int)(int16)rdmem(off);
|
int res = (int)(int16)regA * (int)(int16)rdmem(off, SELPT2(IR));
|
||||||
regA = res;
|
regA = res;
|
||||||
regSTL &= ~STS_Q;
|
regSTL &= ~STS_Q;
|
||||||
if (res > 32767)
|
if (res > 32767)
|
||||||
@ -1248,12 +1324,13 @@ int
|
|||||||
ins_jmpl(int IR, int off)
|
ins_jmpl(int IR, int off)
|
||||||
{
|
{
|
||||||
if (BIT12(IR))
|
if (BIT12(IR))
|
||||||
regL = regP+1;
|
regL = regP;
|
||||||
regP = off-1;
|
regP = off;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Conditional jump.
|
* Conditional jump.
|
||||||
|
* off is unused here.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ins_cjp(int IR, int off)
|
ins_cjp(int IR, int off)
|
||||||
@ -1313,8 +1390,6 @@ ins_rop(int IR, int off)
|
|||||||
rd = IR & 07;
|
rd = IR & 07;
|
||||||
s = rs ? R[rs] : 0;
|
s = rs ? R[rs] : 0;
|
||||||
d = rd ? R[rd] : 0;
|
d = rd ? R[rd] : 0;
|
||||||
if (rs == 2) s++;
|
|
||||||
if (rd == 2) d++;
|
|
||||||
if (BIT6(IR)) d = 0; /* clear dest */
|
if (BIT6(IR)) d = 0; /* clear dest */
|
||||||
if (BIT7(IR)) s = ~s; /* complement src */
|
if (BIT7(IR)) s = ~s; /* complement src */
|
||||||
if (BIT10(IR)) { /* add source to destination */
|
if (BIT10(IR)) { /* add source to destination */
|
||||||
@ -1335,7 +1410,6 @@ ins_rop(int IR, int off)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rd) R[rd] = d;
|
if (rd) R[rd] = d;
|
||||||
if (rd == 2) regP--;
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,28 +1419,17 @@ ins_rop(int IR, int off)
|
|||||||
static int
|
static int
|
||||||
iox_check(int dev)
|
iox_check(int dev)
|
||||||
{
|
{
|
||||||
#ifdef TIMERHACK
|
|
||||||
if ((dev & 03777) == 011) {
|
mm_privcheck();
|
||||||
rtccnt = 0;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
if ((dev & 03777) == 013) {
|
|
||||||
rtc_int_enabled = regA & 1;
|
|
||||||
if ((regA >> 13) & 1)
|
|
||||||
rtc_dev_ready = 0;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if ((dev & 0177774) == 010)
|
if ((dev & 0177774) == 010)
|
||||||
return iox_clk(dev);
|
return iox_clk(dev);
|
||||||
#endif
|
|
||||||
if ((dev & 0177770) == 0300)
|
if ((dev & 0177770) == 0300)
|
||||||
return iox_tty(dev);
|
return iox_tty(dev);
|
||||||
if ((dev & 0177770) == 01560)
|
if ((dev & 0177770) == 01560)
|
||||||
return iox_floppy(dev);
|
return iox_floppy(dev);
|
||||||
|
|
||||||
intrpt14(IIE_IOX);
|
intrpt14(IIE_IOX, PM_CPU);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1376,15 +1439,15 @@ getoff(int ir)
|
|||||||
{
|
{
|
||||||
int ea;
|
int ea;
|
||||||
|
|
||||||
ea = BIT8(ir) ? regB : regP;
|
ea = BIT8(ir) ? regB : oregP;
|
||||||
if (BIT10(ir) & !BIT9(ir))
|
if (BIT10(ir) & !BIT9(ir) & !BIT8(ir))
|
||||||
ea = 0;
|
ea = 0;
|
||||||
ea += SEXT8(ir);
|
ea += SEXT8(ir);
|
||||||
if (BIT9(ir))
|
if (BIT9(ir))
|
||||||
ea = rdmem(ea);
|
ea = rdmem(ea & 0177777, BIT8(ir) ? M_APT : M_PT);
|
||||||
if (BIT10(ir))
|
if (BIT10(ir))
|
||||||
ea += regX;
|
ea += regX;
|
||||||
return ea;
|
return ea & 0177777;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1395,6 +1458,8 @@ nd_mcl(int reg)
|
|||||||
{
|
{
|
||||||
int reason = SCPE_OK;
|
int reason = SCPE_OK;
|
||||||
|
|
||||||
|
mm_privcheck();
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case IR_STS:
|
case IR_STS:
|
||||||
regSTL &= ~(regA & 0377);
|
regSTL &= ~(regA & 0377);
|
||||||
@ -1421,14 +1486,16 @@ nd_mst(int reg)
|
|||||||
{
|
{
|
||||||
int reason = SCPE_OK;
|
int reason = SCPE_OK;
|
||||||
|
|
||||||
|
mm_privcheck();
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case IR_STS:
|
case IR_STS:
|
||||||
regSTL |= (regA & 0377);
|
regSTL |= (regA & 0377);
|
||||||
break;
|
break;
|
||||||
case 006: /* PID */
|
case IR_PID: /* PID */
|
||||||
pid |= regA;
|
pid |= regA;
|
||||||
break;
|
break;
|
||||||
case 007: /* PIE */
|
case IR_PIE: /* PIE */
|
||||||
pie |= regA;
|
pie |= regA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1446,6 +1513,8 @@ nd_trr(int reg)
|
|||||||
{
|
{
|
||||||
int reason = SCPE_OK;
|
int reason = SCPE_OK;
|
||||||
|
|
||||||
|
mm_privcheck();
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case IR_STS:
|
case IR_STS:
|
||||||
regSTL = regA & 0377;
|
regSTL = regA & 0377;
|
||||||
@ -1457,7 +1526,7 @@ nd_trr(int reg)
|
|||||||
mm_wrpcr();
|
mm_wrpcr();
|
||||||
break;
|
break;
|
||||||
case 005: /* IIE */
|
case 005: /* IIE */
|
||||||
iie = regA & 02776;
|
iie = regA & 03776;
|
||||||
break;
|
break;
|
||||||
case 006: /* PID */
|
case 006: /* PID */
|
||||||
pid = regA;
|
pid = regA;
|
||||||
@ -1465,6 +1534,12 @@ nd_trr(int reg)
|
|||||||
case 007: /* PIE */
|
case 007: /* PIE */
|
||||||
pie = regA;
|
pie = regA;
|
||||||
break;
|
break;
|
||||||
|
case IR_CCL:
|
||||||
|
break;
|
||||||
|
case IR_LCIL:
|
||||||
|
break;
|
||||||
|
case IR_UCIL:
|
||||||
|
break;
|
||||||
case IR_ECCR:
|
case IR_ECCR:
|
||||||
eccr = regA;
|
eccr = regA;
|
||||||
break;
|
break;
|
||||||
@ -1482,15 +1557,20 @@ nd_tra(int reg)
|
|||||||
{
|
{
|
||||||
int reason = SCPE_OK;
|
int reason = SCPE_OK;
|
||||||
|
|
||||||
|
mm_privcheck();
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
|
case IR_PANS:
|
||||||
|
regA = 0;
|
||||||
|
break;
|
||||||
case IR_STS: /* STS */
|
case IR_STS: /* STS */
|
||||||
regA = regSTL | regSTH | (curlvl << 8);
|
regA = regSTL | regSTH | (curlvl << 8);
|
||||||
break;
|
break;
|
||||||
case IR_PGS: /* 3 */
|
case IRR_OPR:
|
||||||
regA = 0; /* XXX */
|
regA = opr;
|
||||||
break;
|
break;
|
||||||
case IR_PVL: /* 4 */
|
case IRR_PVL:
|
||||||
regA = pvl;
|
regA = (pvl << 3) | 0153602;
|
||||||
break;
|
break;
|
||||||
case IR_IIC: /* read IIC. Clears IIC and IID */
|
case IR_IIC: /* read IIC. Clears IIC and IID */
|
||||||
regA = iic;
|
regA = iic;
|
||||||
@ -1509,23 +1589,14 @@ nd_tra(int reg)
|
|||||||
case 012: /* ALD */
|
case 012: /* ALD */
|
||||||
regA = ald;
|
regA = ald;
|
||||||
break;
|
break;
|
||||||
case 013: /* PES */
|
|
||||||
regA = 0; /* XXX */
|
|
||||||
break;
|
|
||||||
case 014: /* read back PCR */
|
|
||||||
mm_rdpcr();
|
|
||||||
break;
|
|
||||||
case 015: /* */
|
|
||||||
regA = 0; /* XXX */
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
reason = STOP_UNHINS;
|
reason = mm_tra(reg);
|
||||||
}
|
}
|
||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
highest_level(void)
|
highest_level()
|
||||||
{
|
{
|
||||||
int i, d = pid & pie;
|
int i, d = pid & pie;
|
||||||
|
|
||||||
@ -1555,14 +1626,19 @@ fls(int msk)
|
|||||||
* Post an internal interrupt for the given source.
|
* Post an internal interrupt for the given source.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
intrpt14(int src)
|
intrpt14(int src, int where)
|
||||||
{
|
{
|
||||||
iid |= src; /* set detect flipflop */
|
iid |= src; /* set detect flipflop */
|
||||||
for (iic = 0; (src & 1) == 0; iic++, src >>= 1)
|
for (iic = 0; (src & 1) == 0; iic++, src >>= 1)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (iid & iie) /* if internal int enabled, post priority int */
|
if (iid & iie) { /* if internal int enabled, post priority int */
|
||||||
pid |= (1 << 14);
|
pid |= (1 << 14);
|
||||||
|
/* If we can interrupt, jump directly back */
|
||||||
|
if (ISION() && curlvl < 14 && (pie & (1 << 14)) &&
|
||||||
|
(where == PM_CPU))
|
||||||
|
longjmp(env, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1587,7 +1663,8 @@ identrm(int id)
|
|||||||
struct intr *ip = ilnk[id-10];
|
struct intr *ip = ilnk[id-10];
|
||||||
|
|
||||||
if (ip == 0) {
|
if (ip == 0) {
|
||||||
intrpt14(IIE_IOX);
|
intrpt14(IIE_IOX, PM_CPU);
|
||||||
|
regA = 0;
|
||||||
} else {
|
} else {
|
||||||
regA = ip->ident;
|
regA = ip->ident;
|
||||||
ilnk[id-10] = ip->next;
|
ilnk[id-10] = ip->next;
|
||||||
@ -1598,21 +1675,6 @@ identrm(int id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TIMERHACK
|
|
||||||
struct intr rtc_intx = { 0, 1 };
|
|
||||||
void
|
|
||||||
chkrtc(void)
|
|
||||||
{
|
|
||||||
if (rtccnt++ < 5001)
|
|
||||||
return;
|
|
||||||
rtccnt = 0;
|
|
||||||
rtc_dev_ready = 1;
|
|
||||||
if (rtc_int_enabled) {
|
|
||||||
extint(13, &rtc_intx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hist_save(int ir)
|
hist_save(int ir)
|
||||||
{
|
{
|
||||||
@ -1626,13 +1688,13 @@ hist_save(int ir)
|
|||||||
|
|
||||||
hist_ptr->ir = ir;
|
hist_ptr->ir = ir;
|
||||||
hist_ptr->sts = regSTL | regSTH | (curlvl << 8);
|
hist_ptr->sts = regSTL | regSTH | (curlvl << 8);
|
||||||
hist_ptr->d = R[1];
|
hist_ptr->d = regD;
|
||||||
hist_ptr->p = R[2];
|
hist_ptr->p = oregP;
|
||||||
hist_ptr->b = R[3];
|
hist_ptr->b = regB;
|
||||||
hist_ptr->l = R[4];
|
hist_ptr->l = regL;
|
||||||
hist_ptr->a = R[5];
|
hist_ptr->a = regA;
|
||||||
hist_ptr->t = R[6];
|
hist_ptr->t = regT;
|
||||||
hist_ptr->x = R[7];
|
hist_ptr->x = regX;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat
|
t_stat
|
||||||
@ -1732,4 +1794,3 @@ hist_show(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
|||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,14 +82,24 @@
|
|||||||
|
|
||||||
#define ND_SKP_CLEPT 0140301
|
#define ND_SKP_CLEPT 0140301
|
||||||
#define ND_SKP_EXR 0140600
|
#define ND_SKP_EXR 0140600
|
||||||
|
#define ND_SKP_ADDD 0140120 /* CE/CX */
|
||||||
#define ND_SKP_BFILL 0140130
|
#define ND_SKP_BFILL 0140130
|
||||||
#define ND_SKP_MOVB 0140131
|
#define ND_SKP_MOVB 0140131
|
||||||
#define ND_SKP_MOVBF 0140132
|
#define ND_SKP_MOVBF 0140132
|
||||||
|
#define ND_SKP_VERSN 0140133 /* ND110 */
|
||||||
#define ND_SKP_RMPY 0141200
|
#define ND_SKP_RMPY 0141200
|
||||||
#define ND_SKP_RDIV 0141600
|
#define ND_SKP_RDIV 0141600
|
||||||
#define ND_SKP_LBYT 0142200
|
#define ND_SKP_LBYT 0142200
|
||||||
#define ND_SKP_SBYT 0142600
|
#define ND_SKP_SBYT 0142600
|
||||||
#define ND_SKP_MIX3 0143200
|
#define ND_SKP_MIX3 0143200
|
||||||
|
#define ND_SKP_LDATX 0143300 /* ND100 */
|
||||||
|
#define ND_SKP_LDXTX 0143301 /* ND100 */
|
||||||
|
#define ND_SKP_LDDTX 0143302 /* ND100 */
|
||||||
|
#define ND_SKP_LDBTX 0143303 /* ND100 */
|
||||||
|
#define ND_SKP_STATX 0143304 /* ND100 */
|
||||||
|
#define ND_SKP_STZTX 0143305 /* ND100 */
|
||||||
|
#define ND_SKP_STDTX 0143306 /* ND100 */
|
||||||
|
#define ND_SKP_LWCS 0143500 /* NOP on N110 */
|
||||||
#define ND_SKP_IDENT10 0143604
|
#define ND_SKP_IDENT10 0143604
|
||||||
#define ND_SKP_IDENT11 0143611
|
#define ND_SKP_IDENT11 0143611
|
||||||
#define ND_SKP_IDENT12 0143622
|
#define ND_SKP_IDENT12 0143622
|
||||||
@ -115,6 +125,7 @@
|
|||||||
#define ND_WAIT 0151000
|
#define ND_WAIT 0151000
|
||||||
#define ND_MONMSK 0177400
|
#define ND_MONMSK 0177400
|
||||||
|
|
||||||
|
#define ND_MIS_OPCOM 0150400
|
||||||
#define ND_MIS_IOF 0150401
|
#define ND_MIS_IOF 0150401
|
||||||
#define ND_MIS_ION 0150402
|
#define ND_MIS_ION 0150402
|
||||||
#define ND_MIS_POF 0150404
|
#define ND_MIS_POF 0150404
|
||||||
@ -128,20 +139,32 @@
|
|||||||
#define ND_MIS_DEPO 0150417
|
#define ND_MIS_DEPO 0150417
|
||||||
|
|
||||||
/* Internal registers */
|
/* Internal registers */
|
||||||
|
#define IR_PANS 000 /* Panel status */
|
||||||
#define IR_STS 001 /* Status reg (as in register stack) */
|
#define IR_STS 001 /* Status reg (as in register stack) */
|
||||||
#define IR_OPR 002 /* Operator reg */
|
|
||||||
#define IR_LMP 002 /* Display reg */
|
#define IR_LMP 002 /* Display reg */
|
||||||
#define IR_PGS 003 /* paging status reg */
|
|
||||||
#define IR_PCR 003 /* paging control reg */
|
#define IR_PCR 003 /* paging control reg */
|
||||||
#define IR_PVL 004 /* Previous level */
|
|
||||||
#define IR_IIC 005 /* Internal interrupt code */
|
#define IR_IIC 005 /* Internal interrupt code */
|
||||||
#define IR_IIE 005 /* Internal interrupt enable */
|
#define IR_IIE 005 /* Internal interrupt enable */
|
||||||
#define IR_PID 006 /* Priority interrupt detect */
|
#define IR_PID 006 /* Priority interrupt detect */
|
||||||
#define IR_PIE 007 /* Priority interrupt enable */
|
#define IR_PIE 007 /* Priority interrupt enable */
|
||||||
#define IR_CSR 010 /* Cache status reg */
|
#define IR_CSR 010 /* Cache status reg */
|
||||||
#define IR_PCR14 014 /* paging control reg */
|
#define IR_CCL 010 /* (W) Cache clear reg */
|
||||||
|
#define IR_LCIL 011 /* (W) Lower cache inhibit limit register */
|
||||||
|
#define IR_UCIL 012 /* (W) Upper cache inhibit limit register */
|
||||||
#define IR_ECCR 015 /* Error Correction Control Register */
|
#define IR_ECCR 015 /* Error Correction Control Register */
|
||||||
|
|
||||||
|
#define IRR_OPR 002 /* Operator reg */
|
||||||
|
#define IRR_PGS 003 /* paging status reg */
|
||||||
|
#define PGS_FF 0100000 /* fetch fault */
|
||||||
|
#define PGS_PM 0040000 /* permit violation */
|
||||||
|
#define IRR_PVL 004 /* Previous level (oddly encoded) */
|
||||||
|
#define IRR_PES 013 /* Parity error status */
|
||||||
|
#define PES_FETCH 0100000 /* Memory error during fetch, EXAM or DEPO */
|
||||||
|
#define PES_DMA 0040000 /* Error occurred during DMA */
|
||||||
|
#define IRR_PGC 014 /* Read paging control reg */
|
||||||
|
#define IRR_PEA 015 /* Parity error address */
|
||||||
|
int mm_tra(int reg);
|
||||||
|
|
||||||
/* internal interrupt enable register */
|
/* internal interrupt enable register */
|
||||||
#define IIE_MC 0000002 /* Monitor call */
|
#define IIE_MC 0000002 /* Monitor call */
|
||||||
#define IIE_PV 0000004 /* Protect Violation */
|
#define IIE_PV 0000004 /* Protect Violation */
|
||||||
@ -172,7 +195,10 @@
|
|||||||
#define ISPON() BIT14(regSTH)
|
#define ISPON() BIT14(regSTH)
|
||||||
#define ISSEX() BIT13(regSTH)
|
#define ISSEX() BIT13(regSTH)
|
||||||
|
|
||||||
/* paging bits */
|
/* page table bits */
|
||||||
|
#define PT_WPM 0100000
|
||||||
|
#define PT_RPM 0040000
|
||||||
|
#define PT_FPM 0020000
|
||||||
#define PT_WIP 0010000
|
#define PT_WIP 0010000
|
||||||
#define PT_PGU 0004000
|
#define PT_PGU 0004000
|
||||||
|
|
||||||
@ -198,7 +224,8 @@ extern uint16 PM[];
|
|||||||
extern uint16 R[8];
|
extern uint16 R[8];
|
||||||
extern uint16 regSTH; /* common for all levels */
|
extern uint16 regSTH; /* common for all levels */
|
||||||
extern int ald; /* Automatic load descriptor - set by boot */
|
extern int ald; /* Automatic load descriptor - set by boot */
|
||||||
extern int curlvl;
|
extern int curlvl; /* Current interrupt level */
|
||||||
|
extern int userring; /* Current user ring */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* interrupt link per device.
|
* interrupt link per device.
|
||||||
@ -220,18 +247,31 @@ int iox_floppy(int addr);
|
|||||||
int iox_tty(int addr);
|
int iox_tty(int addr);
|
||||||
int iox_clk(int addr);
|
int iox_clk(int addr);
|
||||||
|
|
||||||
|
/* virtual memory access */
|
||||||
#define M_PHYS 0
|
#define M_PHYS 0
|
||||||
#define M_PT 1
|
#define M_PT 1
|
||||||
#define M_APT 2
|
#define M_APT 2
|
||||||
#define M_FETCH 3
|
#define M_FETCH 3
|
||||||
|
|
||||||
uint16 rdmem(int addr/* , int how*/);
|
/* physical memory access */
|
||||||
uint8 rdbyte(int vaddr, int lr/* , int how*/);
|
#define PM_CPU 10 /* CPU requesting (longjmp allowed) */
|
||||||
void wrmem(int addr, int val/* , int how*/);
|
#define PM_DMA 11 /* device requesting (no longjmp) */
|
||||||
void wrbyte(int vaddr, int val, int lr/* , int how*/);
|
|
||||||
void mm_wrpcr(void);
|
|
||||||
void mm_rdpcr(void);
|
|
||||||
|
|
||||||
|
/* Decide page table for late read */
|
||||||
|
#define SELPT2(IR) ((IR) & 03400 ? M_APT : M_PT)
|
||||||
|
|
||||||
|
int dma_rdmem(int addr);
|
||||||
|
int dma_wrmem(int addr, int val);
|
||||||
|
uint16 prdmem(int addr, int how);
|
||||||
|
void pwrmem(int addr, int val, int how);
|
||||||
|
uint16 rdmem(int addr, int how);
|
||||||
|
uint8 rdbyte(int vaddr, int lr, int how);
|
||||||
|
void wrmem(int addr, int val, int how);
|
||||||
|
void wrbyte(int vaddr, int val, int lr, int how);
|
||||||
|
void mm_wrpcr(void);
|
||||||
|
void mm_privcheck(void);
|
||||||
|
|
||||||
|
void intrpt14(int, int where);
|
||||||
void extint(int lvl, struct intr *intr);
|
void extint(int lvl, struct intr *intr);
|
||||||
|
|
||||||
#define STOP_UNHIOX 1
|
#define STOP_UNHIOX 1
|
||||||
@ -239,6 +279,7 @@ void extint(int lvl, struct intr *intr);
|
|||||||
#define STOP_CKSUM 3
|
#define STOP_CKSUM 3
|
||||||
#define STOP_BP 4
|
#define STOP_BP 4
|
||||||
#define STOP_WAIT 5
|
#define STOP_WAIT 5
|
||||||
|
#define STOP_END 6
|
||||||
|
|
||||||
/* Useful bit extraction macros */
|
/* Useful bit extraction macros */
|
||||||
#define BIT0(x) ((x) & 1)
|
#define BIT0(x) ((x) & 1)
|
||||||
|
|||||||
@ -31,13 +31,21 @@
|
|||||||
#include "nd100_defs.h"
|
#include "nd100_defs.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Floppy and Streamer Controller (3112).
|
* Floppy and Streamer Controller 3112.
|
||||||
* ND documentation ND-11.021.1
|
* ND documentation ND-11.021.1
|
||||||
*
|
*
|
||||||
* Currently only 5 1/4" DS/DD floppies implemented (no streamer).
|
* Also support Floppy Controller 3027 (Z80 version).
|
||||||
|
* ND documentation ND-11.015.1
|
||||||
|
*
|
||||||
|
* Currently only floppies implemented (no streamer).
|
||||||
*
|
*
|
||||||
* The device uses eight IOX addresses, but the transfer commands
|
* The device uses eight IOX addresses, but the transfer commands
|
||||||
* are given in a command block of 12 words in memory.
|
* are given in a command block of 12 words in memory.
|
||||||
|
*
|
||||||
|
* ND uses three floppy formats (but in theory can handle a lot of formats).
|
||||||
|
* - SS/SD 8" (type 0): 77*8*512= 315392 bytes.
|
||||||
|
* - DS/DD 8" (type 017): 77*8*1024*2= 1261568 bytes.
|
||||||
|
* - DS/DD 5 1/4 (type 017?): 80*8*1024*2= 1261568 bytes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat floppy_svc(UNIT *uptr);
|
t_stat floppy_svc(UNIT *uptr);
|
||||||
@ -45,6 +53,9 @@ t_stat floppy_reset (DEVICE *dptr);
|
|||||||
t_stat floppy_boot (int32 unitno, DEVICE *dptr);
|
t_stat floppy_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat floppy_attach (UNIT *uptr, CONST char *cptr);
|
t_stat floppy_attach (UNIT *uptr, CONST char *cptr);
|
||||||
static int floppy_excmd(void);
|
static int floppy_excmd(void);
|
||||||
|
static int floppy_test(UNIT *up);
|
||||||
|
static int dtomem(FILE *fp, int daddr, int maddr, int wcnt, int how);
|
||||||
|
static int getmval(void);
|
||||||
|
|
||||||
#define FL_NTR 80 /* # tracks/side */
|
#define FL_NTR 80 /* # tracks/side */
|
||||||
#define FL_NSC 8 /* # sectors/track */
|
#define FL_NSC 8 /* # sectors/track */
|
||||||
@ -59,7 +70,7 @@ static int floppy_excmd(void);
|
|||||||
#define FL_ST_RDY 0000010 /* device ready for transfer (RFT) */
|
#define FL_ST_RDY 0000010 /* device ready for transfer (RFT) */
|
||||||
#define FL_ST_ERR 0000020 /* OR of errors */
|
#define FL_ST_ERR 0000020 /* OR of errors */
|
||||||
#define FL_ST_HE 0000100 /* Hard error (DMA) */
|
#define FL_ST_HE 0000100 /* Hard error (DMA) */
|
||||||
#define FL_ST_DENS 0100000 /* Dual density ctlr */
|
#define FL_ST_DENS 0140000 /* Dual density ctlr */
|
||||||
|
|
||||||
/* hardware control word */
|
/* hardware control word */
|
||||||
#define FL_CW_IE 0000002 /* interrupt enable (RFT) */
|
#define FL_CW_IE 0000002 /* interrupt enable (RFT) */
|
||||||
@ -128,6 +139,7 @@ static int fl_lpl; /* devno + 7 load pointer low */
|
|||||||
/* Command word (000) */
|
/* Command word (000) */
|
||||||
#define CW_FL_RD 0000000 /* Read data */
|
#define CW_FL_RD 0000000 /* Read data */
|
||||||
#define CW_FL_WR 0000001 /* Write data */
|
#define CW_FL_WR 0000001 /* Write data */
|
||||||
|
#define CW_FL_EXTST 0000036 /* Read extended status */
|
||||||
#define CW_FL_RDFMT 0000042 /* Read format */
|
#define CW_FL_RDFMT 0000042 /* Read format */
|
||||||
#define CW_FL_CMDMSK 077 /* mask for command */
|
#define CW_FL_CMDMSK 077 /* mask for command */
|
||||||
#define CW_FL_SELSH 6 /* shift for unit */
|
#define CW_FL_SELSH 6 /* shift for unit */
|
||||||
@ -147,6 +159,7 @@ static int fl_lpl; /* devno + 7 load pointer low */
|
|||||||
#define U_READ 01 /* unit reading */
|
#define U_READ 01 /* unit reading */
|
||||||
#define U_WRITE 02 /* unit writing */
|
#define U_WRITE 02 /* unit writing */
|
||||||
#define U_RDFMT 03 /* Read format */
|
#define U_RDFMT 03 /* Read format */
|
||||||
|
#define U_EXTST 04 /* Read extended status */
|
||||||
|
|
||||||
#define devaddr u4 /* unit offset (in words) */
|
#define devaddr u4 /* unit offset (in words) */
|
||||||
#define wcnt u5 /* word count */
|
#define wcnt u5 /* word count */
|
||||||
@ -199,21 +212,21 @@ iox_floppy(int addr)
|
|||||||
int n;
|
int n;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
|
|
||||||
switch (addr & 07) {
|
switch (addr & 07) {
|
||||||
case 0: /* read data */
|
case 0: /* read data */
|
||||||
regA = 0;
|
regA = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
regA = fl_rstatus;
|
regA = fl_rstatus;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
n = regA;
|
n = regA;
|
||||||
|
if (n & FL_CW_TEST) {
|
||||||
|
rv = floppy_test(&floppy_unit[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (n & FL_CW_FCE) {
|
if (n & FL_CW_FCE) {
|
||||||
rv = floppy_excmd();
|
rv = floppy_excmd();
|
||||||
break;
|
break;
|
||||||
@ -239,10 +252,10 @@ iox_floppy(int addr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
rv = STOP_UNHIOX;
|
if ((addr & 1) == 0)
|
||||||
break;
|
regA = 0;
|
||||||
|
break; /* Unused IOXes are ignored */
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,32 +266,61 @@ floppy_reset(DEVICE *dptr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Estimate floppy format based on disk size and return status2 word.
|
||||||
|
* - SS/SD = 315392 bytes, c/h/s 77/1/8 (512b sectors)
|
||||||
|
* - DS/DD = 1261568 bytes, c/h/s 77/2/8 (1024b sectors)
|
||||||
|
* - DS/DD 5 1/4" = 1310720 bytes, c/h/s 80/2/8 (1024b sectors)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
readfmt(UNIT *up)
|
||||||
|
{
|
||||||
|
if (sim_fseek(up->fileref, 0, SEEK_END) < 0)
|
||||||
|
return -1;
|
||||||
|
switch (sim_ftell(up->fileref)) {
|
||||||
|
case 315392:
|
||||||
|
return 0;
|
||||||
|
case 1261568:
|
||||||
|
return ST2_FL_DD|ST2_FL_DS|ST2_FL_BS1K;
|
||||||
|
case 1310720:
|
||||||
|
return /* ST2_FL_514| */ST2_FL_DD|ST2_FL_DS|ST2_FL_BS1K;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
t_stat
|
t_stat
|
||||||
floppy_svc(UNIT *uptr)
|
floppy_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
unsigned char *wp;
|
int cbaddr = getmval();
|
||||||
int i, j;
|
|
||||||
int cbaddr = fl_lpl + ((fl_lph & 0377) << 8);
|
|
||||||
int lah = 0, lal = 0;
|
int lah = 0, lal = 0;
|
||||||
|
int status2 = 0;
|
||||||
|
int remwh = 0, remwl = 0;
|
||||||
|
|
||||||
if ((fl_rstatus & FL_ST_ACT) == 0)
|
if ((fl_rstatus & FL_ST_ACT) == 0)
|
||||||
return STOP_UNHIOX;
|
return STOP_UNHIOX;
|
||||||
|
|
||||||
switch (uptr->state) {
|
switch (uptr->state) {
|
||||||
case U_READ:
|
case U_READ:
|
||||||
wp = malloc(uptr->wcnt * 2);
|
dtomem(uptr->fileref, uptr->devaddr,
|
||||||
if (fseek(uptr->fileref, uptr->devaddr * 2, SEEK_SET) < 0)
|
uptr->memaddr, uptr->wcnt, PM_DMA);
|
||||||
goto err;
|
|
||||||
if (sim_fread(wp, uptr->wcnt, 2, uptr->fileref) < 0)
|
|
||||||
goto err;
|
|
||||||
for (i = 0, j = 0; i < uptr->wcnt; i++, j += 2)
|
|
||||||
wrmem(uptr->memaddr+i, (wp[j] << 8) | wp[j+1]);
|
|
||||||
lah = (uptr->memaddr + uptr->wcnt) >> 16;
|
lah = (uptr->memaddr + uptr->wcnt) >> 16;
|
||||||
lal = (uptr->memaddr + uptr->wcnt) & 0177777;
|
lal = (uptr->memaddr + uptr->wcnt) & 0177777;
|
||||||
free(wp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case U_RDFMT:
|
case U_RDFMT:
|
||||||
|
if ((status2 = readfmt(uptr)) < 0)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case U_EXTST: /* XXX no docs found...? */
|
||||||
|
lah = (uptr->memaddr + uptr->wcnt) >> 16;
|
||||||
|
lal = (uptr->memaddr + uptr->wcnt) & 0177777;
|
||||||
|
remwh = 0100000; /* XXX */
|
||||||
|
remwl = 1; /* XXX */
|
||||||
|
pwrmem(uptr->memaddr, 06201, PM_DMA); /* XXX */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case U_WRITE:
|
case U_WRITE:
|
||||||
@ -286,13 +328,12 @@ floppy_svc(UNIT *uptr)
|
|||||||
return STOP_UNHIOX;
|
return STOP_UNHIOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
wrmem(cbaddr+CB_ST1, FL_ST_RDY);
|
pwrmem(cbaddr+CB_ST1, FL_ST_RDY, PM_DMA);
|
||||||
wrmem(cbaddr+CB_ST2,
|
pwrmem(cbaddr+CB_ST2, status2, PM_DMA); /* set after error or rdfmt */
|
||||||
ST2_FL_BS1K|ST2_FL_DS|ST2_FL_DD|ST2_FL_514);
|
pwrmem(cbaddr+CB_LAH, lah, PM_DMA);
|
||||||
wrmem(cbaddr+CB_LAH, lah);
|
pwrmem(cbaddr+CB_LAL, lal, PM_DMA);
|
||||||
wrmem(cbaddr+CB_LAL, lal);
|
pwrmem(cbaddr+CB_REMWH, remwh, PM_DMA);
|
||||||
wrmem(cbaddr+CB_REMWH, 0);
|
pwrmem(cbaddr+CB_REMWL, remwl, PM_DMA);
|
||||||
wrmem(cbaddr+CB_REMWL, 0);
|
|
||||||
|
|
||||||
fl_rstatus &= ~FL_ST_ACT;
|
fl_rstatus &= ~FL_ST_ACT;
|
||||||
fl_rstatus |= FL_ST_RDY;
|
fl_rstatus |= FL_ST_RDY;
|
||||||
@ -305,6 +346,38 @@ err:
|
|||||||
return STOP_UNHIOX;
|
return STOP_UNHIOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get physical memory address for command block.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getmval(void)
|
||||||
|
{
|
||||||
|
return fl_lpl + ((fl_lph & 0377) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a block from file fp, position daddr (bytes) to ND100 memory maddr
|
||||||
|
* wcnt words.
|
||||||
|
* Return 0 or fail.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dtomem(FILE *fp, int daddr, int maddr, int wcnt, int how)
|
||||||
|
{
|
||||||
|
unsigned char *wp;
|
||||||
|
int bcnt = wcnt *2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wp = malloc(wcnt * 2); /* bounce buffer */
|
||||||
|
if (sim_fseek(fp, daddr, SEEK_SET) < 0)
|
||||||
|
return STOP_UNHIOX;
|
||||||
|
if (sim_fread(wp, bcnt, 1, fp) < 0)
|
||||||
|
return STOP_UNHIOX;
|
||||||
|
for (i = 0; i < bcnt; i += 2)
|
||||||
|
wrmem(maddr++, (wp[i] << 8) | wp[i+1], how);
|
||||||
|
free(wp);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat
|
t_stat
|
||||||
floppy_boot(int32 unitno, DEVICE *dptr)
|
floppy_boot(int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
@ -312,14 +385,63 @@ floppy_boot(int32 unitno, DEVICE *dptr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It seems that some of the boot programs uses the Z80 test programs
|
||||||
|
* on the controller card. We try to mimic the behaviour.
|
||||||
|
*
|
||||||
|
* This data structure (in ND100) is used in test T13 and T14.
|
||||||
|
*
|
||||||
|
* 15 8 7 0
|
||||||
|
* +---------------------------------------------+
|
||||||
|
* 0 | ND100 Load address |
|
||||||
|
* +---------------------------------------------+
|
||||||
|
* 1 | Z80 address |
|
||||||
|
* +---------------------------------------------+
|
||||||
|
* 2 | Byte count |
|
||||||
|
* +---------------------------------------------+
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
floppy_test(UNIT *up)
|
||||||
|
{
|
||||||
|
int cbaddr = getmval();
|
||||||
|
int n100addr, z80addr, bcnt;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
if ((regA & FL_CW_FCE) == 0)
|
||||||
|
return STOP_UNHIOX; /* What to do? */
|
||||||
|
switch (regA >> 9) {
|
||||||
|
case 016: /* T14, load from Z80 to ND100 */
|
||||||
|
n100addr = prdmem(cbaddr, PM_CPU);
|
||||||
|
z80addr = prdmem(cbaddr+1, PM_CPU);
|
||||||
|
bcnt = prdmem(cbaddr+2, PM_CPU);
|
||||||
|
if (bcnt > 3584)
|
||||||
|
return STOP_UNHIOX;
|
||||||
|
printf("\r\n addr %06o nd100 %06o z80 %04x count %o\r\n",
|
||||||
|
cbaddr, prdmem(cbaddr, PM_CPU),
|
||||||
|
prdmem(cbaddr+1, PM_CPU), prdmem(cbaddr+2, PM_CPU));
|
||||||
|
dtomem(up->fileref, up->devaddr + z80addr - 0x2200,
|
||||||
|
n100addr, bcnt/2, PM_CPU);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return STOP_UNHIOX;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute. Fills in the unit local vars memaddr/wcnt/devaddr from the
|
||||||
|
* command block and setup for interrupt later.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
floppy_excmd(void)
|
floppy_excmd(void)
|
||||||
{
|
{
|
||||||
UNIT *unit;
|
UNIT *unit;
|
||||||
int cw, u, cmd;
|
int cw, u, cmd, i;
|
||||||
int cbaddr = fl_lpl + ((fl_lph & 0377) << 8);
|
int cbaddr = getmval();
|
||||||
|
int status2, sectsz;
|
||||||
|
|
||||||
cw = rdmem(cbaddr+CB_CW);
|
cw = prdmem(cbaddr+CB_CW, PM_CPU);
|
||||||
u = (cw >> CW_FL_SELSH) & 03;
|
u = (cw >> CW_FL_SELSH) & 03;
|
||||||
cmd = cw & CW_FL_CMDMSK;
|
cmd = cw & CW_FL_CMDMSK;
|
||||||
|
|
||||||
@ -327,26 +449,34 @@ floppy_excmd(void)
|
|||||||
if ((unit->flags & UNIT_ATT) == 0)
|
if ((unit->flags & UNIT_ATT) == 0)
|
||||||
goto err; /* floppy not inserted */
|
goto err; /* floppy not inserted */
|
||||||
|
|
||||||
|
status2 = readfmt(unit);
|
||||||
|
sectsz = (status2 & ST2_FL_BS1K) == 0 ? 512 : 1024;
|
||||||
|
|
||||||
/* XXX check disk size, word count etc... */
|
/* XXX check disk size, word count etc... */
|
||||||
unit->memaddr = ((rdmem(cbaddr+CB_DAHMAH) & 0377) << 16) | rdmem(cbaddr+CB_MAL);
|
unit->memaddr = ((prdmem(cbaddr+CB_DAHMAH, PM_CPU) & 0377) << 16) |
|
||||||
unit->wcnt = ((rdmem(cbaddr+CB_OPTWCH) & 0377) << 16) | rdmem(cbaddr+CB_WCL);
|
prdmem(cbaddr+CB_MAL, PM_CPU);
|
||||||
unit->devaddr = ((rdmem(cbaddr+CB_DAHMAH) & 0177400) << 8) |
|
i = prdmem(cbaddr+CB_OPTWCH, PM_CPU);
|
||||||
rdmem(cbaddr+CB_DAL);
|
unit->wcnt = ((i & 0377) << 16) | prdmem(cbaddr+CB_WCL, PM_CPU);
|
||||||
|
if ((i & CB_OPT_WC) == 0)
|
||||||
if (cmd == CW_FL_RDFMT) {
|
unit->wcnt *= (sectsz/2);
|
||||||
unit->state = U_RDFMT;
|
unit->devaddr = (((prdmem(cbaddr+CB_DAHMAH, PM_CPU) & 0177400) << 8) |
|
||||||
} else if (cmd == CW_FL_RD || cmd == CW_FL_WR) {
|
prdmem(cbaddr+CB_DAL, PM_CPU)) * sectsz;
|
||||||
if (cmd == CW_FL_WR)
|
|
||||||
goto err; /* floppy write protected */
|
|
||||||
|
|
||||||
if ((cw & CW_FL_1K) != CW_FL_1K)
|
|
||||||
goto err; /* Require 1K sectors */
|
|
||||||
if ((cw & (CW_FL_DS|CW_FL_DD)) != (CW_FL_DS|CW_FL_DD))
|
|
||||||
goto err; /* Must be double sided/double density */
|
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case CW_FL_RD:
|
||||||
unit->state = U_READ;
|
unit->state = U_READ;
|
||||||
} else
|
break;
|
||||||
|
case CW_FL_WR:
|
||||||
|
goto err; /* floppy write protected */
|
||||||
|
case CW_FL_EXTST:
|
||||||
|
unit->state = U_EXTST;
|
||||||
|
break;
|
||||||
|
case CW_FL_RDFMT:
|
||||||
|
unit->state = U_RDFMT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
sim_activate(&floppy_unit[u], 10);
|
sim_activate(&floppy_unit[u], 10);
|
||||||
fl_rstatus &= ~FL_ST_RDY;
|
fl_rstatus &= ~FL_ST_RDY;
|
||||||
|
|||||||
294
ND100/nd100_mm.c
294
ND100/nd100_mm.c
@ -23,12 +23,61 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
#include "sim_defs.h"
|
#include "sim_defs.h"
|
||||||
|
|
||||||
#include "nd100_defs.h"
|
#include "nd100_defs.h"
|
||||||
|
/*
|
||||||
|
* Nord-100 Memory Management I
|
||||||
|
*
|
||||||
|
* The paging system on Nord-100 have two modes; normal and extended.
|
||||||
|
* In normal mode it is Nord-10-compatible (with a maximum of 512KW memory)
|
||||||
|
* and in extended it can handle up to 16MW.
|
||||||
|
*
|
||||||
|
* It is quite extensive with both individual page protection (RWX) and
|
||||||
|
* ring protection, where it has four rings. Ring 0 has lowest prio, ring 3
|
||||||
|
* has highest.
|
||||||
|
*
|
||||||
|
* Page size is 1KW, so 64 pages per address space (page table, PT).
|
||||||
|
* A process can use an extra page table as well, called alternate page table.
|
||||||
|
* It is intended to allow large processes to use a separate data space.
|
||||||
|
* There are four page tables, the PCR tells which table(s) to use.
|
||||||
|
*
|
||||||
|
* Which protection ring and which page tables a user belongs to is
|
||||||
|
* configured in the internal Paging Control Register (PCR). There is
|
||||||
|
* one PCR per interrupt level. The PCR looks like this:
|
||||||
|
*
|
||||||
|
* +-------------------+-------+-----+----------+--+-----+
|
||||||
|
* | Unused | PT | APT | Level | 0| Ring|
|
||||||
|
* +-------------------+-------+-----+----------+--+-----+
|
||||||
|
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
*
|
||||||
|
* PT/APT tells which page table should be used. There are four of them.
|
||||||
|
* Level is not stored in the PCR, it is only used to tell which level
|
||||||
|
* a PCR belongs to.
|
||||||
|
* Ring is the user ring. Must always be >= the page ring.
|
||||||
|
*
|
||||||
|
* The page tables are located in "shadow memory". Shadow memory is the
|
||||||
|
* top pages (>= 177400 in normal mode and >= 177000 in extended) only
|
||||||
|
* accessible when running as ring 3.
|
||||||
|
* Page table for normal mode looks as below:
|
||||||
|
*
|
||||||
|
* +---+---+---+---+---+-------+-------------------------+
|
||||||
|
* |WPM|RPM|FPM|WIP|PGU| Ring | Physical Page Number |
|
||||||
|
* +---+---+---+---+---+-------+-------------------------+
|
||||||
|
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
*
|
||||||
|
* WPM/RPM/FPM allows for Write/Read/Fetch.
|
||||||
|
* WIP is set by HW and means "Written in page".
|
||||||
|
* PGU is set by HW and means "Page used".
|
||||||
|
* Ring is the ring the page belongs to. Must be <= User ring.
|
||||||
|
*
|
||||||
|
* Note that the executing program get its ring level from the page where
|
||||||
|
* the instruction were fetched from, so if the User ring is 3 but the
|
||||||
|
* page ring is 2 then the progra cannot access the page tables.
|
||||||
|
*/
|
||||||
|
|
||||||
#define MAXMEMSIZE 512*1024
|
#define MAXMEMSIZE (512*1024)
|
||||||
|
|
||||||
t_stat mm_reset(DEVICE *dptr);
|
t_stat mm_reset(DEVICE *dptr);
|
||||||
|
|
||||||
@ -36,6 +85,11 @@ uint16 PM[MAXMEMSIZE];
|
|||||||
uint16 PCR[16]; /* Paging control register */
|
uint16 PCR[16]; /* Paging control register */
|
||||||
uint16 ptmap[4][64]; /* protection */
|
uint16 ptmap[4][64]; /* protection */
|
||||||
uint16 pmmap[4][64]; /* memory mapping */
|
uint16 pmmap[4][64]; /* memory mapping */
|
||||||
|
uint16 pea, pes, pgs;
|
||||||
|
int pea_locked, pgs_locked; /* flag to lock register after error */
|
||||||
|
int userring; /* current user ring */
|
||||||
|
|
||||||
|
extern jmp_buf env;
|
||||||
|
|
||||||
#define ISDIS() (mm_dev.flags & DEV_DIS)
|
#define ISDIS() (mm_dev.flags & DEV_DIS)
|
||||||
|
|
||||||
@ -43,6 +97,9 @@ UNIT mm_unit = { UDATA(NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 0) };
|
|||||||
|
|
||||||
REG mm_reg[] = {
|
REG mm_reg[] = {
|
||||||
{ BRDATA(PCR, PCR, 8, 16, 16) },
|
{ BRDATA(PCR, PCR, 8, 16, 16) },
|
||||||
|
{ ORDATA(PEA, pea, 16) },
|
||||||
|
{ ORDATA(PES, pes, 16) },
|
||||||
|
{ ORDATA(PGS, pgs, 16) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,16 +109,50 @@ DEVICE mm_dev = {
|
|||||||
1, 8, 16, 1, 8, 16,
|
1, 8, 16, 1, 8, 16,
|
||||||
0, 0, &mm_reset,
|
0, 0, &mm_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, DEV_DISABLE+DEV_DIS
|
NULL, DEV_DISABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal registers located on the MM module.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mm_tra(int reg)
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case IRR_PES:
|
||||||
|
regA = pes;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRR_PGS:
|
||||||
|
regA = pgs;
|
||||||
|
pgs_locked = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRR_PGC:
|
||||||
|
regA = PCR[(regA >> 3) & 017];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRR_PEA:
|
||||||
|
regA = pea;
|
||||||
|
pea_locked = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rv = STOP_UNHINS;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a byte. 0 in lr is left byte, 1 is right byte.
|
* Read a byte. 0 in lr is left byte, 1 is right byte.
|
||||||
*/
|
*/
|
||||||
uint8
|
uint8
|
||||||
rdbyte(int vaddr, int lr/* , int how*/)
|
rdbyte(int vaddr, int lr, int how)
|
||||||
{
|
{
|
||||||
uint16 val = rdmem(vaddr);
|
uint16 val = rdmem(vaddr, how);
|
||||||
|
|
||||||
return lr ? val & 0377 : val >> 8;
|
return lr ? val & 0377 : val >> 8;
|
||||||
}
|
}
|
||||||
@ -70,13 +161,13 @@ rdbyte(int vaddr, int lr/* , int how*/)
|
|||||||
* Write a byte. 0 in lr is left byte, 1 is right byte.
|
* Write a byte. 0 in lr is left byte, 1 is right byte.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
wrbyte(int vaddr, int val, int lr/* , int how*/)
|
wrbyte(int vaddr, int val, int lr, int how)
|
||||||
{
|
{
|
||||||
uint16 ov = rdmem(vaddr);
|
uint16 ov = rdmem(vaddr, how);
|
||||||
|
|
||||||
val &= 0377; /* sanity */
|
val &= 0377; /* sanity */
|
||||||
ov = lr ? (ov & 0177400) | val : (ov & 0377) | (val << 8);
|
ov = lr ? (ov & 0177400) | val : (ov & 0377) | (val << 8);
|
||||||
wrmem(vaddr, ov);
|
wrmem(vaddr, ov, how);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -90,6 +181,8 @@ is_shadow(int vaddr)
|
|||||||
{
|
{
|
||||||
if ((PCR[curlvl] & 03) < 3 && ISPON())
|
if ((PCR[curlvl] & 03) < 3 && ISPON())
|
||||||
return 0; /* not valid */
|
return 0; /* not valid */
|
||||||
|
if (vaddr > 0177777)
|
||||||
|
return 0;
|
||||||
if (ISSEX())
|
if (ISSEX())
|
||||||
return 1;
|
return 1;
|
||||||
return (vaddr >= 0177400);
|
return (vaddr >= 0177400);
|
||||||
@ -139,57 +232,188 @@ shadowwr(int v, int dat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
uint16
|
* MOR - memory out of range. Addressing non-existent memory.
|
||||||
rdmem(int vaddr/* , int how*/)
|
*/
|
||||||
|
void
|
||||||
|
morerr(int addr, int why, int pesval)
|
||||||
{
|
{
|
||||||
int pt;
|
if (pea_locked == 0) {
|
||||||
|
pea = (uint16)addr;
|
||||||
vaddr &= 0177777;
|
pes = (uint16)(addr >> 16) | pesval;
|
||||||
|
pea_locked = 1;
|
||||||
if ((vaddr >= 0177000) && is_shadow(vaddr))
|
}
|
||||||
return shadowrd(vaddr);
|
intrpt14(IIE_MOR, why);
|
||||||
/* Mark page as read */
|
|
||||||
if (ISPON()) {
|
|
||||||
pt = (PCR[curlvl] >> 8) & 03;
|
|
||||||
ptmap[pt][vaddr >> 10] |= PT_PGU;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (ISPON() == 0)
|
/*
|
||||||
return PM[vaddr];
|
* Physical memory read when doing DMA.
|
||||||
|
* The only error that can occur is non-existent memory (MOR).
|
||||||
|
* returns -1 if MOR, value otherwise.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dma_rdmem(int addr)
|
||||||
|
{
|
||||||
|
addr &= 0xffffff;
|
||||||
|
if (addr < MAXMEMSIZE)
|
||||||
|
return PM[addr];
|
||||||
|
morerr(addr, PM_DMA, PES_DMA);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dma_wrmem(int addr, int val)
|
||||||
|
{
|
||||||
|
addr &= 0xffffff;
|
||||||
|
if (addr < MAXMEMSIZE) {
|
||||||
|
PM[addr] = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
morerr(addr, PM_DMA, PES_DMA);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read direct from physical (24-bit-addr) memory.
|
||||||
|
*/
|
||||||
|
uint16
|
||||||
|
prdmem(int vaddr, int how)
|
||||||
|
{
|
||||||
|
if ((vaddr & 0xffffff) < MAXMEMSIZE)
|
||||||
|
return PM[vaddr];
|
||||||
|
morerr(vaddr, PM_CPU, how == M_FETCH ? PES_FETCH : 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pgsupd(int pgnr, int pnr, int flg)
|
||||||
|
{
|
||||||
|
if (pgs_locked)
|
||||||
|
return;
|
||||||
|
pgs = (pgnr << 6) | pnr | flg;
|
||||||
|
pgs_locked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16
|
||||||
|
rdmem(int vaddr, int how)
|
||||||
|
{
|
||||||
|
uint16 *ptmapp;
|
||||||
|
int sh, pagetablenr, pagering, pagenr, permit, p;
|
||||||
|
|
||||||
|
vaddr &= 0177777; /* Sanity */
|
||||||
|
|
||||||
|
/* Shadow memory? */
|
||||||
|
if ((vaddr >= 0177000) && is_shadow(vaddr))
|
||||||
|
return shadowrd(vaddr);
|
||||||
|
/* Physical memory? */
|
||||||
|
if (ISPON() == 0)
|
||||||
|
return prdmem(vaddr, 0);
|
||||||
|
|
||||||
|
/* Paging on. */
|
||||||
|
permit = (how == M_FETCH ? PT_FPM : PT_RPM);
|
||||||
|
userring = PCR[curlvl] & 03;
|
||||||
|
sh = how == M_APT ? 7 : 9;
|
||||||
|
pagetablenr = (PCR[curlvl] >> sh) & 03;
|
||||||
|
pagenr = vaddr >> 10;
|
||||||
|
ptmapp = &ptmap[pagetablenr][pagenr];
|
||||||
|
pagering = (*ptmapp >> 9) & 03;
|
||||||
|
p = (permit == PT_FPM ? PGS_FF : 0);
|
||||||
|
if ((*ptmapp & (PT_WPM|PT_RPM|PT_FPM)) == 0) {
|
||||||
|
/* page fault */
|
||||||
|
pgsupd(pagetablenr, pagenr, p | PGS_PM);
|
||||||
|
intrpt14(IIE_PF, PM_CPU);
|
||||||
|
} else if ((*ptmapp & permit) == 0) {
|
||||||
|
pgsupd(pagetablenr, pagenr, p | PGS_PM);
|
||||||
|
intrpt14(IIE_PV, PM_CPU);
|
||||||
|
} else if (pagering > userring) {
|
||||||
|
pgsupd(pagetablenr, pagenr, p);
|
||||||
|
intrpt14(IIE_PV, PM_CPU);
|
||||||
|
} else {
|
||||||
|
/* Mark page as read */
|
||||||
|
*ptmapp |= PT_PGU;
|
||||||
|
vaddr = (pmmap[pagetablenr][pagenr] << 10) | (vaddr & 01777);
|
||||||
|
return prdmem(vaddr, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write direct to physical (24-bit-addr) memory.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pwrmem(int vaddr, int val, int how)
|
||||||
|
{
|
||||||
|
if ((vaddr & 0xffffff) < MAXMEMSIZE)
|
||||||
|
PM[vaddr] = val;
|
||||||
|
else
|
||||||
|
morerr(vaddr, PM_CPU, how == M_FETCH ? PES_FETCH : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wrmem(int vaddr, int val/* , int how*/)
|
wrmem(int vaddr, int val, int how)
|
||||||
{
|
{
|
||||||
|
uint16 *ptmapp;
|
||||||
|
int sh, pagetablenr, pagering, permit, pagenr;
|
||||||
|
|
||||||
vaddr &= 0177777;
|
vaddr &= 0177777;
|
||||||
if ((vaddr >= 0177000) && is_shadow(vaddr)) {
|
if ((vaddr >= 0177000) && is_shadow(vaddr)) {
|
||||||
shadowwr(vaddr, val);
|
shadowwr(vaddr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PM[vaddr] = val;
|
if (ISPON() == 0) {
|
||||||
|
pwrmem(vaddr, val, PM_CPU);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Paging on. */
|
||||||
|
permit = PT_WPM;
|
||||||
|
userring = PCR[curlvl] & 03;
|
||||||
|
sh = how == M_APT ? 7 : 9;
|
||||||
|
pagetablenr = (PCR[curlvl] >> sh) & 03;
|
||||||
|
pagenr = vaddr >> 10;
|
||||||
|
ptmapp = &ptmap[pagetablenr][pagenr];
|
||||||
|
pagering = (*ptmapp >> 9) & 03;
|
||||||
|
if ((*ptmapp & (PT_WPM|PT_RPM|PT_FPM)) == 0) {
|
||||||
|
/* page fault */
|
||||||
|
pgsupd(pagetablenr, pagenr, PGS_PM);
|
||||||
|
intrpt14(IIE_PF, PM_CPU);
|
||||||
|
} else if ((*ptmapp & permit) == 0) {
|
||||||
|
pgsupd(pagetablenr, pagenr, PGS_PM);
|
||||||
|
intrpt14(IIE_PV, PM_CPU);
|
||||||
|
} else if (pagering > userring) {
|
||||||
|
pgsupd(pagetablenr, pagenr, 0);
|
||||||
|
intrpt14(IIE_PV, PM_CPU);
|
||||||
|
} else {
|
||||||
|
/* Mark page as written */
|
||||||
|
*ptmapp |= (PT_PGU|PT_WIP);
|
||||||
|
vaddr = (pmmap[pagetablenr][pagenr] << 10) | (vaddr & 01777);
|
||||||
|
pwrmem(vaddr, val, PM_CPU);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mm_wrpcr(void)
|
mm_wrpcr()
|
||||||
{
|
{
|
||||||
if (ISDIS())
|
if (ISDIS())
|
||||||
return;
|
return;
|
||||||
PCR[(regA >> 3) & 017] = regA & 03603;
|
PCR[(regA >> 3) & 017] = regA & 03603;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
mm_rdpcr(void)
|
|
||||||
{
|
|
||||||
if (ISDIS())
|
|
||||||
return;
|
|
||||||
regA = PCR[(regA >> 3) & 017];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
t_stat
|
t_stat
|
||||||
mm_reset(DEVICE *dptr)
|
mm_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if instruction is privileged enough to execute,
|
||||||
|
* otherwise give priv instruction fault.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mm_privcheck(void)
|
||||||
|
{
|
||||||
|
if (ISPON() == 0)
|
||||||
|
return;
|
||||||
|
if (userring > 1)
|
||||||
|
return;
|
||||||
|
intrpt14(IIE_PI, PM_CPU);
|
||||||
|
}
|
||||||
|
|||||||
@ -54,6 +54,8 @@ t_stat tty_setpar(UNIT *uptr);
|
|||||||
#define TT_OCTRL_ACT 0000004 /* set device active */
|
#define TT_OCTRL_ACT 0000004 /* set device active */
|
||||||
|
|
||||||
#define TT_OSTAT_IRDY 0000001 /* device ready gives interrupt */
|
#define TT_OSTAT_IRDY 0000001 /* device ready gives interrupt */
|
||||||
|
#define TT_OSTAT_EINT 0000002 /* error interrupt enabled */
|
||||||
|
#define TT_OSTAT_ACT 0000004 /* device active */
|
||||||
#define TT_OSTAT_RDY 0000010 /* device ready for transfer */
|
#define TT_OSTAT_RDY 0000010 /* device ready for transfer */
|
||||||
|
|
||||||
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
|
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
|
||||||
@ -147,6 +149,7 @@ tto_svc(UNIT *uptr)
|
|||||||
sim_activate (uptr, uptr->wait); /* try again */
|
sim_activate (uptr, uptr->wait); /* try again */
|
||||||
return ((r == SCPE_STALL)? SCPE_OK : r);/* !stall? report */
|
return ((r == SCPE_STALL)? SCPE_OK : r);/* !stall? report */
|
||||||
}
|
}
|
||||||
|
tto_status &= ~TT_OSTAT_ACT;
|
||||||
tto_status |= TT_OSTAT_RDY;
|
tto_status |= TT_OSTAT_RDY;
|
||||||
if (tto_ctrl & TT_OCTRL_EIRDY)
|
if (tto_ctrl & TT_OCTRL_EIRDY)
|
||||||
extint(10, &tto_int);
|
extint(10, &tto_int);
|
||||||
@ -193,6 +196,7 @@ iox_tty(int addr)
|
|||||||
case 5: /* Write data */
|
case 5: /* Write data */
|
||||||
tto_unit.buf = regA & 0177;
|
tto_unit.buf = regA & 0177;
|
||||||
tto_status &= ~TT_OSTAT_RDY;
|
tto_status &= ~TT_OSTAT_RDY;
|
||||||
|
tto_status |= TT_OSTAT_ACT;
|
||||||
sim_activate (&tto_unit, tto_unit.wait);
|
sim_activate (&tto_unit, tto_unit.wait);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -201,15 +205,8 @@ iox_tty(int addr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* Write output control reg */
|
case 7: /* Write output control reg */
|
||||||
tto_ctrl = regA;
|
/* Only interrupts are controlled */
|
||||||
if (tto_ctrl & TT_OCTRL_ACT)
|
tto_status = (tto_status & ~03) | (regA & 03);
|
||||||
tto_status |= TT_OSTAT_RDY;
|
|
||||||
else
|
|
||||||
tto_status &= ~TT_OSTAT_RDY;
|
|
||||||
if (tto_ctrl & TT_OCTRL_EIRDY)
|
|
||||||
tto_status |= TT_OSTAT_IRDY;
|
|
||||||
else
|
|
||||||
tto_status &= ~TT_OSTAT_IRDY;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
char sim_name[] = "ND100";
|
char sim_name[] = "ND100";
|
||||||
|
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
REG *sim_PC = &cpu_reg[2];
|
REG *sim_PC = &cpu_reg[8];
|
||||||
int32 sim_emax = 1;
|
int32 sim_emax = 1;
|
||||||
|
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
@ -50,6 +50,7 @@ const char *sim_stop_messages[SCPE_BASE] = {
|
|||||||
"Checksum error",
|
"Checksum error",
|
||||||
"Simulator breakpoint",
|
"Simulator breakpoint",
|
||||||
"Wait at level 0",
|
"Wait at level 0",
|
||||||
|
"manual end",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mlp;
|
static int mlp;
|
||||||
@ -60,7 +61,7 @@ gb(FILE *f)
|
|||||||
int w;
|
int w;
|
||||||
|
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return rdmem(mlp++);
|
return prdmem(mlp++, PM_CPU);
|
||||||
w = getc(f) & 0377;
|
w = getc(f) & 0377;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
@ -106,7 +107,7 @@ sim_load(FILE *f, CONST char *buf, CONST char *fnam, t_bool flag)
|
|||||||
/* images have MSB first */
|
/* images have MSB first */
|
||||||
s = (getc(f) & 0377) << 8;
|
s = (getc(f) & 0377) << 8;
|
||||||
s |= getc(f) & 0377;
|
s |= getc(f) & 0377;
|
||||||
wrmem(i, s);
|
pwrmem(i, s, PM_CPU);
|
||||||
}
|
}
|
||||||
f = NULL;
|
f = NULL;
|
||||||
}
|
}
|
||||||
@ -133,8 +134,8 @@ sim_load(FILE *f, CONST char *buf, CONST char *fnam, t_bool flag)
|
|||||||
printf("Load address %06o\n", E = gw(f));
|
printf("Load address %06o\n", E = gw(f));
|
||||||
printf("Word count %06o\n", F = gw(f));
|
printf("Word count %06o\n", F = gw(f));
|
||||||
for (i = s = 0; i < F; i++) {
|
for (i = s = 0; i < F; i++) {
|
||||||
wrmem(E+i, gw(f));
|
pwrmem(E+i, gw(f), PM_CPU);
|
||||||
s += rdmem(E+i);
|
s += prdmem(E+i, PM_CPU);
|
||||||
}
|
}
|
||||||
printf("Checksum %06o\n", H = gw(f));
|
printf("Checksum %06o\n", H = gw(f));
|
||||||
if (H != s)
|
if (H != s)
|
||||||
@ -180,6 +181,10 @@ static char *trrtab[] = {
|
|||||||
"cclr", "lcil", "ucil", "err13", "err14", "eccr", "err16", "err17"
|
"cclr", "lcil", "ucil", "err13", "err14", "eccr", "err16", "err17"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *mitab[] = {
|
||||||
|
"ldatx", "ldxtx", "lddtx", "ldbtx", "statx", "stztx", "stdtx", "ERR"
|
||||||
|
};
|
||||||
|
|
||||||
t_stat
|
t_stat
|
||||||
fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||||||
{
|
{
|
||||||
@ -330,6 +335,8 @@ fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
|||||||
fprintf(of, "sbyt");
|
fprintf(of, "sbyt");
|
||||||
else if ((op & 0177707) == ND_SKP_EXR)
|
else if ((op & 0177707) == ND_SKP_EXR)
|
||||||
fprintf(of, "exr %s", dactab[(op & 070) >> 3]);
|
fprintf(of, "exr %s", dactab[(op & 070) >> 3]);
|
||||||
|
else if ((op & 0177700) == ND_SKP_LDATX)
|
||||||
|
fprintf(of, "%s", mitab[op & 07]);
|
||||||
else if ((op & 0177700) == ND_SKP_RMPY)
|
else if ((op & 0177700) == ND_SKP_RMPY)
|
||||||
fprintf(of, "rmpy %s %s",
|
fprintf(of, "rmpy %s %s",
|
||||||
dactab[(op & 070) >> 3], dactab[op & 07]);
|
dactab[(op & 070) >> 3], dactab[op & 07]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user