1
0
mirror of https://github.com/prirun/p50em.git synced 2026-04-26 12:26:56 +00:00

32-bit page maps for access to more than 8MB of physical memory

optimized ZMV
implemented LIOT, PTLB
optimized backstop BIX loop to just sleep instead
This commit is contained in:
Jim
2005-09-03 00:00:00 -04:00
parent 37882550a8
commit c6a52800f0
2 changed files with 211 additions and 165 deletions

353
em.c
View File

@@ -198,8 +198,10 @@ char gen0nam[][5] = {
#define T_FAULT (traceflags & TB_FAULT)
#define T_PX (traceflags & TB_PX)
#define T_TRACE1 TB_FLOW | TB_INST | T_DIO | T_PCL | T_FAULT
int traceflags=0; /* each bit is a trace flag */
int savetraceflags=0; /* see ITLB, BDX */
int savetraceflags=0; /* see ITLB */
int intvec=-1; /* currently raised interrupt (if >= zero) */
@@ -208,7 +210,9 @@ int intvec=-1; /* currently raised interrupt (if >= zero)
unsigned short sswitch = 0; /* sense switches, set with --ss */
unsigned short cpuid = 0; /* STPM CPU model, set with --cpuid */
/* NOTE: the default cpuid is a 4150: 2 MIPS, 32MB of memory */
unsigned short cpuid = 27; /* STPM CPU model, set with --cpuid */
unsigned long instcount=0; /* global instruction count */
@@ -218,10 +222,12 @@ unsigned int instpermsec = 2048; /* initially assume 2048 inst/msec */
jmp_buf jmpbuf; /* for longjumps to the fetch loop */
/* define a 4 million 16-bit word system memory; later systems have
more main memory capacity, using a different page map setup */
/* The standard Prime physical memory limit on early machines is 8MB.
Later machines have higher memory capacities, up to 1GB, using
32-bit page tables.
NOTE: rev 20 is limited to 32MB on all machines. */
#define MEMSIZE 4*1024*1024
#define MEMSIZE 16*1024*1024 /* 32 MB */
unsigned short mem[MEMSIZE]; /* system's physical memory */
#define MAKEVA(seg,word) ((((int)(seg))<<16) | (word))
@@ -233,20 +239,21 @@ unsigned short mem[MEMSIZE]; /* system's physical memory */
/* STLB cache is defined here. There are several different styles on
various Prime models. This is modeled after the 6350 STLB, but is
only 1-way associative */
only 1-way associative and doesn't have slots dedicated to I/O
segments */
#define STLBENTS 512
typedef struct {
char valid; /* 1 if this STLB entry is valid, zero otherwise */
char unmodified; /* 1 if this page hasn't been modified, 0 if modified */
char valid; /* 1 if STLB entry is valid, zero otherwise */
char unmodified; /* 1 if page hasn't been modified, 0 if modified */
// char shared; /* 1 if page is shared and can't be cached */
char access[4]; /* ring n access rights */
unsigned short procid; /* process id for segments >= '4000 */
unsigned short seg; /* segment number */
unsigned int ppn; /* physical page number (128MB limit) */
unsigned int ppn; /* physical page number (15 bits = 64MB limit) */
unsigned short *pmep; /* pointer to page table flag word */
unsigned long load_ic; /* instruction where STLB was loaded */
unsigned long load_ic; /* instruction where STLB was loaded (for debug) */
} stlbe_t;
stlbe_t stlb[STLBENTS];
@@ -305,9 +312,12 @@ unsigned short amask; /* address mask */
#define SEGFAULT 076
#define POINTERFAULT 077
ea_t tnoua_ea=0, tnou_ea=0;
int verbose; /* --v (not used anymore) */
int domemdump; /* --memdump arg */
int boot; /* true if reading a boot record */
int pmap32bits; /* true if 32-bit page maps */
int csoffset; /* concealed stack segment offset */
/* load map related data, specified with --map */
@@ -397,6 +407,10 @@ readloadmap(char *filename) {
addsym(sym, pbseg, pbword, 'p');
addsym(sym, lbseg, lbword, 'l');
//printf("adding proc symbol, line=%s\n", line);
if (tnou_ea == 0 && strcmp(sym,"TNOU") == 0)
tnou_ea = MAKEVA(ecbseg, ecbword);
if (tnoua_ea == 0 && strcmp(sym,"TNOUA") == 0)
tnoua_ea = MAKEVA(ecbseg, ecbword);
} else if (sscanf(line, "%s %o %o", sym, &segno, &wordno) == 3) {
addsym(sym, segno, wordno, 'x');
//printf("adding symbol, line=%s\n", line);
@@ -490,7 +504,7 @@ pa_t mapva(ea_t ea, short intacc, unsigned short *access, ea_t rp) {
short relseg,seg,nsegs,ring;
unsigned short pte, stlbix;
stlbe_t *stlbp;
unsigned int dtar,sdw,staddr,ptaddr,pmaddr;
unsigned int dtar,sdw,staddr,ptaddr,pmaddr,ppn;
pa_t pa;
seg = SEGNO(ea);
@@ -521,9 +535,17 @@ pa_t mapva(ea_t ea, short intacc, unsigned short *access, ea_t rp) {
if (sdw & 0x8000)
fault(SEGFAULT, 2, ea); /* fcode = sdw fault bit set */
ptaddr = (((sdw & 0x3F)<<10) | (sdw>>22)) << 6;
pmaddr = ptaddr + PAGENO(ea);
pte = mem[pmaddr];
if (T_MAP) fprintf(stderr," ptaddr=%o, pmaddr=%o, pte=%o\n", ptaddr, pmaddr, pte);
if (pmap32bits) {
pmaddr = ptaddr + 2*PAGENO(ea);
pte = mem[pmaddr];
ppn = mem[pmaddr+1];
if (T_MAP) fprintf(stderr," ptaddr=%o, pmaddr=%o, pte=%o\n", ptaddr, pmaddr, pte);
} else {
pmaddr = ptaddr + PAGENO(ea);
pte = mem[pmaddr];
ppn = pte & 0xFFF;
if (T_MAP) fprintf(stderr," ptaddr=%o, pmaddr=%o, pte=%o\n", ptaddr, pmaddr, pte);
}
if (!(pte & 0x8000))
fault(PAGEFAULT, 0, ea);
mem[pmaddr] |= 040000; /* set referenced bit */
@@ -534,7 +556,7 @@ pa_t mapva(ea_t ea, short intacc, unsigned short *access, ea_t rp) {
stlbp->access[3] = (sdw >> 6) & 7;
stlbp->procid = crs[OWNERL];
stlbp->seg = seg;
stlbp->ppn = (pte & 0xFFF);
stlbp->ppn = ppn;
stlbp->pmep = mem+pmaddr;
stlbp->load_ic = instcount;
}
@@ -548,7 +570,7 @@ pa_t mapva(ea_t ea, short intacc, unsigned short *access, ea_t rp) {
pa = (stlbp->ppn << 10) | (ea & 0x3FF);
if (T_MAP) fprintf(stderr," for ea %o/%o, stlbix=%d, pa=%o loaded at #%d\n", ea>>16, ea&0xffff, stlbix, pa, stlbp->load_ic);
} else {
pa = ea & 0x3FFFFF;
pa = ea & (MEMSIZE-1);
}
if (pa <= MEMSIZE)
return pa;
@@ -727,7 +749,7 @@ void calf(ea_t ea) {
this = last;
else
this = next-6;
csea = MAKEVA(crs[OWNERH], this);
csea = MAKEVA(crs[OWNERH]+csoffset, this);
if (T_FAULT) fprintf(stderr,"CALF: cs frame is at %o/%o\n", csea>>16, csea&0xFFFF);
/* make sure ecb specifies zero arguments */
@@ -843,7 +865,7 @@ void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) {
if (T_FAULT) fprintf(stderr, "fault: Concealed stack wraparound to first");
next = first;
}
csea = MAKEVA(crs[OWNERH], next);
csea = MAKEVA(crs[OWNERH]+csoffset, next);
put32r(faultrp, csea, 0);
put16r(crs[KEYS], csea+2, 0);
put16r(fcode, csea+3, 0);
@@ -1147,21 +1169,21 @@ unsigned int ea32i (ea_t earp, unsigned short inst, short i, short x) {
ea_t apea(unsigned short *bitarg) {
unsigned short ibr, ea_s, ea_w, bit, br;
unsigned short ibr, ea_s, ea_w, bit, br, a;
ea_t ea, ip;
ibr = get16(RP);
RPL++;
a = get16(RP);
RPL++;
bit = (ibr >> 12) & 0xF;
br = (ibr >> 8) & 3;
if (T_EAAP) fprintf(stderr," AP ibr=%o, br=%d, i=%d, bit=%d\n", ibr, br, (ibr & 004000) != 0, bit);
if (T_EAAP) fprintf(stderr," AP ibr=%o, br=%d, i=%d, bit=%d, a=%o\n", ibr, br, (ibr & 004000) != 0, bit, a);
/* XXX: should ea ring be weakened with RP ring? */
ea_s = crs[PBH + 2*br];
ea_w = crs[PBL + 2*br];
ea_w += get16(RP);
RPL++;
ea_w = crs[PBL + 2*br] + a;
ea = MAKEVA(ea_s, ea_w);
if (T_EAAP) fprintf(stderr," AP ea = %o/%o %s\n", ea_s, ea_w, searchloadmap(ea,' '));
if (ibr & 004000) {
@@ -1347,6 +1369,26 @@ ea_t stex(unsigned int extsize) {
}
void prtn() {
unsigned short stackrootseg;
ea_t newrp,newsb,newlb;
unsigned short keys;
stackrootseg = get16(*(unsigned int *)(crs+SB)+1);
put32(*(unsigned int *)(crs+SB), MAKEVA(stackrootseg,0));
newrp = get32(*(unsigned int *)(crs+SB)+2);
newsb = get32(*(unsigned int *)(crs+SB)+4);
newlb = get32(*(unsigned int *)(crs+SB)+6);
keys = get16(*(unsigned int *)(crs+SB)+8);
RP = newrp | (RP & RINGMASK32);
*(unsigned int *)(crs+SB) = newsb;
*(unsigned int *)(crs+LB) = newlb;
newkeys(keys & 0177770);
if (T_INST) fprintf(stderr," Finished PRTN, RP=%o/%o\n", RPH, RPL);
}
/* NOTE: the brsave array contains copies of the PB, SB, and LB base
registers at the time of the PCL, to compute argument effective
addresses. If the PCL faults during argument transfer, the ARGT
@@ -1558,6 +1600,9 @@ pcl (ea_t ecbea) {
ea_t stackfp; /* new stack frame pointer */
pa_t pa; /* physical address of ecb */
unsigned short brsave[6]; /* old PB,SB,LB */
unsigned short utempa;
unsigned short tnstring[500];
unsigned short tnlen;
#define FATAL$ MAKEVA(06,0164600)
#define INIT$3 MAKEVA(013,0174041)
@@ -1575,12 +1620,6 @@ pcl (ea_t ecbea) {
pa = mapva(ecbea, PACC, &access, RP);
if (T_PCL) fprintf(stderr," ecb @ %o/%o, access=%d\n", ecbea>>16, ecbea&0xFFFF, access);
#if 0
if (strstr(searchloadmap(ea,' '),"TNOU")) {
fprintf(stderr," TNOUx called!\n");
}
#endif
/* get a copy of the ecb. gates must be aligned on a 16-word
boundary, therefore can't cross a page boundary, and mapva has
already ensured that the ecb page is resident. For a non-gate
@@ -1713,6 +1752,44 @@ pcl (ea_t ecbea) {
crs[YL] = ecb[5];
crs[XL] = 0;
argt();
#if 0
/* do something here to intercept TNOUx calls for user 1, to avoid
9600-bps system console issue. This sort of works, but not all
console output is trapped so it gets mixed together. Trapping
tolio$ may work better. However, that has the problem of not
putting characters into the como file. Could also trap, do
printf, let it go into asrbuf, ignore it in devasr. With a big
ASRBUF, this might work fine. */
if (ecbea == tnou_ea || ecbea == tnoua_ea) {
fprintf(stderr," TNOUx called, ea=%o/%o\n", ecbea>>16, ecbea&0xffff);
ea = *(unsigned int *)(crs+SB) + ecb[4];
utempa = get16(get32(ea)); /* userid */
if (utempa == 1) {
ea = ea + 6;
tnlen = get16(get32(ea)); /* length in bytes */
ea = get32(ea-3); /* address of string */
for (i=0; i<(tnlen+1)/2; i++)
tnstring[i] = get16(ea+i) & 0x7f7f;
tnstring[i] = 0;
if (ecbea == tnoua_ea) {
printf("%s", tnstring);
fflush(stdout);
} else
printf("%s\n", tnstring);
prtn();
return;
/* HOWEVER, RP really needs to point to a real PRTN
instruction in case prtn faults. Right now, RP points to
ARGT. Maybe use flags in the stackframe header to indicate
that the ARGT should actually prtn instead??
*/
}
}
#endif
RPL++; /* advance real RP past ARGT after argument transfer */
}
}
@@ -1819,25 +1896,6 @@ argt() {
}
void prtn() {
unsigned short stackrootseg;
ea_t newrp,newsb,newlb;
unsigned short keys;
stackrootseg = get16(*(unsigned int *)(crs+SB)+1);
put32(*(unsigned int *)(crs+SB), MAKEVA(stackrootseg,0));
newrp = get32(*(unsigned int *)(crs+SB)+2);
newsb = get32(*(unsigned int *)(crs+SB)+4);
newlb = get32(*(unsigned int *)(crs+SB)+6);
keys = get16(*(unsigned int *)(crs+SB)+8);
RP = newrp | (RP & RINGMASK32);
*(unsigned int *)(crs+SB) = newsb;
*(unsigned int *)(crs+LB) = newlb;
newkeys(keys & 0177770);
if (T_INST) fprintf(stderr," Finished PRTN, RP=%o/%o\n", RPH, RPL);
}
/* process exchange register save: saves the current register
set to the process pcb.
NOTES:
@@ -2478,6 +2536,7 @@ main (int argc, char **argv) {
unsigned short trapvalue;
ea_t trapaddr;
unsigned short stpm[8];
unsigned short access;
unsigned short zresult, zclen1, zclen2, zaccess;
unsigned int zlen1, zlen2;
@@ -2517,6 +2576,8 @@ main (int argc, char **argv) {
verbose = 0;
domemdump = 0;
boot = 0;
pmap32bits = 0;
csoffset = 0;
/* check args */
@@ -2541,7 +2602,7 @@ main (int argc, char **argv) {
sscanf(argv[i+1],"%d", &templ);
cpuid = templ;
} else
cpuid = 0;
fprintf(stderr,"--cpuid needs an argument\n");
} else if (strcmp(argv[i],"--trace") == 0)
while (i+1 < argc && argv[i+1][0] != '-') {
if (strcmp(argv[i+1],"ear") == 0)
@@ -2580,6 +2641,12 @@ main (int argc, char **argv) {
fprintf(stderr,"Unrecognized argument: %s\n", argv[i]);
}
/* set some vars after the options have been read */
pmap32bits = (cpuid == 15 || cpuid == 18 || cpuid == 19 || cpuid == 24 || cpuid >= 26);
if ((26 <= cpuid && cpuid <= 29) || cpuid >= 35)
csoffset = 1;
fprintf(stderr,"Sense switches set to %o\n", sswitch);
/* initialize all devices */
@@ -2627,9 +2694,6 @@ main (int argc, char **argv) {
newkeys(rvec[6]);
RPL = rvec[2];
if (RPL == 0161000) /* hack for *DOS64; P is off by 3?? */
RPL = 0161003;
if (domemdump)
memdump(rvec[0], rvec[1]);
@@ -2653,20 +2717,9 @@ main (int argc, char **argv) {
while (1) {
if (0 && instcount > 85400000) /* this is to debug ppa problem */
if (0 && instcount > 46800000) /* to debug LIOT on --cpuid 5 */
traceflags = ~TB_MAP;
if (0 && instcount > 99700000) /* this is to debug disk rd err problem */
traceflags = ~TB_MAP;
#if 0
if (savetraceflags || (crs[MODALS] & 0100010)==010)
traceflags = ~TB_MAP;
else
traceflags = 0;
#endif
#if 0
/* NOTE: don't trace TFLADJ loops */
@@ -2698,8 +2751,6 @@ main (int argc, char **argv) {
if (devpoll[i] && (--devpoll[i] == 0)) {
if (!devmap[i])
fatal("devpoll set but devmap is null");
if (RPL == 070511 && savetraceflags != 0)
traceflags = savetraceflags;
devmap[i](4, 0, i);
}
@@ -2707,8 +2758,6 @@ main (int argc, char **argv) {
if (intvec >= 0 && (crs[MODALS] & 0100000) && inhcount == 0) {
//printf("fetch: taking interrupt vector '%o, modals='%o\n", intvec, crs[MODALS]);
if (RPL == 070511 && savetraceflags != 0)
traceflags = savetraceflags;
if (T_INST) fprintf(stderr, "\nfetch: taking interrupt vector '%o, modals='%o\n", intvec, crs[MODALS]);
regs.sym.pswpb = RP;
regs.sym.pswkeys = crs[KEYS];
@@ -3164,7 +3213,6 @@ stfa:
#if 1
#if 1
#define ZGETC(zea, zlen, zcp, zclen, zch) \
if (zclen == 0) { \
zcp = (unsigned char *) (mem+mapva(zea, RACC, &zaccess, RP)); \
@@ -3201,8 +3249,6 @@ stfa:
zclen--; \
zlen--
#endif
if (inst == 001114) {
if (T_FLOW) fprintf(stderr," ZMV\n");
if (crs[KEYS] & 020)
@@ -3210,20 +3256,25 @@ stfa:
else
zspace = 0240;
//printf("ZMV: source=%o/%o, len=%d, dest=%o/%o, len=%d, keys=%o\n", crsl[FAR0]>>16, crsl[FAR0]&0xffff, GETFLR(0), crsl[FAR1]>>16, crsl[FAR1]&0xffff, GETFLR(1), crs[KEYS]);
utempa = crs[A];
do {
ldc(0);
if (!(crs[KEYS] & 0100))
stc(1);
else {
crs[A] = zspace;
do {
stc(1);
} while (!(crs[KEYS] & 0100));
}
} while (!(crs[KEYS] & 0100));
crs[A] = utempa;
//printf("ZMV finished\n");
zlen1 = GETFLR(0);
zlen2 = GETFLR(1);
zea1 = crsl[FAR0];
if (crsl[FLR0] & 0x8000)
zea1 |= EXTMASK32;
zea2 = crsl[FAR1];
if (crsl[FLR1] & 0x8000)
zea2 |= EXTMASK32;
if (T_INST) fprintf(stderr," ea1=%o/%o, len1=%d, ea2=%o/%o, len2=%d\n", zea1>>16, zea1&0xffff, zlen1, zea2>>16, zea2&0xffff, zlen2);
zclen1 = 0;
zclen2 = 0;
while (zlen2) {
if (zlen1) {
ZGETC(zea1, zlen1, zcp1, zclen1, zch1);
} else
zch1 = zspace;
ZPUTC(zea2, zlen2, zcp2, zclen2, zch1);
}
crs[KEYS] |= 0100;
continue;
}
@@ -3241,7 +3292,7 @@ stfa:
//printf("ZMVD: ea1=%o/%o, ea2=%o/%o, len=%d\n", zea1>>16, zea1&0xffff, zea2>>16, zea2&0xffff, zlen1);
zclen1 = 0;
zclen2 = 0;
while (zlen1) {
while (zlen2) {
ZGETC(zea1, zlen1, zcp1, zclen1, zch1);
ZPUTC(zea2, zlen2, zcp2, zclen2, zch1);
}
@@ -3377,17 +3428,36 @@ stfa:
continue;
}
if (inst == 000711) {
if (T_FLOW) fprintf(stderr," LPSW\n");
/* NOTE: L contains target virtual address. How does
LIOT use the target virtual address to "help invalidate
the cache"? */
if (inst == 000044) {
if (T_FLOW) fprintf(stderr," LIOT\n");
RESTRICT();
lpsw();
ea = apea(NULL);
utempa = STLBIX(ea);
stlb[utempa].valid = 0;
if (T_INST) fprintf(stderr," invalidated STLB index %d\n", utempa);
mapva(ea, RACC, &access, RP);
if (T_INST) fprintf(stderr," loaded STLB for %o/%o\n", ea>>16, ea&0xffff);
continue;
}
if (inst == 000064) {
if (T_FLOW) fprintf(stderr," PTLB\n");
RESTRICT();
utempl = *(unsigned int *)(crs+L);
for (utempa = 0; utempa < STLBENTS; utempa++)
if ((utempl & 0x80000000) || stlb[utempa].ppn == utempl)
stlb[utempa].valid = 0;
continue;
}
if (inst == 000615) {
if (T_FLOW) fprintf(stderr," ITLB\n");
RESTRICT();
utempl = *(int *)(crs+L);
utempl = *(unsigned int *)(crs+L);
/* NOTE: Primos substitutes an ITLB loop for PTLB, and the ITLB
segno is 1, ie, it looks like using segment 1 invalidates all
@@ -3416,6 +3486,13 @@ stfa:
continue;
}
if (inst == 000711) {
if (T_FLOW) fprintf(stderr," LPSW\n");
RESTRICT();
lpsw();
continue;
}
if (inst == 000024) {
if (T_FLOW) fprintf(stderr," STPM\n", inst);
RESTRICT();
@@ -3443,8 +3520,8 @@ stfa:
*/
if (inst == 001702) {
if (T_FLOW) fprintf(stderr," IDLE?\n", inst);
printf(" IDLE? at #%d, OWNERL=%o, RP=%o/%o\n", instcount, crs[OWNERL], RPH, RPL);
if (T_FLOW) fprintf(stderr," 1702?\n", inst);
printf(" 1702? at #%d, OWNERL=%o, RP=%o/%o\n", instcount, crs[OWNERL], RPH, RPL);
RESTRICT();
//fault(UIIFAULT, RPL, RP);
traceflags = ~TB_MAP;
@@ -3526,8 +3603,10 @@ irtn:
if (inst == 001010) { /* E32I */
if (T_FLOW) fprintf(stderr," E32I\n");
fault(RESTRICTFAULT, 0, 0);
newkeys((crs[KEYS] & 0161777) | 4<<10);
if (cpuid < 4)
fault(RESTRICTFAULT, 0, 0);
else
newkeys((crs[KEYS] & 0161777) | 4<<10);
continue;
}
@@ -3931,17 +4010,30 @@ bidy:
if (inst == 0140734) {
if (T_FLOW) fprintf(stderr," BDX\n");
crs[X]--;
#if 0
if (RPL == 070512 && traceflags != 0) { /* backstop loop */
fprintf(stderr," Suppressing backstop trace\n");
savetraceflags = traceflags;
traceflags = 0;
} else if (RPL == 070512 && savetraceflags != 0 && crs[X] == 0) {
fprintf(stderr," Restoring backstop trace\n");
traceflags = savetraceflags;
#if 1
m = get16(RP);
if (crs[X] > 100 && m == RPL-1) {
//fprintf(stderr," BDX loop detected at %o/%o, remainder=%d\n", prevpc>>16, prevpc&0xffff, crs[X]);
utempl = instpermsec*10;
for (i=0; i<64; i++)
if (devpoll[i] && devpoll[i] < utempl)
utempl = devpoll[i];
utempl--;
for (i=0; i<64; i++)
if (devpoll[i])
devpoll[i] -= utempl;
usleep(utempl*1000/instpermsec);
crs[X] = 0;
instcount += utempl;
}
#endif
if (crs[X] != 0)
RPL = m;
else
RPL++;
continue;
#else
goto bidx;
#endif
}
if (inst == 0141206) {
@@ -5206,21 +5298,6 @@ keys = 14200, modals=100177
if (opcode == 00100) {
if (T_FLOW) fprintf(stderr," JMP\n");
RP = ea;
#if 1
/* it seems that on some DIAG tests (see JST), the monitor is
incorrectly entered in R-mode, which causes LDL to be
interpreted as JEQ, and the test incorrectly halts. This
helps with that, though the wrong tests appear to run, ie, it
says it's running test 1 but runs test 2, and some tests fail
that should work. (This latter problem is fixed with the JST
change to use the segment number on a long JST) */
if (prevpc < 0100000 && RP >= 0100000 && (crs[KEYS] & 010000) == 0) {
printf("Switching to V mode for DIAGS, keys=%o!\n", crs[KEYS]);
newkeys((crs[KEYS] & ~016000) | 014000);
}
#endif
continue;
}
@@ -5365,45 +5442,7 @@ keys = 14200, modals=100177
if (opcode == 01000) {
if (T_FLOW) fprintf(stderr," JST\n");
#if 1
/* NOTE: CPU.KEYS.SR, CPU.LOGICAL.VI, CPU.CLEAR.VI, CPU.MOVE.VI all
fail with unexpected seg faults on a 2-word JST instruction that
references a weird segment.
Ignoring the ea segment number gets past the segfault and seems
to begin the actual test, but then it fails with program halts
(and for CPU.CLEAR.VI, executes the Case 2 instruction CRLE when
it says it's executing Case 1)
Using the ea segment number as the JST word address seems to
work better, and executes CRE like it should. However, the
program still halts in the monitor portion (see below) and
this hack causes the Primos rev 22 boot to fail, even before
the memory test... :(
0/140561: 43400 A='0/0 B='177777/-1 X=147635/-12387 Y=177777/-1 C=0 L=0 LT=0 EQ=1 #25131753 [ 0]
opcode=00100, i=0, x=40000
ea32r64r: i=0, x=1
special, new opcode=00100, class=0
Class 0, new ea=3
Preindex, ea=3, X='147635/-12387
Preindex, new ea=147640
EA: 0/147640
JMP
0/147640: 5414 A='0/0 B='177777/-1 X=147635/-12387 Y=177777/-1 C=0 L=0 LT=0 EQ=1 #25131754 [ 0]
opcode=00200, i=0, x=0
ea32r64r: i=0, x=0
special, new opcode=00203, class=0
Class 0, new ea=115561
EA: 0/115561
JEQ
0/115561: 0 A='0/0 B='177777/-1 X=147635/-12387 Y=177777/-1 C=0 L=0 LT=0 EQ=1 #25131755 [ 0]
generic class 0
HLT
*/
#if 0
ea = MAKEVA(RPH, ea & 0xFFFF);
#endif
if (amask == 0177777)

23
emdev.h
View File

@@ -327,6 +327,9 @@ readasr:
IOSKIP;
} else if (04 <= func && func <= 07) { /* write control register 1/2 */
IOSKIP;
} else if (func == 017) {
/* NOTE: 9950 does this in rev 20, others don't */
IOSKIP;
} else {
printf("Unimplemented OTA '04 function '%02o\n", func);
fatal(NULL);
@@ -685,9 +688,9 @@ void devdisk (short class, short func, short device) {
case 4: /* poll (run channel program) */
while (dc[device].state == S_RUN) {
m = get16(dc[device].oar);
m1 = get16(dc[device].oar+1);
if (T_INST || T_DIO) fprintf(stderr,"\nDIOC %o: %o %o %o\n", dc[device].oar, m, m1, get16(dc[device].oar+2));
m = get16r(dc[device].oar, 0);
m1 = get16r(dc[device].oar+1, 0);
if (T_INST || T_DIO) fprintf(stderr,"\nDIOC %o: %o %o %o\n", dc[device].oar, m, m1, get16r(dc[device].oar+2, 0));
dc[device].oar += 2;
order = m>>12;
if (m & 04000) { /* "execute if ..." */
@@ -707,7 +710,7 @@ void devdisk (short class, short func, short device) {
case 2: /* SFORM = Format */
case 5: /* SREAD = Read */
case 6: /* SWRITE = Write */
m2 = get16(dc[device].oar++);
m2 = get16r(dc[device].oar++, 0);
recsize = m & 017;
track = m1 & 01777;
rec = m2 >> 8; /* # records for format, rec # for R/W */
@@ -756,12 +759,12 @@ void devdisk (short class, short func, short device) {
}
if (crs[MODALS] & 020)
for (i=0; i<dmanw; i++)
put16(iobuf[i], dmaaddr+i);
put16r(iobuf[i], dmaaddr+i, 0);
} else {
if (crs[MODALS] & 020) {
iobufp = iobuf;
for (i=0; i<dmanw; i++)
iobuf[i] = get16(dmaaddr+i);
iobuf[i] = get16r(dmaaddr+i, 0);
} else
iobufp = mem+dmaaddr;
if (write(dc[device].unit[u].devfd, (char *)iobufp, dmanw*2) != dmanw*2) {
@@ -797,17 +800,21 @@ void devdisk (short class, short func, short device) {
case 7: /* DSTALL = Stall */
if (T_INST || T_DIO) fprintf(stderr," stall\n");
#if 1
devpoll[device] = instpermsec/5; /* 200 microseconds, sb 210 */
return;
#else
break;
#endif
case 9: /* DSTAT = Store status to memory */
if (T_INST || T_DIO) fprintf(stderr, " store status='%o to '%o\n", dc[device].status, m1);
put16(dc[device].status,m1);
put16r(dc[device].status,m1,0);
break;
case 11: /* DOAR = Store OAR to memory (2 words) */
if (T_INST || T_DIO) fprintf(stderr, " store OAR='%o to '%o\n", dc[device].oar, m1);
put16(dc[device].oar,m1);
put16r(dc[device].oar,m1,0);
break;
case 13: /* SDMA = select DMA channel(s) to use */