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"
|
||||
|
||||
#define MAXMEMSIZE 512*1024
|
||||
#undef TIMERHACK
|
||||
|
||||
#ifdef TIMERHACK
|
||||
int rtc_int_enabled, rtc_dev_ready, rtccnt;
|
||||
void chkrtc(void);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int ir;
|
||||
@ -59,11 +53,11 @@ static Hist_entry *hist = NULL;
|
||||
static struct intr *ilnk[4]; /* level 10-13 */
|
||||
jmp_buf env;
|
||||
|
||||
uint16 R[8], RBLK[16][8], regSTH;
|
||||
uint16 R[8], RBLK[16][8], regSTH, oregP;
|
||||
int curlvl; /* current interrupt level */
|
||||
int iic, iie, iid; /* IIC/IIE/IID register */
|
||||
int pid, pie; /* PID/PIE register */
|
||||
int ald, eccr, pvl, lmp;
|
||||
int ald, eccr, pvl, lmp, opr;
|
||||
|
||||
#define SETC() (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_mst(int reg);
|
||||
static int highest_level(void);
|
||||
static void intrpt14(int);
|
||||
static void identrm(int);
|
||||
static uint16 add3(uint16 a, uint16 d, uint16 c);
|
||||
int fls(int);
|
||||
|
||||
|
||||
int ins_store(int ir, int addr);
|
||||
int ins_stdf(int ir, int addr);
|
||||
int ins_lddf(int ir, int addr);
|
||||
@ -144,6 +136,7 @@ REG cpu_reg[] = {
|
||||
{ ORDATA(A, regA, 16) },
|
||||
{ ORDATA(T, regT, 16) },
|
||||
{ ORDATA(X, regX, 16) },
|
||||
{ ORDATA(oldP, oregP, 16) },
|
||||
{ DRDATA(LVL, curlvl, 4) },
|
||||
{ DRDATA(LMP, lmp, 16) },
|
||||
{ DRDATA(PVL, pvl, 4) },
|
||||
@ -151,6 +144,7 @@ REG cpu_reg[] = {
|
||||
{ ORDATA(PIE, pie, 16) },
|
||||
{ ORDATA(IIC, iic, 4) },
|
||||
{ ORDATA(IIE, iie, 10) },
|
||||
{ ORDATA(OPR, opr, 16) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -176,16 +170,16 @@ sim_instr(void)
|
||||
int first = 1;
|
||||
uint16 off;
|
||||
|
||||
reason = setjmp(env);
|
||||
(void)setjmp(env);
|
||||
reason = 0;
|
||||
|
||||
while (reason == 0) {
|
||||
if (sim_interval <= 0)
|
||||
if ((reason = sim_process_event ()))
|
||||
break;
|
||||
|
||||
#ifdef TIMERHACK
|
||||
chkrtc();
|
||||
#endif
|
||||
if (regSTL & STS_Z)
|
||||
intrpt14(IIE_V, PM_DMA); /* no longjmp here */
|
||||
if ((pid & pie) > (0177777 >> (15-curlvl)) && ISION()) {
|
||||
/* need to interrupt */
|
||||
pvl = curlvl;
|
||||
@ -199,10 +193,21 @@ while (reason == 0) {
|
||||
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--;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -229,8 +234,6 @@ while (reason == 0) {
|
||||
off = getoff(IR);
|
||||
|
||||
reason = (*ins_table[ID(IR)])(IR, off);
|
||||
if (reason == 0)
|
||||
regP++;
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
@ -248,7 +251,7 @@ cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
||||
{
|
||||
if (addr >= MAXMEMSIZE)
|
||||
return SCPE_ARG;
|
||||
*vptr = rdmem(addr);
|
||||
*vptr = rdmem(addr, M_PT); /* XXX */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -279,7 +282,7 @@ int
|
||||
ins_store(int IR, int off)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -289,10 +292,12 @@ ins_store(int IR, int off)
|
||||
int
|
||||
ins_stdf(int IR, int off)
|
||||
{
|
||||
int pt = SELPT2(IR);
|
||||
|
||||
if (ID(IR) == ID(ND_STF) /* && 48-bit */)
|
||||
wrmem(off++, regT);
|
||||
wrmem(off++, regA);
|
||||
wrmem(off, regD);
|
||||
wrmem(off++, regT, pt);
|
||||
wrmem(off++, regA, pt);
|
||||
wrmem(off, regD, pt);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -302,10 +307,11 @@ ins_stdf(int IR, int off)
|
||||
int
|
||||
ins_lddf(int IR, int off)
|
||||
{
|
||||
int pt = SELPT2(IR);
|
||||
if (ID(IR) == ID(ND_LDF) /* && 48-bit */)
|
||||
regT = rdmem(off++);
|
||||
regA = rdmem(off++);
|
||||
regD = rdmem(off);
|
||||
regT = rdmem(off++, pt);
|
||||
regA = rdmem(off++, pt);
|
||||
regD = rdmem(off, pt);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -315,7 +321,7 @@ ins_lddf(int IR, int off)
|
||||
int
|
||||
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;
|
||||
}
|
||||
|
||||
@ -326,8 +332,9 @@ int
|
||||
ins_min(int IR, int off)
|
||||
{
|
||||
uint16 s;
|
||||
int pt = SELPT2(IR);
|
||||
|
||||
wrmem(off, s = rdmem(off) + 1);
|
||||
wrmem(off, s = rdmem(off, pt) + 1, pt);
|
||||
if (s == 0)
|
||||
regP++;
|
||||
return SCPE_OK;
|
||||
@ -339,7 +346,7 @@ ins_min(int IR, int off)
|
||||
int
|
||||
ins_add(int IR, int off)
|
||||
{
|
||||
uint16 d = rdmem(off);
|
||||
uint16 d = rdmem(off, SELPT2(IR));
|
||||
int n = 0;
|
||||
|
||||
if (ID(IR) == ID(ND_SUB))
|
||||
@ -354,7 +361,7 @@ ins_add(int IR, int off)
|
||||
int
|
||||
ins_andor(int IR, int off)
|
||||
{
|
||||
uint16 s = rdmem(off);
|
||||
uint16 s = rdmem(off, SELPT2(IR));
|
||||
|
||||
regA = BIT11(IR) ? (regA | s) : (regA & s);
|
||||
return SCPE_OK;
|
||||
@ -394,7 +401,7 @@ static void
|
||||
ins_bfill(int IR)
|
||||
{
|
||||
while (regT & 07777) {
|
||||
wrbyte(regX, regA, BIT15(regT));
|
||||
wrbyte(regX, regA, BIT15(regT), M_APT);
|
||||
regT--;
|
||||
regT ^= 0100000;
|
||||
if (BIT15(regT) == 0)
|
||||
@ -442,8 +449,8 @@ ins_movb(int IR)
|
||||
|
||||
if (regX > regA) { /* copy bottom-top */
|
||||
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
||||
int8 w = rdbyte(regA, BIT15(regD));
|
||||
wrbyte(regX, w, BIT15(regT));
|
||||
int8 w = rdbyte(regA, BIT15(regD), M_APT);
|
||||
wrbyte(regX, w, BIT15(regT), M_APT);
|
||||
regD ^= 0100000;
|
||||
if (BIT15(regD) == 0) regA++;
|
||||
regT ^= 0100000;
|
||||
@ -494,8 +501,8 @@ ins_movbf(int IR)
|
||||
}
|
||||
|
||||
for (i = BYTELN(regD); i < BYTELN(regT); i++, regD++) {
|
||||
int8 w = rdbyte(regA, BIT15(regD));
|
||||
wrbyte(regX, w, BIT15(regT));
|
||||
int8 w = rdbyte(regA, BIT15(regD), M_APT);
|
||||
wrbyte(regX, w, BIT15(regT), M_APT);
|
||||
regD ^= 0100000;
|
||||
if (BIT15(regD) == 0) regA++;
|
||||
regT ^= 0100000;
|
||||
@ -515,11 +522,41 @@ ins_skip_ext(int IR)
|
||||
uint16 d;
|
||||
int16 ss, sd;
|
||||
int32 shc;
|
||||
int reason = 0;
|
||||
int paddr, reason = 0;
|
||||
|
||||
if ((IR & 0177707) == ND_SKP_CLEPT) {
|
||||
intrpt14(IIE_II);
|
||||
regP--;
|
||||
intrpt14(IIE_II, PM_CPU);
|
||||
} 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) {
|
||||
/* X = (A-1)*3 */
|
||||
regX = (regA-1)*3;
|
||||
@ -531,14 +568,22 @@ ins_skip_ext(int IR)
|
||||
identrm(12);
|
||||
} else if (IR == ND_SKP_IDENT13) {
|
||||
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);
|
||||
else if (IR == ND_SKP_MOVB)
|
||||
} else if (IR == ND_SKP_MOVB) {
|
||||
ins_movb(IR);
|
||||
else if (IR == ND_SKP_MOVBF)
|
||||
} else if (IR == ND_SKP_MOVBF) {
|
||||
ins_movbf(IR);
|
||||
else if (IR == ND_SKP_LBYT) {
|
||||
d = rdmem(regT + (regX >> 1));
|
||||
} else if (IR == ND_SKP_LWCS) {
|
||||
;
|
||||
} 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)
|
||||
regA = d & 0377;
|
||||
else
|
||||
@ -546,9 +591,9 @@ ins_skip_ext(int IR)
|
||||
} else if (IR == ND_SKP_SBYT) {
|
||||
d = regT + (regX >> 1);
|
||||
if (regX & 1)
|
||||
wrmem(d, (rdmem(d) & 0xff00) | (regA & 0xff));
|
||||
wrmem(d, (rdmem(d, M_APT) & 0xff00) | (regA & 0xff), M_APT);
|
||||
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) {
|
||||
ss = R[(IR & 070) >> 3];
|
||||
sd = R[IR & 07];
|
||||
@ -560,10 +605,9 @@ ins_skip_ext(int IR)
|
||||
shc = (regA << 16) | regD;
|
||||
regA = shc / ss;
|
||||
regD = shc % ss;
|
||||
} else if (IR == 0142700) {
|
||||
} else if (IR == 0142700 || IR == 0143700) {
|
||||
/* ??? what is this? */
|
||||
intrpt14(IIE_II);
|
||||
regP--;
|
||||
intrpt14(IIE_II, PM_CPU);
|
||||
} else
|
||||
reason = STOP_UNHINS;
|
||||
return reason;
|
||||
@ -590,11 +634,10 @@ ins_srb(int IR)
|
||||
/* Save current level (maybe used) to reg block */
|
||||
for (i = 0; i < 8; i++)
|
||||
RBLK[curlvl][i] = R[i];
|
||||
RBLK[curlvl][rnP]++; /* following insn */
|
||||
|
||||
/* store requested block to memory */
|
||||
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 */
|
||||
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;
|
||||
|
||||
if (n == curlvl)
|
||||
@ -623,6 +666,56 @@ ins_lrb(int IR)
|
||||
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.
|
||||
*/
|
||||
@ -632,29 +725,9 @@ ins_mis(int IR, int off)
|
||||
int reason = 0;
|
||||
int n, i;
|
||||
|
||||
if (IR == ND_MIS_SEX)
|
||||
regSTH |= STS_SEXI;
|
||||
else if (IR == ND_MIS_DEPO) {
|
||||
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)
|
||||
if ((IR & 0177760) == ND_MIS_OPCOM)
|
||||
reason = nd_mis_opc(IR);
|
||||
else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRA)
|
||||
reason = nd_tra(IR & ~ND_MIS_TRMSK);
|
||||
else if ((IR & ND_MIS_TRMSK) == ND_MIS_TRR)
|
||||
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)
|
||||
reason = nd_mcl(IR & ~ND_MIS_TRMSK);
|
||||
else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRR) {
|
||||
mm_privcheck();
|
||||
n = (IR >> 3) & 017;
|
||||
if (n == curlvl)
|
||||
regA = R[IR & 07];
|
||||
else
|
||||
regA = RBLK[n][IR & 07];
|
||||
} else if ((IR & ND_MIS_IRRMSK) == ND_MIS_IRW) {
|
||||
mm_privcheck();
|
||||
n = (IR >> 3) & 017;
|
||||
RBLK[n][IR & 07] = regA;
|
||||
if (n == curlvl && (IR & 07) != rnP)
|
||||
@ -679,21 +754,18 @@ ins_mis(int IR, int off)
|
||||
ins_lrb(IR);
|
||||
} else if ((IR & ND_MONMSK) == ND_MON) {
|
||||
RBLK[14][rnT] = SEXT8(IR);
|
||||
intrpt14(IIE_MC);
|
||||
intrpt14(IIE_MC, PM_CPU);
|
||||
} else if ((IR & ND_MONMSK) == ND_WAIT) {
|
||||
if (ISION() == 0) {
|
||||
regP++;
|
||||
reason = STOP_WAIT;
|
||||
} else if (curlvl > 0) {
|
||||
pid &= ~(1 << curlvl);
|
||||
n = highest_level();
|
||||
if (curlvl != n) {
|
||||
regP++;
|
||||
for (i = 0; i < 8; i++) {
|
||||
RBLK[curlvl][i] = R[i];
|
||||
R[i] = RBLK[n][i];
|
||||
}
|
||||
regP--;
|
||||
}
|
||||
curlvl = n;
|
||||
}
|
||||
@ -794,6 +866,7 @@ ins_bop(int IR, int addr)
|
||||
|
||||
int rd, n, reason = 0;
|
||||
|
||||
regSTL = (regSTL & 0377) | regSTH; /* Hack for bskp */
|
||||
rd = IR & 7;
|
||||
n = (IR >> 3) & 017;
|
||||
switch ((IR >> 7) & 017) {
|
||||
@ -826,7 +899,6 @@ ins_bop(int IR, int addr)
|
||||
regP++;
|
||||
break;
|
||||
|
||||
|
||||
case 010: /* BSTA store ~K and set K */
|
||||
R[rd] &= ~(1 << n);
|
||||
if ((regSTL & STS_K) == 0)
|
||||
@ -885,6 +957,7 @@ ins_bop(int IR, int addr)
|
||||
reason = STOP_UNHINS;
|
||||
break;
|
||||
}
|
||||
regSTL &= 0377;
|
||||
return reason;
|
||||
}
|
||||
|
||||
@ -1000,11 +1073,11 @@ int
|
||||
ins_fmu(int IR, int addr)
|
||||
{
|
||||
struct fp f1, f2;
|
||||
int s3, e3;
|
||||
int s3, e3, pt = SELPT2(IR);
|
||||
t_uint64 m3;
|
||||
|
||||
/* 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 */
|
||||
mkfp48(&f2, regT, regA, regD);
|
||||
@ -1044,11 +1117,12 @@ int
|
||||
ins_fdv(int IR, int addr)
|
||||
{
|
||||
struct fp f1, f2;
|
||||
int s3, e3;
|
||||
int s3, e3, pt;
|
||||
t_uint64 m3;
|
||||
|
||||
/* 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 */
|
||||
mkfp48(&f2, regT, regA, regD);
|
||||
@ -1059,7 +1133,7 @@ ins_fdv(int IR, int addr)
|
||||
regSTL |= STS_Z;
|
||||
regT |= 077777;
|
||||
regA = regD = 0177777;
|
||||
intrpt14(IIE_V);
|
||||
intrpt14(IIE_V, PM_CPU);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -1177,8 +1251,9 @@ int
|
||||
ins_fad(int IR, int addr)
|
||||
{
|
||||
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);
|
||||
|
||||
if (f1.s ^ f2.s)
|
||||
@ -1192,8 +1267,9 @@ int
|
||||
ins_fsb(int IR, int addr)
|
||||
{
|
||||
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);
|
||||
|
||||
f1.s ^= 1; /* swap sign of right op */
|
||||
@ -1233,7 +1309,7 @@ add3(uint16 a, uint16 d, uint16 c)
|
||||
int
|
||||
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;
|
||||
regSTL &= ~STS_Q;
|
||||
if (res > 32767)
|
||||
@ -1248,12 +1324,13 @@ int
|
||||
ins_jmpl(int IR, int off)
|
||||
{
|
||||
if (BIT12(IR))
|
||||
regL = regP+1;
|
||||
regP = off-1;
|
||||
regL = regP;
|
||||
regP = off;
|
||||
return SCPE_OK;
|
||||
}
|
||||
/*
|
||||
* Conditional jump.
|
||||
* off is unused here.
|
||||
*/
|
||||
int
|
||||
ins_cjp(int IR, int off)
|
||||
@ -1313,8 +1390,6 @@ ins_rop(int IR, int off)
|
||||
rd = IR & 07;
|
||||
s = rs ? R[rs] : 0;
|
||||
d = rd ? R[rd] : 0;
|
||||
if (rs == 2) s++;
|
||||
if (rd == 2) d++;
|
||||
if (BIT6(IR)) d = 0; /* clear dest */
|
||||
if (BIT7(IR)) s = ~s; /* complement src */
|
||||
if (BIT10(IR)) { /* add source to destination */
|
||||
@ -1335,7 +1410,6 @@ ins_rop(int IR, int off)
|
||||
}
|
||||
}
|
||||
if (rd) R[rd] = d;
|
||||
if (rd == 2) regP--;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -1345,28 +1419,17 @@ ins_rop(int IR, int off)
|
||||
static int
|
||||
iox_check(int dev)
|
||||
{
|
||||
#ifdef TIMERHACK
|
||||
if ((dev & 03777) == 011) {
|
||||
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
|
||||
|
||||
mm_privcheck();
|
||||
|
||||
if ((dev & 0177774) == 010)
|
||||
return iox_clk(dev);
|
||||
#endif
|
||||
if ((dev & 0177770) == 0300)
|
||||
return iox_tty(dev);
|
||||
if ((dev & 0177770) == 01560)
|
||||
return iox_floppy(dev);
|
||||
|
||||
intrpt14(IIE_IOX);
|
||||
|
||||
intrpt14(IIE_IOX, PM_CPU);
|
||||
return SCPE_OK;
|
||||
|
||||
}
|
||||
@ -1376,15 +1439,15 @@ getoff(int ir)
|
||||
{
|
||||
int ea;
|
||||
|
||||
ea = BIT8(ir) ? regB : regP;
|
||||
if (BIT10(ir) & !BIT9(ir))
|
||||
ea = BIT8(ir) ? regB : oregP;
|
||||
if (BIT10(ir) & !BIT9(ir) & !BIT8(ir))
|
||||
ea = 0;
|
||||
ea += SEXT8(ir);
|
||||
if (BIT9(ir))
|
||||
ea = rdmem(ea);
|
||||
ea = rdmem(ea & 0177777, BIT8(ir) ? M_APT : M_PT);
|
||||
if (BIT10(ir))
|
||||
ea += regX;
|
||||
return ea;
|
||||
return ea & 0177777;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1395,6 +1458,8 @@ nd_mcl(int reg)
|
||||
{
|
||||
int reason = SCPE_OK;
|
||||
|
||||
mm_privcheck();
|
||||
|
||||
switch (reg) {
|
||||
case IR_STS:
|
||||
regSTL &= ~(regA & 0377);
|
||||
@ -1421,14 +1486,16 @@ nd_mst(int reg)
|
||||
{
|
||||
int reason = SCPE_OK;
|
||||
|
||||
mm_privcheck();
|
||||
|
||||
switch (reg) {
|
||||
case IR_STS:
|
||||
regSTL |= (regA & 0377);
|
||||
break;
|
||||
case 006: /* PID */
|
||||
case IR_PID: /* PID */
|
||||
pid |= regA;
|
||||
break;
|
||||
case 007: /* PIE */
|
||||
case IR_PIE: /* PIE */
|
||||
pie |= regA;
|
||||
break;
|
||||
|
||||
@ -1446,6 +1513,8 @@ nd_trr(int reg)
|
||||
{
|
||||
int reason = SCPE_OK;
|
||||
|
||||
mm_privcheck();
|
||||
|
||||
switch (reg) {
|
||||
case IR_STS:
|
||||
regSTL = regA & 0377;
|
||||
@ -1457,7 +1526,7 @@ nd_trr(int reg)
|
||||
mm_wrpcr();
|
||||
break;
|
||||
case 005: /* IIE */
|
||||
iie = regA & 02776;
|
||||
iie = regA & 03776;
|
||||
break;
|
||||
case 006: /* PID */
|
||||
pid = regA;
|
||||
@ -1465,6 +1534,12 @@ nd_trr(int reg)
|
||||
case 007: /* PIE */
|
||||
pie = regA;
|
||||
break;
|
||||
case IR_CCL:
|
||||
break;
|
||||
case IR_LCIL:
|
||||
break;
|
||||
case IR_UCIL:
|
||||
break;
|
||||
case IR_ECCR:
|
||||
eccr = regA;
|
||||
break;
|
||||
@ -1482,15 +1557,20 @@ nd_tra(int reg)
|
||||
{
|
||||
int reason = SCPE_OK;
|
||||
|
||||
mm_privcheck();
|
||||
|
||||
switch (reg) {
|
||||
case IR_PANS:
|
||||
regA = 0;
|
||||
break;
|
||||
case IR_STS: /* STS */
|
||||
regA = regSTL | regSTH | (curlvl << 8);
|
||||
break;
|
||||
case IR_PGS: /* 3 */
|
||||
regA = 0; /* XXX */
|
||||
case IRR_OPR:
|
||||
regA = opr;
|
||||
break;
|
||||
case IR_PVL: /* 4 */
|
||||
regA = pvl;
|
||||
case IRR_PVL:
|
||||
regA = (pvl << 3) | 0153602;
|
||||
break;
|
||||
case IR_IIC: /* read IIC. Clears IIC and IID */
|
||||
regA = iic;
|
||||
@ -1509,23 +1589,14 @@ nd_tra(int reg)
|
||||
case 012: /* ALD */
|
||||
regA = ald;
|
||||
break;
|
||||
case 013: /* PES */
|
||||
regA = 0; /* XXX */
|
||||
break;
|
||||
case 014: /* read back PCR */
|
||||
mm_rdpcr();
|
||||
break;
|
||||
case 015: /* */
|
||||
regA = 0; /* XXX */
|
||||
break;
|
||||
default:
|
||||
reason = STOP_UNHINS;
|
||||
reason = mm_tra(reg);
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
int
|
||||
highest_level(void)
|
||||
highest_level()
|
||||
{
|
||||
int i, d = pid & pie;
|
||||
|
||||
@ -1555,14 +1626,19 @@ fls(int msk)
|
||||
* Post an internal interrupt for the given source.
|
||||
*/
|
||||
void
|
||||
intrpt14(int src)
|
||||
intrpt14(int src, int where)
|
||||
{
|
||||
iid |= src; /* set detect flipflop */
|
||||
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);
|
||||
/* If we can interrupt, jump directly back */
|
||||
if (ISION() && curlvl < 14 && (pie & (1 << 14)) &&
|
||||
(where == PM_CPU))
|
||||
longjmp(env, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1587,7 +1663,8 @@ identrm(int id)
|
||||
struct intr *ip = ilnk[id-10];
|
||||
|
||||
if (ip == 0) {
|
||||
intrpt14(IIE_IOX);
|
||||
intrpt14(IIE_IOX, PM_CPU);
|
||||
regA = 0;
|
||||
} else {
|
||||
regA = ip->ident;
|
||||
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
|
||||
hist_save(int ir)
|
||||
{
|
||||
@ -1626,13 +1688,13 @@ hist_save(int ir)
|
||||
|
||||
hist_ptr->ir = ir;
|
||||
hist_ptr->sts = regSTL | regSTH | (curlvl << 8);
|
||||
hist_ptr->d = R[1];
|
||||
hist_ptr->p = R[2];
|
||||
hist_ptr->b = R[3];
|
||||
hist_ptr->l = R[4];
|
||||
hist_ptr->a = R[5];
|
||||
hist_ptr->t = R[6];
|
||||
hist_ptr->x = R[7];
|
||||
hist_ptr->d = regD;
|
||||
hist_ptr->p = oregP;
|
||||
hist_ptr->b = regB;
|
||||
hist_ptr->l = regL;
|
||||
hist_ptr->a = regA;
|
||||
hist_ptr->t = regT;
|
||||
hist_ptr->x = regX;
|
||||
}
|
||||
|
||||
t_stat
|
||||
@ -1732,4 +1794,3 @@ hist_show(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -82,14 +82,24 @@
|
||||
|
||||
#define ND_SKP_CLEPT 0140301
|
||||
#define ND_SKP_EXR 0140600
|
||||
#define ND_SKP_ADDD 0140120 /* CE/CX */
|
||||
#define ND_SKP_BFILL 0140130
|
||||
#define ND_SKP_MOVB 0140131
|
||||
#define ND_SKP_MOVBF 0140132
|
||||
#define ND_SKP_VERSN 0140133 /* ND110 */
|
||||
#define ND_SKP_RMPY 0141200
|
||||
#define ND_SKP_RDIV 0141600
|
||||
#define ND_SKP_LBYT 0142200
|
||||
#define ND_SKP_SBYT 0142600
|
||||
#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_IDENT11 0143611
|
||||
#define ND_SKP_IDENT12 0143622
|
||||
@ -115,6 +125,7 @@
|
||||
#define ND_WAIT 0151000
|
||||
#define ND_MONMSK 0177400
|
||||
|
||||
#define ND_MIS_OPCOM 0150400
|
||||
#define ND_MIS_IOF 0150401
|
||||
#define ND_MIS_ION 0150402
|
||||
#define ND_MIS_POF 0150404
|
||||
@ -128,20 +139,32 @@
|
||||
#define ND_MIS_DEPO 0150417
|
||||
|
||||
/* Internal registers */
|
||||
#define IR_PANS 000 /* Panel status */
|
||||
#define IR_STS 001 /* Status reg (as in register stack) */
|
||||
#define IR_OPR 002 /* Operator reg */
|
||||
#define IR_LMP 002 /* Display reg */
|
||||
#define IR_PGS 003 /* paging status reg */
|
||||
#define IR_PCR 003 /* paging control reg */
|
||||
#define IR_PVL 004 /* Previous level */
|
||||
#define IR_IIC 005 /* Internal interrupt code */
|
||||
#define IR_IIE 005 /* Internal interrupt enable */
|
||||
#define IR_PID 006 /* Priority interrupt detect */
|
||||
#define IR_PIE 007 /* Priority interrupt enable */
|
||||
#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 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 */
|
||||
#define IIE_MC 0000002 /* Monitor call */
|
||||
#define IIE_PV 0000004 /* Protect Violation */
|
||||
@ -172,7 +195,10 @@
|
||||
#define ISPON() BIT14(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_PGU 0004000
|
||||
|
||||
@ -198,7 +224,8 @@ extern uint16 PM[];
|
||||
extern uint16 R[8];
|
||||
extern uint16 regSTH; /* common for all levels */
|
||||
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.
|
||||
@ -220,18 +247,31 @@ int iox_floppy(int addr);
|
||||
int iox_tty(int addr);
|
||||
int iox_clk(int addr);
|
||||
|
||||
/* virtual memory access */
|
||||
#define M_PHYS 0
|
||||
#define M_PT 1
|
||||
#define M_APT 2
|
||||
#define M_FETCH 3
|
||||
|
||||
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_rdpcr(void);
|
||||
/* physical memory access */
|
||||
#define PM_CPU 10 /* CPU requesting (longjmp allowed) */
|
||||
#define PM_DMA 11 /* device requesting (no longjmp) */
|
||||
|
||||
/* 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);
|
||||
|
||||
#define STOP_UNHIOX 1
|
||||
@ -239,6 +279,7 @@ void extint(int lvl, struct intr *intr);
|
||||
#define STOP_CKSUM 3
|
||||
#define STOP_BP 4
|
||||
#define STOP_WAIT 5
|
||||
#define STOP_END 6
|
||||
|
||||
/* Useful bit extraction macros */
|
||||
#define BIT0(x) ((x) & 1)
|
||||
|
||||
@ -31,13 +31,21 @@
|
||||
#include "nd100_defs.h"
|
||||
|
||||
/*
|
||||
* Floppy and Streamer Controller (3112).
|
||||
* Floppy and Streamer Controller 3112.
|
||||
* 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
|
||||
* 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);
|
||||
@ -45,6 +53,9 @@ t_stat floppy_reset (DEVICE *dptr);
|
||||
t_stat floppy_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat floppy_attach (UNIT *uptr, CONST char *cptr);
|
||||
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_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_ERR 0000020 /* OR of errors */
|
||||
#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 */
|
||||
#define FL_CW_IE 0000002 /* interrupt enable (RFT) */
|
||||
@ -128,6 +139,7 @@ static int fl_lpl; /* devno + 7 load pointer low */
|
||||
/* Command word (000) */
|
||||
#define CW_FL_RD 0000000 /* Read 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_CMDMSK 077 /* mask for command */
|
||||
#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_WRITE 02 /* unit writing */
|
||||
#define U_RDFMT 03 /* Read format */
|
||||
#define U_EXTST 04 /* Read extended status */
|
||||
|
||||
#define devaddr u4 /* unit offset (in words) */
|
||||
#define wcnt u5 /* word count */
|
||||
@ -199,21 +212,21 @@ iox_floppy(int addr)
|
||||
int n;
|
||||
int rv = 0;
|
||||
|
||||
|
||||
switch (addr & 07) {
|
||||
case 0: /* read data */
|
||||
regA = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
regA = fl_rstatus;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
n = regA;
|
||||
if (n & FL_CW_TEST) {
|
||||
rv = floppy_test(&floppy_unit[0]);
|
||||
break;
|
||||
}
|
||||
if (n & FL_CW_FCE) {
|
||||
rv = floppy_excmd();
|
||||
break;
|
||||
@ -239,10 +252,10 @@ iox_floppy(int addr)
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = STOP_UNHIOX;
|
||||
break;
|
||||
if ((addr & 1) == 0)
|
||||
regA = 0;
|
||||
break; /* Unused IOXes are ignored */
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -253,32 +266,61 @@ floppy_reset(DEVICE *dptr)
|
||||
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
|
||||
floppy_svc(UNIT *uptr)
|
||||
{
|
||||
unsigned char *wp;
|
||||
int i, j;
|
||||
int cbaddr = fl_lpl + ((fl_lph & 0377) << 8);
|
||||
int cbaddr = getmval();
|
||||
int lah = 0, lal = 0;
|
||||
int status2 = 0;
|
||||
int remwh = 0, remwl = 0;
|
||||
|
||||
if ((fl_rstatus & FL_ST_ACT) == 0)
|
||||
return STOP_UNHIOX;
|
||||
|
||||
switch (uptr->state) {
|
||||
case U_READ:
|
||||
wp = malloc(uptr->wcnt * 2);
|
||||
if (fseek(uptr->fileref, uptr->devaddr * 2, SEEK_SET) < 0)
|
||||
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]);
|
||||
dtomem(uptr->fileref, uptr->devaddr,
|
||||
uptr->memaddr, uptr->wcnt, PM_DMA);
|
||||
lah = (uptr->memaddr + uptr->wcnt) >> 16;
|
||||
lal = (uptr->memaddr + uptr->wcnt) & 0177777;
|
||||
free(wp);
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
case U_WRITE:
|
||||
@ -286,13 +328,12 @@ floppy_svc(UNIT *uptr)
|
||||
return STOP_UNHIOX;
|
||||
}
|
||||
|
||||
wrmem(cbaddr+CB_ST1, FL_ST_RDY);
|
||||
wrmem(cbaddr+CB_ST2,
|
||||
ST2_FL_BS1K|ST2_FL_DS|ST2_FL_DD|ST2_FL_514);
|
||||
wrmem(cbaddr+CB_LAH, lah);
|
||||
wrmem(cbaddr+CB_LAL, lal);
|
||||
wrmem(cbaddr+CB_REMWH, 0);
|
||||
wrmem(cbaddr+CB_REMWL, 0);
|
||||
pwrmem(cbaddr+CB_ST1, FL_ST_RDY, PM_DMA);
|
||||
pwrmem(cbaddr+CB_ST2, status2, PM_DMA); /* set after error or rdfmt */
|
||||
pwrmem(cbaddr+CB_LAH, lah, PM_DMA);
|
||||
pwrmem(cbaddr+CB_LAL, lal, PM_DMA);
|
||||
pwrmem(cbaddr+CB_REMWH, remwh, PM_DMA);
|
||||
pwrmem(cbaddr+CB_REMWL, remwl, PM_DMA);
|
||||
|
||||
fl_rstatus &= ~FL_ST_ACT;
|
||||
fl_rstatus |= FL_ST_RDY;
|
||||
@ -305,6 +346,38 @@ err:
|
||||
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
|
||||
floppy_boot(int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
@ -312,14 +385,63 @@ floppy_boot(int32 unitno, DEVICE *dptr)
|
||||
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
|
||||
floppy_excmd(void)
|
||||
{
|
||||
UNIT *unit;
|
||||
int cw, u, cmd;
|
||||
int cbaddr = fl_lpl + ((fl_lph & 0377) << 8);
|
||||
int cw, u, cmd, i;
|
||||
int cbaddr = getmval();
|
||||
int status2, sectsz;
|
||||
|
||||
cw = rdmem(cbaddr+CB_CW);
|
||||
cw = prdmem(cbaddr+CB_CW, PM_CPU);
|
||||
u = (cw >> CW_FL_SELSH) & 03;
|
||||
cmd = cw & CW_FL_CMDMSK;
|
||||
|
||||
@ -327,26 +449,34 @@ floppy_excmd(void)
|
||||
if ((unit->flags & UNIT_ATT) == 0)
|
||||
goto err; /* floppy not inserted */
|
||||
|
||||
status2 = readfmt(unit);
|
||||
sectsz = (status2 & ST2_FL_BS1K) == 0 ? 512 : 1024;
|
||||
|
||||
/* XXX check disk size, word count etc... */
|
||||
unit->memaddr = ((rdmem(cbaddr+CB_DAHMAH) & 0377) << 16) | rdmem(cbaddr+CB_MAL);
|
||||
unit->wcnt = ((rdmem(cbaddr+CB_OPTWCH) & 0377) << 16) | rdmem(cbaddr+CB_WCL);
|
||||
unit->devaddr = ((rdmem(cbaddr+CB_DAHMAH) & 0177400) << 8) |
|
||||
rdmem(cbaddr+CB_DAL);
|
||||
|
||||
if (cmd == CW_FL_RDFMT) {
|
||||
unit->state = U_RDFMT;
|
||||
} else if (cmd == CW_FL_RD || cmd == CW_FL_WR) {
|
||||
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 */
|
||||
unit->memaddr = ((prdmem(cbaddr+CB_DAHMAH, PM_CPU) & 0377) << 16) |
|
||||
prdmem(cbaddr+CB_MAL, PM_CPU);
|
||||
i = prdmem(cbaddr+CB_OPTWCH, PM_CPU);
|
||||
unit->wcnt = ((i & 0377) << 16) | prdmem(cbaddr+CB_WCL, PM_CPU);
|
||||
if ((i & CB_OPT_WC) == 0)
|
||||
unit->wcnt *= (sectsz/2);
|
||||
unit->devaddr = (((prdmem(cbaddr+CB_DAHMAH, PM_CPU) & 0177400) << 8) |
|
||||
prdmem(cbaddr+CB_DAL, PM_CPU)) * sectsz;
|
||||
|
||||
switch (cmd) {
|
||||
case CW_FL_RD:
|
||||
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;
|
||||
}
|
||||
|
||||
sim_activate(&floppy_unit[u], 10);
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "sim_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);
|
||||
|
||||
@ -36,6 +85,11 @@ uint16 PM[MAXMEMSIZE];
|
||||
uint16 PCR[16]; /* Paging control register */
|
||||
uint16 ptmap[4][64]; /* protection */
|
||||
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)
|
||||
|
||||
@ -43,6 +97,9 @@ UNIT mm_unit = { UDATA(NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 0) };
|
||||
|
||||
REG mm_reg[] = {
|
||||
{ BRDATA(PCR, PCR, 8, 16, 16) },
|
||||
{ ORDATA(PEA, pea, 16) },
|
||||
{ ORDATA(PES, pes, 16) },
|
||||
{ ORDATA(PGS, pgs, 16) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -52,16 +109,50 @@ DEVICE mm_dev = {
|
||||
1, 8, 16, 1, 8, 16,
|
||||
0, 0, &mm_reset,
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
@ -70,13 +161,13 @@ rdbyte(int vaddr, int lr/* , int how*/)
|
||||
* Write a byte. 0 in lr is left byte, 1 is right byte.
|
||||
*/
|
||||
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 */
|
||||
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())
|
||||
return 0; /* not valid */
|
||||
if (vaddr > 0177777)
|
||||
return 0;
|
||||
if (ISSEX())
|
||||
return 1;
|
||||
return (vaddr >= 0177400);
|
||||
@ -139,57 +232,188 @@ shadowwr(int v, int dat)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
rdmem(int vaddr/* , int how*/)
|
||||
/*
|
||||
* MOR - memory out of range. Addressing non-existent memory.
|
||||
*/
|
||||
void
|
||||
morerr(int addr, int why, int pesval)
|
||||
{
|
||||
int pt;
|
||||
|
||||
vaddr &= 0177777;
|
||||
|
||||
if ((vaddr >= 0177000) && is_shadow(vaddr))
|
||||
return shadowrd(vaddr);
|
||||
/* Mark page as read */
|
||||
if (ISPON()) {
|
||||
pt = (PCR[curlvl] >> 8) & 03;
|
||||
ptmap[pt][vaddr >> 10] |= PT_PGU;
|
||||
if (pea_locked == 0) {
|
||||
pea = (uint16)addr;
|
||||
pes = (uint16)(addr >> 16) | pesval;
|
||||
pea_locked = 1;
|
||||
}
|
||||
intrpt14(IIE_MOR, why);
|
||||
}
|
||||
|
||||
// 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
|
||||
wrmem(int vaddr, int val/* , int how*/)
|
||||
wrmem(int vaddr, int val, int how)
|
||||
{
|
||||
uint16 *ptmapp;
|
||||
int sh, pagetablenr, pagering, permit, pagenr;
|
||||
|
||||
vaddr &= 0177777;
|
||||
if ((vaddr >= 0177000) && is_shadow(vaddr)) {
|
||||
shadowwr(vaddr, val);
|
||||
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
|
||||
mm_wrpcr(void)
|
||||
mm_wrpcr()
|
||||
{
|
||||
if (ISDIS())
|
||||
return;
|
||||
PCR[(regA >> 3) & 017] = regA & 03603;
|
||||
}
|
||||
|
||||
void
|
||||
mm_rdpcr(void)
|
||||
{
|
||||
if (ISDIS())
|
||||
return;
|
||||
regA = PCR[(regA >> 3) & 017];
|
||||
}
|
||||
|
||||
|
||||
t_stat
|
||||
mm_reset(DEVICE *dptr)
|
||||
{
|
||||
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_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 */
|
||||
|
||||
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 */
|
||||
return ((r == SCPE_STALL)? SCPE_OK : r);/* !stall? report */
|
||||
}
|
||||
tto_status &= ~TT_OSTAT_ACT;
|
||||
tto_status |= TT_OSTAT_RDY;
|
||||
if (tto_ctrl & TT_OCTRL_EIRDY)
|
||||
extint(10, &tto_int);
|
||||
@ -193,6 +196,7 @@ iox_tty(int addr)
|
||||
case 5: /* Write data */
|
||||
tto_unit.buf = regA & 0177;
|
||||
tto_status &= ~TT_OSTAT_RDY;
|
||||
tto_status |= TT_OSTAT_ACT;
|
||||
sim_activate (&tto_unit, tto_unit.wait);
|
||||
break;
|
||||
|
||||
@ -201,15 +205,8 @@ iox_tty(int addr)
|
||||
break;
|
||||
|
||||
case 7: /* Write output control reg */
|
||||
tto_ctrl = regA;
|
||||
if (tto_ctrl & TT_OCTRL_ACT)
|
||||
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;
|
||||
/* Only interrupts are controlled */
|
||||
tto_status = (tto_status & ~03) | (regA & 03);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
char sim_name[] = "ND100";
|
||||
|
||||
extern REG cpu_reg[];
|
||||
REG *sim_PC = &cpu_reg[2];
|
||||
REG *sim_PC = &cpu_reg[8];
|
||||
int32 sim_emax = 1;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
@ -50,6 +50,7 @@ const char *sim_stop_messages[SCPE_BASE] = {
|
||||
"Checksum error",
|
||||
"Simulator breakpoint",
|
||||
"Wait at level 0",
|
||||
"manual end",
|
||||
};
|
||||
|
||||
static int mlp;
|
||||
@ -60,7 +61,7 @@ gb(FILE *f)
|
||||
int w;
|
||||
|
||||
if (f == NULL)
|
||||
return rdmem(mlp++);
|
||||
return prdmem(mlp++, PM_CPU);
|
||||
w = getc(f) & 0377;
|
||||
return w;
|
||||
}
|
||||
@ -106,7 +107,7 @@ sim_load(FILE *f, CONST char *buf, CONST char *fnam, t_bool flag)
|
||||
/* images have MSB first */
|
||||
s = (getc(f) & 0377) << 8;
|
||||
s |= getc(f) & 0377;
|
||||
wrmem(i, s);
|
||||
pwrmem(i, s, PM_CPU);
|
||||
}
|
||||
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("Word count %06o\n", F = gw(f));
|
||||
for (i = s = 0; i < F; i++) {
|
||||
wrmem(E+i, gw(f));
|
||||
s += rdmem(E+i);
|
||||
pwrmem(E+i, gw(f), PM_CPU);
|
||||
s += prdmem(E+i, PM_CPU);
|
||||
}
|
||||
printf("Checksum %06o\n", H = gw(f));
|
||||
if (H != s)
|
||||
@ -180,6 +181,10 @@ static char *trrtab[] = {
|
||||
"cclr", "lcil", "ucil", "err13", "err14", "eccr", "err16", "err17"
|
||||
};
|
||||
|
||||
static char *mitab[] = {
|
||||
"ldatx", "ldxtx", "lddtx", "ldbtx", "statx", "stztx", "stdtx", "ERR"
|
||||
};
|
||||
|
||||
t_stat
|
||||
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");
|
||||
else if ((op & 0177707) == ND_SKP_EXR)
|
||||
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)
|
||||
fprintf(of, "rmpy %s %s",
|
||||
dactab[(op & 070) >> 3], dactab[op & 07]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user