diff --git a/ea64v.h b/ea64v.h index 32a4d48..5e898a8 100644 --- a/ea64v.h +++ b/ea64v.h @@ -17,10 +17,7 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor unsigned short m; unsigned short rph,rpl; - if (crs[MODALS] & 4) /* segmentation enabled? */ - live = 010; /* yes, limit register traps */ - else - live = 040; + i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ /* rph/rpl (and earp) are usually = RPH/RPL in the register file, except for the case of an XEC instruction; in that case, these @@ -30,40 +27,12 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor rpl = earp & 0xFFFF; //TRACE(T_EAV, " inst=%o, rph=%o, rpl=%o\n", inst, rph, rpl); + if (crs[MODALS] & 4) /* segmentation enabled? */ + live = 010; /* yes, limit register traps */ + else + live = 040; + ea_s = rph; - - /* first check for direct short-form - the most commonly occurring case */ - - if ((inst & 0101000) == 0) { - ea_w = (inst & 0777); - if (x) { - TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, crs[X], *(short *)(crs+X)); - ea_w += crs[X]; - TRACE(T_EAV, " Postindex, new ea_w=%o\n", ea_w); - } - if (inst & 0400) { - TRACE(T_EAV, " Short LB relative, LB=%o/%o\n", crs[LBH], crs[LBL]); -#if 1 - ea_s = crs[LBH] | (ea_s & RINGMASK16); - ea_w += crs[LBL]; - return MAKEVA(ea_s, ea_w); -#else - ea_w += crs[LBL]; - return (((*(int *)(crs+LBH) | (earp & RINGMASK32)) & 0xFFFF0000) | ea_w); -#endif; - } - if (ea_w >= live) { - ea_s = crs[SBH] | (ea_s & RINGMASK16); - ea_w += crs[SBL]; - TRACE(T_EAV, " Short SB relative, SB=%o/%o\n", crs[SBH], crs[SBL]); - return MAKEVA(ea_s, ea_w); - } - TRACE(T_EAV, " Live register '%o\n", ea_w); - return 0x80000000 | ea_w; - } - - i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ - if (inst & 001000) /* sector bit 7 set? */ if ((inst & 0740) != 0400) { /* PC relative? */ ea_w = rpl + (((short) (inst << 7)) >> 7); /* yes, sign extend D */ @@ -81,7 +50,7 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor x = 0; } } else - fatal("goto labA?"); + goto labA; if (i) { if (ea_w < live) { @@ -106,11 +75,34 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor return 0x80000000 | ea_w; +labA: + ea_w = (inst & 0777); + if (x) { + TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, crs[X], *(short *)(crs+X)); + ea_w += crs[X]; + TRACE(T_EAV, " Postindex, new ea_w=%o\n", ea_w); + } + if ((inst & 0777) >= 0400) { + ea_s = crs[LBH] | (ea_s & RINGMASK16); + ea_w += crs[LBL]; + TRACE(T_EAV, " Short LB relative, LB=%o/%o\n", crs[LBH], crs[LBL]); + return MAKEVA(ea_s, ea_w); + } + if (ea_w >= live) { + ea_s = crs[SBH] | (ea_s & RINGMASK16); + ea_w += crs[SBL]; + TRACE(T_EAV, " Short SB relative, SB=%o/%o\n", crs[SBH], crs[SBL]); + return MAKEVA(ea_s, ea_w); + } + TRACE(T_EAV, " Live register '%o\n", ea_w); + return 0x80000000 | ea_w; + + /* here for long, 2-word, V-mode memory reference */ labB: a = iget16(RP); - INCRP; + RPL++; TRACE(T_EAV, " 2-word format, a=%o\n", a); y = (inst & 020); ixy = ((i != 0)<<2) | ((x != 0)<<1) | (y != 0); diff --git a/em.c b/em.c index c488950..5312c3e 100644 --- a/em.c +++ b/em.c @@ -449,6 +449,9 @@ static int memlimit; /* user's desired memory limit (-mem) */ DIAG cpu.pcl test 42 does check for segment wraparound, so -DFAST will cause this test to fail. + + Update: when cpuid=40 (6650), cpu.pcl test 42 *expects* 32-bit + increment on RP (segment gets incremented too)! */ #if FAST @@ -2042,118 +2045,14 @@ static ea_t pclea(unsigned short brsave[6], ea_t rp, unsigned short *bitarg, sho if (ea & 0x80000000) fault(POINTERFAULT, ea>>16, 0); /* XXX: faddr=0? */ iwea = ea; - ea = get32(iwea) | (RP & RINGMASK32); + ea = get32(iwea); TRACE(T_PCL, " Indirect pointer is %o/%o\n", ea>>16, ea & 0xFFFF); - - /* Case 35 wants a fault when the IP is 120000/0: - - #28307386 24000/27740: PCL 24000/30045 - ecb @ 24000/30045, access=7 - ecb.pb: 4000/30041 - ecb.framesize: 16 - ecb.stackroot 4000 - ecb.argdisp: 12 - ecb.nargs: 1 - ecb.lb: 4000/60000 - ecb.keys: 14000 - stack free pointer: 4000/70000, current ring=20000 - before update, stackfp=24000/70000, SB=0/0 - new SB=24000/70000 - new RP=24000/30041 - Entered ARGT - Transferring arg, 1 left, Y=12 - PCLAP ibr=4300, br=0, i=1, bit=0, store=1, lastarg=1, a=27117 - PCLAP ea = 24000/27117, bit=0 - Indirect pointer is 120000/0 - After indirect, PCLAP ea = 120000/0, bit=0 - Storing arg, 1 left, Y=12 - Stored - #29019968: fault '62, fcode=0, faddr=0/0, faultrp=24000/1356 - - [ Failure Report ] - - address instruction scope loop - 024000/027740 021410/030045 024000/027547 - - Actual: NO POINTER FAULT - Expected: POINTER FAULT - - But, Case 37 doesn't want a fault: - - #28891410 24000/30760: PCL 24000/31065 - ecb @ 24000/31065, access=7 - ecb.pb: 4000/31054 - ecb.framesize: 16 - ecb.stackroot 4000 - ecb.argdisp: 12 - ecb.nargs: 1 - ecb.lb: 4000/60000 - ecb.keys: 14000 - stack free pointer: 4000/70000, current ring=20000 - before update, stackfp=24000/70000, SB=0/0 - new SB=24000/70000 - new RP=24000/31054 - Entered ARGT - Transferring arg, 1 left, Y=12 - PCLAP ibr=4300, br=0, i=1, bit=0, store=1, lastarg=1, a=27117 - PCLAP ea = 24000/27117, bit=0 - Indirect pointer is 120000/0 - #28891410: fault '77, fcode=120000, faddr=24000/27117, faultrp=24000/30760 - - 0003 Unexpected POINTER fault. Returning to 030760 - - Changing <= to < in the ring comparison makes Case 37 work and Case 35 fail. - */ - -#if 0 - /* NOTE: this code causes every command to give a pointer fault: - - - #281037430 [SUPPCB 100100] SB: 6003/754 LB: 6/100112 PGMAPA XB: 6/100272 -6/100367: 11415 A='201/129 B='11/9 X=2/2 Y=20/16 C=0 L=0 LT=0 EQ=0 K=14000 M=100177 - opcode=00400, i=0, x=0 - 2-word format, a=22 - new opcode=00403, y=0, br=1, ixy=0, xok=1 - 2-word format, a=1142 - new opcode=01002, y=1, br=2, ixy=3, xok=1 - Long indirect, ea=60013/24350, ea_s=60013, ea_w=24350 - After indirect, ea_s=60013, ea_w=60422, bit=0 - EA: 60013/60422 MISSIN - PCL MISSIN - ecb @ 60013/60422, access=6 - ecb.pb: 13/60404 - ecb.framesize: 14 - ecb.stackroot 0 - ecb.argdisp: 12 - ecb.nargs: 1 - ecb.lb: 13/60022 - ecb.keys: 14000 - stack root in ecb was zero, stack root from caller is 6002 - stack free pointer: 6002/3770, current ring=3, new ring=3 - before update, stackfp=66002/3770, SB=66002/1434 - new SB=66002/3770 -Entering 64V mode, keys=14000 - new RP=60013/60404 -Entered ARGT - Transferring arg, 1 left, Y=12 - PCLAP ibr=4700, br=1, i=1, bit=0, store=1, lastarg=1, a=143 - PCLAP ea = 66002/1577, bit=0 - Indirect pointer is 160000/0 -fault '77, fcode=160000, faddr=66002/1577, faultrp=60013/60404 -fault: PX enabled, pcbp=65/100100, cs first=1026, next=1026, last=1064 -fault: updated cs next=1034 -Entering 64V mode, keys=14000 -fault: jumping to fault table entry at RP=60013/61212 - - */ - - if (ea & 0x80000000) - if ((ea & 0xFFFF0000) != 0x80000000) - if ((ea & 0x1FFF0000) || ((RP & RINGMASK32) <= (ea & RINGMASK32))) - fault(POINTERFAULT, ea>>16, iwea); -#else - if ((ea & 0x80000000) && (ea & 0x1FFF0000)) - fault(POINTERFAULT, ea>>16, iwea); +#if 1 + if (ea & 0x80000000) { + if (!*store || (ea & 0x8FFF0000) != 0x80000000) + fault(POINTERFAULT, ea>>16, iwea); + } else + ea |= (RP & RINGMASK32); /* weaken */ #endif bit = 0; if (ea & EXTMASK32) @@ -2161,26 +2060,17 @@ fault: jumping to fault table entry at RP=60013/61212 TRACE(T_PCL, " After indirect, PCLAP ea = %o/%o, bit=%d\n", ea>>16, ea & 0xFFFF, bit); } - if (!*store) { -#if 0 - /* Case 36 wants a pointer fault here... See Case 31, 34, 37 also */ - if (ea & 0x80000000) - if ((ea & 0xFFFF0000) != 0x80000000) - if ((ea & 0x1FFF0000) || ((RP & RINGMASK32) <= (ea & RINGMASK32))) - fault(POINTERFAULT, ea>>16, iwea); -#else - if (ea & 0x80000000) - fault(POINTERFAULT, ea>>16, iwea); -#endif - *(unsigned int *)(crs+XB) = ea; - crs[X] = bit; - } if (bit) { ea |= EXTMASK32; *bitarg = bit; - } else { + } else *bitarg = 0; + + if (!*store) { + *(unsigned int *)(crs+XB) = ea | (RP & RINGMASK32);; + crs[X] = bit; } + return ea; } @@ -2235,7 +2125,7 @@ static argt() { store = 1; advancepb = 0; } else { - ea = pclea(brsave, rp, &bit, &store, &lastarg) | (RP & RINGMASK32); + ea = pclea(brsave, rp, &bit, &store, &lastarg); advancepb = 1; } if (argsleft > 0 && store) { @@ -2349,20 +2239,11 @@ static pcl (ea_t ecbea) { ecb[8] = get16(ecbea+8); } - /* XXX: P400 docs say "no ring change takes place if not a - gate"; does that mean that if R0 calls a R3 ecb, it's - still in R0, or should it be weakened to the ecb ring? - (Case 24 of CPU.PCL indicates it should be weakened) */ - TRACE(T_PCL, " ecb.pb: %o/%o\n ecb.framesize: %d\n ecb.stackroot %o\n ecb.argdisp: %o\n ecb.nargs: %d\n ecb.lb: %o/%o\n ecb.keys: %o\n", ecb[0], ecb[1], ecb[2], ecb[3], ecb[4], ecb[5], ecb[6], ecb[7], ecb[8]); newrp = *(unsigned int *)(ecb+0); - if (access != 1) -#if 0 - newrp = (newrp & ~RINGMASK32) | (RP & RINGMASK32); /* no ring change */ -#else - newrp = newrp | (RP & RINGMASK32); /* Case 24 indicates to weaken ring */ -#endif + if (access != 1) /* not a gate, but weaken ring (outward calls) */ + newrp = newrp | (RP & RINGMASK32); /* setup stack frame NOTE: newrp must be used here so that accesses succeed when calling @@ -2373,17 +2254,7 @@ static pcl (ea_t ecbea) { stackrootseg = get16((*(unsigned int *)(crs+SB)) + 1); TRACE(T_PCL, " stack root in ecb was zero, stack root from caller is %o\n", stackrootseg); } -#if 0 - /* NOTE: higher revs of Primos establish stacks in segment zero - during coldstart and bomb if this check is enabled */ - if (stackrootseg == 0) - fatal("Stack base register root segment is zero"); -#endif stackfp = get32r(MAKEVA(stackrootseg,0), newrp); -#if 0 - if (stackfp == 0) - fatal("Stack free pointer is zero"); -#endif TRACE(T_PCL, " stack free pointer: %o/%o, current ring=%o, new ring=%o\n", stackfp>>16, stackfp&0xFFFF, (RPH&RINGMASK16)>>13, (newrp&RINGMASK32)>>29); stacksize = ecb[2]; @@ -2792,6 +2663,7 @@ static dispatcher() { printf("disp: rl bol=%o, != process dispatched=%o\n", rlbol, pcbw); fatal(NULL); } +#endif #if 0 /* NOTE: if a running process has its priority changed (in the pcb), this test fails, so it has been disabled */ @@ -2800,7 +2672,6 @@ static dispatcher() { printf("disp: dispatched process level=%o, != pla=%o\n", get16r0(pcbp+PCBLEV), regs.sym.pla); fatal(NULL); } -#endif #endif /* pcbp now points to the process we're going to run (pcbw is the @@ -4157,7 +4028,7 @@ For disk boots, the last 3 digits can be:\n\ fetch: #if 0 - if (gvp->instcount > 10300000) + if (gvp->instcount > 20500000) gvp->savetraceflags = ~0; #endif @@ -4574,7 +4445,7 @@ d_tka: /* 001005 */ d_tak: /* 001015 */ TRACE(T_FLOW, " TAK\n"); - newkeys(crs[A] & 0177774); + newkeys(crs[A] & 0177770); goto fetch; d_nop: /* 000001 */ @@ -5690,7 +5561,7 @@ d_bdy: /* 0140724 */ d_bdx: /* 0140734 */ TRACE(T_FLOW, " BDX\n"); crs[X]--; -#if 0 +#if 1 m = iget16(RP); if (crs[X] > 100 && m == RPL-1) { struct timeval tv0,tv1; @@ -8178,8 +8049,7 @@ imode: case 1: imodepcl: stopwatch_push(&sw_pcl); - TRACE(T_FLOW|T_PCL, " PCL %s\n", searchloadmap(ea, 'e')); - //TRACE(T_FLOW|T_PCL, "#%d %o/%o: PCL %o/%o\n", gvp->instcount, RPH, RPL-2, ea>>16, ea&0xFFFF); + TRACE(T_FLOW|T_PCL, "#%d %o/%o: PCL %o/%o %s\n", gvp->instcount, RPH, RPL-2, ea>>16, ea&0xFFFF, searchloadmap(ea, 'e')); if (gvp->numtraceprocs > 0 && TRACEUSER) for (i=0; inumtraceprocs; i++) if (traceprocs[i].ecb == (ea & 0xFFFFFFF) && traceprocs[i].sb == -1) { diff --git a/emdev.h b/emdev.h index f59c984..5205593 100644 --- a/emdev.h +++ b/emdev.h @@ -1646,12 +1646,6 @@ int devdisk (int class, int func, int device) { unsigned char *hashp; int lockkey; - /* NOTE: this iobuf size looks suspicious; probably should be 1040 words, - the largest disk record size, and there probably should be some checks - that no individual DMA exceeds this size, that no individual disk - read or write exceeds 1040 words. Maybe it's 4096 bytes because this - is the largest DMA transfer request size... */ - unsigned short iobuf[1040]; /* local I/O buf (for mapped I/O) */ unsigned short *iobufp; unsigned short access; @@ -1807,13 +1801,21 @@ int devdisk (int class, int func, int device) { dc[device].status |= 02000; /* header check (right error?) */ break; } +#if 0 + /* this has been disabled because preseeks in the disk driver sometimes + goof up, depending on timings in the emulator */ + if (track != dc[device].unit[u].curtrack) { fprintf(stderr," Device '%o, order %d at track %d, but positioned to track %d\n", device, order, track, dc[device].unit[u].curtrack); -#if 0 dc[device].status |= 4; /* illegal seek */ break; -#endif } +#endif + if (track > dc[device].unit[u].maxtrack) { + fprintf(stderr," Device '%o, unit %d, seek to track %d > cylinder limit of %d\n", device, u, track, dc[device].unit[u].maxtrack); + fatal("Invalid seek"); + } + /* XXX: could check for head > max head on drive here... */ if (dc[device].unit[u].devfd == -1) { TRACE(T_INST|T_DIO, " Device '%o unit %d not ready\n", device, u); @@ -1937,12 +1939,16 @@ int devdisk (int class, int func, int device) { track = m1 & 03777; } TRACE(T_INST|T_DIO, " seek track %d, restore=%d, clear=%d\n", track, (m1 & 0100000) != 0, (m1 & 040000) != 0); +#if 0 + /* this has been disabled because SCSI drives sometimes seek to + track 512 (special meaning in controller?) */ + if (track > dc[device].unit[u].maxtrack) { fprintf(stderr," Device '%o, unit %d, seek to track %d > cylinder limit of %d\n", device, u, track, dc[device].unit[u].maxtrack); dc[device].status |= 4; /* set bit 14: seek error */ track = -1; } -# +#endif dc[device].unit[u].curtrack = track; break;