From fdb4d4ae4cf90a2809cff645be7a08bc270a22b9 Mon Sep 17 00:00:00 2001 From: Jim Date: Sun, 2 Sep 2007 00:00:00 -0400 Subject: [PATCH] New ea64v, missing memory check, #ifdef FAST --- ea64v.h | 70 ++++++++++++++++++++++------------------ em.c | 99 ++++++++++++++++++++++++++++++++++++++++++--------------- regs.h | 28 ++++++++-------- 3 files changed, 127 insertions(+), 70 deletions(-) diff --git a/ea64v.h b/ea64v.h index 5e898a8..32a4d48 100644 --- a/ea64v.h +++ b/ea64v.h @@ -17,7 +17,10 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor unsigned short m; unsigned short rph,rpl; - i = inst & 0100000; /* indirect is bit 1 (left/MS bit) */ + if (crs[MODALS] & 4) /* segmentation enabled? */ + live = 010; /* yes, limit register traps */ + else + live = 040; /* rph/rpl (and earp) are usually = RPH/RPL in the register file, except for the case of an XEC instruction; in that case, these @@ -27,12 +30,40 @@ 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 */ @@ -50,7 +81,7 @@ static inline ea_t ea64v (ea_t earp, unsigned short inst, short x, unsigned shor x = 0; } } else - goto labA; + fatal("goto labA?"); if (i) { if (ea_w < live) { @@ -75,34 +106,11 @@ 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); - RPL++; + INCRP; 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 5312c3e..d430c8e 100644 --- a/em.c +++ b/em.c @@ -98,6 +98,7 @@ OK: #include #include #include +#include /* In SR modes, Prime CPU registers are mapped to memory locations 0-'37, but only 0-7 are user accessible. In the post-P300 @@ -121,6 +122,7 @@ typedef unsigned int pa_t; /* physical address */ static void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) __attribute__ ((noreturn)); static void fatal(char *msg) __attribute__ ((noreturn)); +static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int dswstat, unsigned int dswrma) __attribute__ ((noreturn)); /* condition code macros */ @@ -454,7 +456,7 @@ static int memlimit; /* user's desired memory limit (-mem) */ increment on RP (segment gets incremented too)! */ -#if FAST +#ifdef FAST #define RPADD(n) (RP+n) #define INCRP RP++ #else @@ -777,17 +779,23 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { pa = (stlbp->ppn << 10) | (ea & 0x3FF); TRACE(T_MAP," for ea %o/%o, stlbix=%d, pa=%o loaded at #%d\n", ea>>16, ea&0xffff, stlbix, pa, stlbp->load_ic); } else { - /* XXX: this test looks bogus and should be removed, but causes boot failures related to disk I/O if removed */ - pa = ea & (MEMSIZE-1); + pa = ea; } stopwatch_pop(&sw_mapva); -#if DBG +#ifndef FAST if (pa < memlimit) #endif return pa; - printf(" map: Memory address '%o (%o/%o) is out of range 0-'%o!\n", ea, ea>>16, ea & 0xffff, memlimit-1); - fatal(NULL); - /* NOTE: could also take a missing memory check here... */ +#if DBG + printf(" map: Memory address '%o (%o/%o) is out of range 0-'%o (%o/%o) at #%d!\n", pa, pa>>16, pa & 0xffff, memlimit-1, (memlimit-1)>>16, (memlimit-1) & 0xffff, gvp->instcount); +#endif + + /* take a missing memory check + XXX: not sure if dswstat and dswrma are right, but Primos doesn't + seem to look at them for this check */ + + macheck(071, 0310, 0xd000, pa); + fatal("Return from macheck"); } /* for I/O, ea is either an 18-bit physical address (which is just @@ -810,6 +818,7 @@ static unsigned int mapio(ea_t ea) { return ea; } + /* these are I/O versions of get/put that use the IOTLB rather than the STLB */ @@ -1147,6 +1156,39 @@ static put64r(long long value, ea_t ea, ea_t rpring) { } } +/* machine check handler, called with check vector locations + The first arg is used when PX is disabled, the 2nd when PX is enabled. */ + +void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int dswstat, unsigned int dswrma) { + unsigned short m; + + /* set check registers in the register file */ + + regs.sym.dswpb = RP; + regs.sym.dswstat = dswstat; + regs.sym.dswrma = dswrma; + + /* if process exchange is enabled, follow the standard check protocol; + if PX not enabled, simulate JST p300vec,* to invoke the check. + Then longjmp back to the fetch loop */ + + if (crs[MODALS] & 010) { + printf(" map: missing memory while PX enabled\n"); + } else { + m = get16(p300vec); + put16(RPL, m); + RP = m+1; + } + + /* similar code in the fault handler */ + + grp = RP; + gcrsl = crsl; + longjmp(jmpbuf, 1); + fatal("macheck: returned after longjmp\n"); +} + + static warn(char *msg) { printf("emulator warning:\n instruction #%d at %o/%o: %o %o keys=%o, modals=%o\n %s\n", gvp->instcount, gvp->prevpc >> 16, gvp->prevpc & 0xFFFF, get16(gvp->prevpc), get16(gvp->prevpc+1),crs[KEYS], crs[MODALS], msg); } @@ -1517,7 +1559,8 @@ static void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { } } - /* on longjmp, register globals are reset (PPC); save them before jumping */ + /* on longjmp, register globals are reset (PPC); save them before jumping + See also macheck */ grp = RP; gcrsl = crsl; @@ -2301,7 +2344,7 @@ static pcl (ea_t ecbea) { /* load new execution state from ecb */ TRACE(T_PCL, " before update, stackfp=%o/%o, SB=%o/%o\n", stackfp>>16, stackfp&0xFFFF, crs[SBH], crs[SBL]); - if (access == 1) + if (access == 1) /* for gate access, don't weaken ring */ *(unsigned int *)(crs+SB) = stackfp; else *(unsigned int *)(crs+SB) = (stackfp & ~RINGMASK32) | (RP & RINGMASK32); @@ -2311,12 +2354,16 @@ static pcl (ea_t ecbea) { /* update the stack free pointer; this has to wait until after all memory accesses, in case of stack page faults (PCL restarts). + Some ucode versions incorrectly store the ring in the free - pointer if the extension pointer was followed. Set EHDB to - suppress this spurious DIAG error. */ + pointer if the extension pointer was followed. Try setting EHDB + to suppress this spurious DIAG error. */ ea = MAKEVA(stackrootseg,0) | (newrp & RINGMASK32); - put32r((stackfp+stacksize) & ~RINGMASK32, ea, newrp); + if (cpuid == 15) + put32r(stackfp+stacksize, ea, newrp); + else + put32r((stackfp+stacksize) & ~RINGMASK32, ea, newrp); /* transfer arguments if arguments are expected. There is no documentation explaining how the Y register is used during @@ -3727,6 +3774,7 @@ main (int argc, char **argv) { fatal("-cpuid arg range is 0 to 44\n"); } else fatal("-cpuid needs an argument\n"); +#ifndef FAST } else if (strcmp(argv[i],"-mem") == 0) { if (i+1 < argc && argv[i+1][0] != '-') { sscanf(argv[++i],"%d", &templ); @@ -3736,6 +3784,7 @@ main (int argc, char **argv) { fatal("-mem arg range is 1 to 1024 (megabytes)\n"); } else fatal("-mem needs an argument\n"); +#endif } else if (strcmp(argv[i],"-tport") == 0) { if (i+1 < argc && argv[i+1][0] != '-') { sscanf(argv[++i],"%d", &templ); @@ -4028,7 +4077,7 @@ For disk boots, the last 3 digits can be:\n\ fetch: #if 0 - if (gvp->instcount > 20500000) + if (gvp->instcount > 32727500) gvp->savetraceflags = ~0; #endif @@ -5561,7 +5610,7 @@ d_bdy: /* 0140724 */ d_bdx: /* 0140734 */ TRACE(T_FLOW, " BDX\n"); crs[X]--; -#if 1 +#if 0 m = iget16(RP); if (crs[X] > 100 && m == RPL-1) { struct timeval tv0,tv1; @@ -8610,7 +8659,17 @@ nonimode: stopwatch_push(&sw_cas); m = get16t(ea); TRACE(T_FLOW, " CAS ='%o/%d\n", m, *(short *)&m); -#if 1 +#ifdef FAST + CLEARCC; + if (crs[A] == m) { + INCRP; + SETEQ; + } else if (*(short *)(crs+A) < *(short *)&m) { + RPL += 2; + SETLT; + } + XSETL(0); +#else crs[KEYS] &= ~020300; /* clear L, and CC */ utempa = crs[A]; utempl = crs[A]; @@ -8631,16 +8690,6 @@ nonimode: INCRP; else if (*(short *)(crs+A) < *(short *)&m) RPL += 2; -#else - CLEARCC; - if (crs[A] == m) { - INCRP; - SETEQ; - } else if (*(short *)(crs+A) < *(short *)&m) { - RPL += 2; - SETLT; - } - XSETL(0); #endif stopwatch_pop(&sw_cas); goto fetch; diff --git a/regs.h b/regs.h index 5a5c616..398aba7 100644 --- a/regs.h +++ b/regs.h @@ -104,20 +104,20 @@ static union { /* symbolic register file locations */ struct { - unsigned int tr0,tr1,tr2,tr3,tr4,tr5,tr6,tr7; - unsigned int rdmx1,rdmx2; - unsigned short rdum1[1],ratmpl; - unsigned int rsgt1,rsgt2,recc1,recc2; - unsigned short rdum2[1],reoiv,zero,one; - unsigned int pbsave,rdmx3,rdmx4,c377,rdum3[3]; - unsigned int pswpb; - unsigned short pswkeys,rdum4[1]; - unsigned short pla,pcba,plb,pcbb; - unsigned int dswrma; - unsigned int dswstat; - unsigned int dswpb,rsavptr; - unsigned short regdmx[64]; - unsigned int userregs[REGSETS-2][32]; + unsigned int tr0,tr1,tr2,tr3,tr4,tr5,tr6,tr7; /* '0-7 */ + unsigned int rdmx1,rdmx2; /* '10-11 */ + unsigned short rdum1[1],ratmpl; /* '12 */ + unsigned int rsgt1,rsgt2,recc1,recc2; /* '13-16 */ + unsigned short rdum2[1],reoiv,zero,one; /* '17-20 */ + unsigned int pbsave,rdmx3,rdmx4,c377,rdum3[3]; /* '21-27 */ + unsigned int pswpb; /* '30 */ + unsigned short pswkeys,rdum4[1]; /* '31 */ + unsigned short pla,pcba,plb,pcbb; /* '32-33 */ + unsigned int dswrma; /* '34 */ + unsigned int dswstat; /* '35 */ + unsigned int dswpb,rsavptr; /* '36-37 */ + unsigned short regdmx[64]; /* '40-77 */ + unsigned int userregs[REGSETS-2][32]; /* '100- */ } sym; } regs;