diff --git a/em.c b/em.c index 6a2afd0..11a6f11 100644 --- a/em.c +++ b/em.c @@ -126,6 +126,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 warn(char *msg); static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int dswstat, unsigned int dswrma) __attribute__ ((noreturn)); /* condition code macros */ @@ -225,8 +226,6 @@ static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int #define BCGE if (!(crs[KEYS] & 0200)) RPL = iget16(RP); else INCRP #define BCGT if (!(crs[KEYS] & 0300)) RPL = iget16(RP); else INCRP #define BLS if (crs[KEYS] & 020000) RPL = iget16(RP); else INCRP -#define BXNE if (crs[X] != 0) RPL = iget16(RP); else INCRP -#define BYNE if (crs[Y] != 0) RPL = iget16(RP); else INCRP #define BHNE(r) if (crs[(r)*2] != 0) RPL = iget16(RP); else INCRP #define BRNE(r) if (crsl[(r)] != 0) RPL = iget16(RP); else INCRP @@ -329,9 +328,13 @@ static struct { static unsigned short sswitch = 014114; /* sense switches, set with -ss & -boot */ -/* NOTE: the default cpuid is a P750: 1 MIPS, 8MB of memory */ +/* NOTE: the default cpuid is a P750: 1 MIPS, 8MB of memory -static unsigned short cpuid = 5; /* STPM CPU model, set with -cpuid */ + 9/21/2007: changed the default to a P9950 so that the date gets + automagically set via special VCP commands. The 9950 was a 2 MIP + CPU w/max of 16MB physical memory via the extended page map format */ + +static unsigned short cpuid = 15; /* STPM CPU model, set with -cpuid */ /* STLB cache structure is defined here; the actual stlb is in gv. There are several different styles on Prime models. This is @@ -340,8 +343,9 @@ static unsigned short cpuid = 5; /* STPM CPU model, set with -cpuid * user. Instead of using a valid/invalid bit, a segment number of 0xFFFF - means "invalid", since it won't match any real segment number. - This eliminates testing the valid bit in mapva. + (note that the fault, ring, and E bits are set) means "invalid", + since it won't match any 12-bit segment number. This eliminates + testing the valid bit in mapva. As a speed-up, the unmodified bit is stored in access[2], where Ring 2 access should be kept. This makes the structure exactly 16 @@ -355,7 +359,7 @@ static unsigned short cpuid = 5; /* STPM CPU model, set with -cpuid * typedef struct { unsigned short *pmep; /* pointer to page table flag word */ - unsigned int ppn; /* physical page number */ + unsigned int ppa; /* physical page address (PPN << 10) */ unsigned short procid; /* process id for segments >= '4000 */ short seg; /* segment number (0-0xFFF), 0xFFFF = invalid */ char access[4]; /* ring n access rights */ @@ -372,7 +376,7 @@ typedef struct { #define IOTLBENTS 64*4 typedef struct { - unsigned int ppn; /* physical page number */ + unsigned int ppa; /* physical page address (PPN << 10) */ char valid; /* 1 if IOTLB entry is valid, zero otherwise */ } iotlbe_t; @@ -427,7 +431,7 @@ typedef struct { PCL and PRTN when the ring might change). Storing the access bits in the vpn allows use of of the brp - supercache for write accesses as well as read accesses. */ + cache for write accesses as well as read accesses. */ typedef struct { unsigned short *memp; /* MEM[] physical page address */ @@ -551,10 +555,10 @@ static unsigned short physmem[MEMSIZE]; /* system's physical memory */ */ #ifdef FAST -#define RPADD(n) (RP+n) +#define RPADD(n) (RP+(n)) #define INCRP RP++ #else -#define RPADD(n) MAKEVA(RPH,RPL+n) +#define RPADD(n) MAKEVA(RPH,RPL+(n)) #define INCRP RPL++ #endif @@ -811,7 +815,7 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { short relseg,seg,nsegs,ring; unsigned short pte, stlbix, iotlbix; stlbe_t *stlbp; - unsigned int dtar,sdw,staddr,ptaddr,pmaddr,ppn; + unsigned int dtar,sdw,staddr,ptaddr,pmaddr,ppa; pa_t pa; stopwatch_push(&sw_mapva); @@ -856,18 +860,19 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { pmaddr = ptaddr + 2*PAGENO(ea); pte = MEM[pmaddr]; - /* this is probably correct (don't have any references) for - the 53xx and later machines that support more than 128MB of - physical memory, but it can't be used for earlier machines - like the 9950 or they can't run older software (rev 19 for - example). Need to have a mask for each CPU type to make it - technically correct. */ + /* this line enables 512MB on the 53xx and later machines that + support more than 128MB of physical memory. The pmap32mask + is cpu-dependant: older machines like the 9950 looked at + fewer bits, and the older software like Primos rev 19 had + other stuff in the higher-order bits that the hardware + ignored. So on older machines, we need to ignore them + too, so older software still works. */ - ppn = ((MEM[pmaddr] & gvp->pmap32mask) << 16) | MEM[pmaddr+1]; + ppa = (*(unsigned int *)(MEM+pmaddr) & gvp->pmap32mask) << 10; } else { pmaddr = ptaddr + PAGENO(ea); pte = MEM[pmaddr]; - ppn = pte & 0xFFF; + ppa = (pte & 0xFFF) << 10; } TRACE(T_MAP," ptaddr=%o, pmaddr=%o, pte=%o\n", ptaddr, pmaddr, pte); if (!(pte & 0x8000)) @@ -879,7 +884,7 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { stlbp->access[3] = (sdw >> 6) & 7; stlbp->procid = crs[OWNERL]; stlbp->seg = seg; - stlbp->ppn = ppn; + stlbp->ppa = ppa; stlbp->pmep = MEM+pmaddr; #ifndef NOTRACE stlbp->load_ic = gvp->instcount; @@ -894,9 +899,14 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { if (seg < 4) { iotlbix = (ea & 0x3FFFF) >> 10; gvp->iotlb[iotlbix].valid = 1; - gvp->iotlb[iotlbix].ppn = ppn; + gvp->iotlb[iotlbix].ppa = ppa; } } +#if 0 + /* seems like ea ring should always be = rp ring, but not true */ + if ((rp & RINGMASK32) != (ea & RINGMASK32)) + warn("rp ring <> ea ring!"); +#endif ring = ((rp | ea) >> 29) & 3; /* current ring | ea ring = access ring */ *access = stlbp->access[ring]; if (((intacc & *access) != intacc) || (intacc == PACC && ((*access & 3) == 0))) @@ -905,7 +915,7 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { stlbp->access[STLB_UNMODIFIED_BIT] = 0; *(stlbp->pmep) &= ~020000; /* reset unmodified bit in memory */ } - pa = (stlbp->ppn << 10) | (ea & 0x3FF); + pa = stlbp->ppa | (ea & 0x3FF); TRACE(T_MAP," for ea %o/%o, iacc=%d, stlbix=%d, pa=%o loaded at #%d\n", ea>>16, ea&0xffff, intacc, stlbix, pa, stlbp->load_ic); } else { pa = ea; @@ -928,6 +938,9 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) { } #if 0 +/* NOTE: this is ifdef'd out because it slowed things down (it was a + precursor to the brp cache, which worked much better */ + /* Use fastmap only when intacc = RACC or WACC, ie, get/put, not PACC!): (pa_t) pa = fastmap(ea, intacc, rp); @@ -955,7 +968,7 @@ static pa_t fastmap (ea_t ea, ea_t rp, short intacc) { stlbp->unmodified = 0; *(stlbp->pmep) &= ~020000; /* reset unmodified bit in memory */ } - return ((stlbp->ppn << 10) | (ea & 0x3FF)); + return (stlbp->ppa | (ea & 0x3FF)); } } return mapva(ea, rp, intacc, &access); @@ -975,7 +988,7 @@ const static unsigned int mapio(ea_t ea) { if (crs[MODALS] & 020) { /* mapped I/O mode? */ iotlbix = (ea >> 10) & 0xFF; /* TLB range is 0-255 */ if (gvp->iotlb[iotlbix].valid) - return (gvp->iotlb[iotlbix].ppn << 10) | (ea & 0x3FF); + return gvp->iotlb[iotlbix].ppa | (ea & 0x3FF); else { printf("Mapped I/O request to %o/%o, but IOTLB is invalid!\n", ea>>16, ea&0xFFFF); fatal(NULL); @@ -1010,14 +1023,15 @@ const static unsigned int mapio(ea_t ea) { /* get16 handles 16-bit fetches that CANNOT cause address traps. - get16t handles 16-bit fetches that MIGHT cause address traps. - These traps can occur: + get16t handles 16-bit fetches that MIGHT cause address traps, + indicated by the sign bit set in EA. + Address traps can occur: - fetching S/R mode instructions - fetching V-mode instructions when RPL < 010 or 040 (seg enabled/not) - in any S/R mode memory reference or address calculation - in V-mode address calculations (16-bit indirects) - in V-mode short instruction execution (LDA# 0 for example) - These traps CANNOT occur: + Address traps CANNOT occur: - in I-mode - in V-mode long instruction address calculation or execution @@ -1027,7 +1041,9 @@ const static unsigned int mapio(ea_t ea) { (only the ring part is used from this address). VERY IMPORTANT: get16r _cannot_ use the supercache! You don't want to - cache Ring 0 accesses to data, then let Ring 3 use the cache! + cache Ring 0 accesses to data, then let Ring 3 use the cache! It could + be changed to use a special R0 brp cache entry, but probably not much + gain performance-wise. Might speed up process exchange... */ @@ -1051,7 +1067,7 @@ static inline unsigned short get16(ea_t ea) { gvp->supercalls++; #endif if ((ea & 0x0FFFFC00) == (eap->vpn & 0x0FFFFFFF)) { - TRACE(T_MAP, " get16: supercached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); + TRACE(T_MAP, " get16: cached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); return eap->memp[ea & 0x3FF]; } else { #ifndef NOTRACE @@ -1104,7 +1120,7 @@ static unsigned short get16r(ea_t ea, ea_t rpring) { PCL uses "r" versions of get/put because it may be crossing rings. However, if PCL isn't crossing rings (user calls his own subroutine for example), then the if below will try to use the - brp supercache. */ + brp cache. */ if (((rpring ^ RP) & RINGMASK32) == 0) return get16(ea); @@ -1134,7 +1150,7 @@ static unsigned int get32m(ea_t ea) { return (get16(ea) << 16) | get16(INCVA(ea,1)); } -/* get32 tries to use the supercache and is inlined */ +/* get32 tries to use the cache and is inlined */ static inline unsigned int get32(ea_t ea) { pa_t pa; @@ -1150,7 +1166,7 @@ static inline unsigned int get32(ea_t ea) { #endif if ((ea & 01777) <= 01776) if ((ea & 0x0FFFFC00) == (eap->vpn & 0x0FFFFFFF)) { - TRACE(T_MAP, " get32: supercached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); + TRACE(T_MAP, " get32: cached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); return *(unsigned int *)&eap->memp[ea & 0x3FF]; } return get32m(ea); @@ -1296,11 +1312,11 @@ static inline put16(unsigned short value, ea_t ea) { gvp->supercalls++; #endif - /* access bits are stored in bits 2-4 of the supercache vpn. + /* access bits are stored in bits 2-4 of the cache vpn. write access is indicated by bit 4 (MSB = bit 1) */ if ((ea & 0x0FFFFC00) == (eap->vpn & 0x0FFFFFFF) && (eap->vpn & 0x10000000)) { - TRACE(T_MAP, " put16: supercached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); + TRACE(T_MAP, " put16: cached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); eap->memp[ea & 0x3FF] = value; } else { #ifndef NOTRACE @@ -1385,7 +1401,7 @@ static put32(unsigned int value, ea_t ea) { #endif if ((ea & 01777) <= 01776) { if ((ea & 0x0FFFFC00) == (eap->vpn & 0x0FFFFFFF) && (eap->vpn & 0x10000000)) { - TRACE(T_MAP, " put32: supercached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); + TRACE(T_MAP, " put32: cached %o/%o [%s]\n", ea>>16, ea&0xFFFF, brp_name()); *(unsigned int *)&eap->memp[ea & 0x3FF] = value; } else { #ifndef NOTRACE @@ -1493,11 +1509,6 @@ void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int dswsta } -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); -} - - /* queue instructions NOTE: ABQ is typically used in software to add an item to a @@ -1658,6 +1669,11 @@ static int (*devmap[64])(int, int, int) = { +static void 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); +} + + static void fatal(char *msg) { ea_t pcbp, csea; unsigned short first,next,last,this; @@ -1678,6 +1694,8 @@ static void fatal(char *msg) { stopwatch_report(&sw_pcl); stopwatch_report(&sw_idle); + /* XXX: need to log this stuff... */ + printf("Fatal error"); if (msg) printf(": %s", msg); @@ -1747,9 +1765,9 @@ static newkeys (unsigned short new) { TRACE(T_MODE, "Entering 64V mode, keys=%o\n", new); gvp->amask = 0177777; break; - default: /* invalid */ - printf("Invalid CPU mode: %o\n", new); - fatal(NULL); + default: /* invalid mode */ + warn("Invalid CPU mode"); + fault(ILLINSTFAULT, RPL, RP); } crs[KEYS] = new; } @@ -2333,7 +2351,7 @@ static ea_t stex(unsigned int extsize) { PRTN can be restarted. After all the temps are loaded, the stack free pointer can be updated since no further faults can occur. - If changing rings, make sure to invalidate the brp supercache. */ + If changing rings, make sure to invalidate the brp cache. */ static inline void prtn() { unsigned short stackrootseg; @@ -2979,7 +2997,7 @@ static ors(unsigned short pcbw) { gvp->savetraceflags = ~0; #endif - /* invalidate the mapva translation supercache */ + /* invalidate the mapva translation cache */ invalidate_brp(); } @@ -3469,39 +3487,33 @@ static lpsw() { TRACE(T_PX, "LPSW: crs=%d, ownerl[2]=%o, keys[2]=%o, modals[2]=%o, ownerl[3]=%o, keys[3]=%o, modals[3]=%o\n", crs==regs.rs16[2]? 2:3, regs.rs16[2][OWNERL], regs.rs16[2][KEYS], regs.rs16[2][MODALS], regs.rs16[3][OWNERL], regs.rs16[3][KEYS], regs.rs16[3][MODALS]); } } -#if 0 - /* XXX: hack to disable serial number checking if a cpuid > 4 is used. - This code is very rev and/or build dependent; this is for 23.4. - Look for ERA/ANA sequence after SSSN, set the ANA operand to zero. */ - - ea = MAKEVA(014,040747); - printf("Current value of 14/40747 is: %o\n", get16(ea)); - put16(0,ea); - - /* patch SBL instruction to clear L instead */ - ea = MAKEVA(014,020104); - printf("Current value of 14/20104 is: %o\n", get16(ea)); - put16(0140010, ea); - put16(0140010, ea+1); -#endif } static sssn() { +#if 1 + static char snbuf[] = "FN 123456 "; /* dummy serial number for DIAG */ +#else + static char snbuf[] = "FN 018554 "; /* Doug's serial number */ +#endif ea_t ea; int i; - printf("SSSN @ %o/%o\n", RPH, RPL); - /* gvp->savetraceflags = traceflags = ~TB_MAP; /*****/ + //printf("SSSN @ %o/%o\n", RPH, RPL); + //gvp->savetraceflags = gvp->traceflags = ~TB_MAP; /*****/ TRACE(T_FLOW, " SSSN\n"); -#if 1 ea = *(unsigned int *)(crs+XB); - for (i=0; i<16; i++) { + for (i=0; i<8; i++) + put16(*(((unsigned short *)snbuf)+i), ea+i); + for (i=8; i<16; i++) { put16(0, ea+i); } -#else - fault(UIIFAULT, RPL, RP); -#endif + + /* if SSSN is from segment 14, it's probably the rev 23.4.Y2K + system serial number check. Bypass the check loop. */ + + if (RPH == 014) + RP += 12; } @@ -4110,7 +4122,6 @@ main (int argc, char **argv) { bootarg = NULL; bootfile[0] = 0; gvp->pmap32bits = 0; - gvp->pmap32mask = 0; gvp->csoffset = 0; gvp->memlimit = MEMSIZE; tport = 0; @@ -4270,10 +4281,13 @@ main (int argc, char **argv) { /* set some vars after the options have been read */ - if (cpuid == 15 || cpuid == 18 || cpuid == 19 || cpuid == 24 || cpuid >= 26) + if (cpuid == 15 || cpuid == 18 || cpuid == 19 || cpuid == 24 || cpuid >= 26) { gvp->pmap32bits = 1; - if (cpuid == 33 || cpuid == 37 || cpuid == 39 || cpuid >= 43) - gvp->pmap32mask = 0x3; + if (cpuid == 33 || cpuid == 37 || cpuid == 39 || cpuid >= 43) + gvp->pmap32mask = 0x3FFFF; /* this is for 512MB physical memory */ + else + gvp->pmap32mask = 0xFFFF; /* this is for 128MB physical memory */ + } if ((26 <= cpuid && cpuid <= 29) || cpuid >= 35) gvp->csoffset = 1; @@ -4324,8 +4338,10 @@ main (int argc, char **argv) { rvec[1] = rvec[0]+1040-1; /* read 1 disk block */ /* setup DMA register '20 (address only) for the next boot record */ regs.sym.regdmx[041] = 03000; - if (globdisk(bootfile, sizeof(bootfile), bootctrl, bootunit) != 0) - fatal("Can't find disk boot device file"); + if (globdisk(bootfile, sizeof(bootfile), bootctrl, bootunit) != 0) { + printf("Can't find disk boot device file %s, or multiple files match this device", bootfile); + fatal(NULL); + } } else if ((sswitch & 0x7) == 5) { /* tape boot */ bootctrl = 014; @@ -4362,7 +4378,7 @@ For disk boots, the last 3 digits can be:\n\ exit(1); } - TRACEA("Boot file is %s\n", bootfile); + printf("Booting from file %s\n", bootfile); if ((bootfd=open(bootfile, O_RDONLY)) == -1) { perror("Error opening boot device file"); fatal(NULL); @@ -4603,13 +4619,13 @@ fetch: } else { /* standard interrupt mode */ m = get16(063); - printf("Standard mode interrupt vector loc = %o\n", m); + //printf("Standard mode interrupt vector loc = %o\n", m); //gvp->traceflags = ~TB_MAP; if (m != 0) { put16(RPL, m); RP = m+1; } else { - fatal("fetch: loc '63 = 0 in standard interrupt mode"); + fatal("em: loc '63 = 0 when standard mode interrupt occurred"); } } crs[MODALS] &= 077777; /* inhibit interrupts */ @@ -4746,13 +4762,7 @@ xec: d_iab: /* 000201 */ TRACE(T_FLOW, " IAB\n"); -#ifdef FAST crsl[GR2] = (crsl[GR2] << 16) | (crsl[GR2] >> 16); -#else - utempa = crs[B]; - crs[B] = crs[A]; - crs[A] = utempa; -#endif goto fetch; d_cgt: /* 001314 */ @@ -5578,7 +5588,7 @@ d_ptlb: /* 000064 */ RESTRICT(); utempl = *(unsigned int *)(crs+L); for (utempa = 0; utempa < STLBENTS; utempa++) - if ((utempl & 0x80000000) || gvp->stlb[utempa].ppn == utempl) + if ((utempl & 0x80000000) || gvp->stlb[utempa].ppa == (utempl << 10)) gvp->stlb[utempa].seg = 0xFFFF; goto fetch; @@ -5643,6 +5653,12 @@ d_dbgill: /* 001700, 001701 */ LDA modals get modals SAS 1 interrupts enabled? 1702 no, they should be, die + + Update: this is the "slow halt" instruction. Ewan explained + that if a HLT instruction is encountered, any DMX in progress + will stop, leading to partial disk records being written. + Using this instruction instead lets Primos delay the halt + until DMX has completed. */ d_pbug: /* 001702 */ @@ -6042,25 +6058,30 @@ d_bfgt: /* 0141611 */ d_bix: /* 0141334 */ TRACE(T_FLOW, " BIX\n"); - crs[X]++; - BXNE; + if ((short)(++crs[X]) != 0) + RPL = iget16(RP); + else + INCRP; goto fetch; d_biy: /* 0141324 */ TRACE(T_FLOW, " BIY\n"); - crs[Y]++; - BYNE; + if ((short)(++crs[Y]) != 0) + RPL = iget16(RP); + else + INCRP; goto fetch; d_bdy: /* 0140724 */ TRACE(T_FLOW, " BDY\n"); - crs[Y]--; - BYNE; + if ((short)(--crs[Y]) != 0) + RPL = iget16(RP); + else + INCRP; goto fetch; d_bdx: /* 0140734 */ TRACE(T_FLOW, " BDX\n"); - crs[X]--; #ifndef NOIDLE m = iget16(RP); if (crs[X] > 100 && m == RPL-1) { @@ -6109,7 +6130,7 @@ d_bdx: /* 0140734 */ for (i=0; i<64; i++) if (devpoll[i] > 0) devpoll[i] -= utempl; - crs[X] = 0; + crs[X] = 1; /* decremented below */ utempa = crs[TIMER]; if (actualmsec > 0) { crs[TIMER] += actualmsec; @@ -6126,7 +6147,10 @@ d_bdx: /* 0140734 */ stopwatch_stop(&sw_idle); } #endif - BXNE; + if ((short)(--crs[X]) != 0) + RPL = iget16(RP); + else + INCRP; goto fetch; d_a1a: /* 0141206 */ @@ -6223,16 +6247,13 @@ d_irx: /* 0140114 */ unsigned short type promotion! */ TRACE(T_FLOW, " IRX\n"); - /* XXX: change to if ((++crs[X] & 0xFFFF) == 0) */ - crs[X]++; - if (crs[X] == 0) + if ((short)(++crs[X]) == 0) INCRP; goto fetch; d_drx: /* 0140210 */ TRACE(T_FLOW, " DRX\n"); - crs[X]--; - if (crs[X] == 0) + if ((short)(--crs[X]) == 0) INCRP; goto fetch; @@ -6296,22 +6317,12 @@ d_tya: /* 0141124 */ d_xca: /* 0140104 */ TRACE(T_FLOW, " XCA\n"); -#ifdef FAST crsl[GR2] = crsl[GR2] >> 16; -#else - crs[B] = crs[A]; - crs[A] = 0; -#endif goto fetch; d_xcb: /* 0140204 */ TRACE(T_FLOW, " XCB\n"); -#ifdef FAST crsl[GR2] = crsl[GR2] << 16; -#else - crs[A] = crs[B]; - crs[B] = 0; -#endif goto fetch; d_tca: /* 0140407 */ @@ -6551,7 +6562,7 @@ d_fsgt: /* 0140515 */ goto fetch; d_int: /* 0140554 */ - TRACE(T_FLOW, " INT\n"); + TRACE(T_FLOW, " INTr\n"); /* XXX: do -1073741824.5 and 1073741823.5 work on Prime, or overflow? */ if (prieee8(crs+FLTH, &tempd) && -1073741824.0 <= tempd && tempd <= 1073741823.0) { templ = tempd; @@ -6632,12 +6643,7 @@ d_cre: /* 0141404 */ d_crle: /* 0141410 */ TRACE(T_FLOW, " CRLE\n"); -#ifdef FAST *(long long *)(crs+L) = 0; -#else - *(int *)(crs+L) = 0; - *(int *)(crs+E) = 0; -#endif goto fetch; d_ile: /* 0141414 */ @@ -8880,7 +8886,7 @@ imodepcl: d_ldadld: /* 00200 */ crs[A] = get16t(ea); if ((crs[KEYS] & 050000) != 040000) { /* not R-mode or not DP */ - TRACE(T_FLOW, " LDA ='%o/%d\n", crs[A], *(short *)(crs+A)); + TRACE(T_FLOW, " LDA ='%o/%d %03o %03o\n", crs[A], *(short *)(crs+A), crs[A]>>8, crs[A] & 0xFF); } else { TRACE(T_FLOW, " DLD\n"); crs[B] = get16t(INCVA(ea,1)); diff --git a/emdev.h b/emdev.h index 53e7adb..63802f4 100644 --- a/emdev.h +++ b/emdev.h @@ -164,7 +164,8 @@ int devnone (int class, int func, int device) { switch (class) { - case -1: + case -1: /* emulator initialization */ + case -2: /* emulator termination */ return 0; case 0: @@ -255,6 +256,12 @@ int devnone (int class, int func, int device) { int devasr (int class, int func, int device) { +/* on OSX, doing select() to see if it's okay to write means that there is + room for at least 1024 characters. On other platforms, this constant + may need to be lowered. It can be lowered to 1. */ + +#define MAXASRBUF 1024 + static initialized = 0; static FILE *conslog; static int ttydev; @@ -264,6 +271,7 @@ int devasr (int class, int func, int device) { static fd_set fds; static short vcptime[8] = {7*0, 1}; static short vcptimeix; + static short roomleft = MAXASRBUF; struct timeval timeout; unsigned char ch; @@ -356,18 +364,21 @@ int devasr (int class, int func, int device) { TRACE(T_INST, " SKS '%02o%02o\n", func, device); if (func == 6) { /* skip if room for a character */ - if (crs[MODALS] & 010) /* PX enabled? */ - timeout.tv_sec = 0; /* yes, can't delay */ - else - timeout.tv_sec = 1; /* single user: okay to delay */ - timeout.tv_usec = 0; - FD_SET(ttydev, &fds); - n = select(ttydev+1, NULL, &fds, NULL, &timeout); - if (n == -1) { - perror(" unable to do write select on tty"); - fatal(NULL); + if (roomleft <= 0) { /* shouldn't be negative, but safer */ + if (crs[MODALS] & 010) /* PX enabled? */ + timeout.tv_sec = 0; /* yes, can't delay */ + else + timeout.tv_sec = 1; /* single user: okay to delay */ + timeout.tv_usec = 0; + FD_SET(ttydev, &fds); + n = select(ttydev+1, NULL, &fds, NULL, &timeout); + if (n == -1) { + perror(" unable to do write select on tty"); + fatal(NULL); + } else if (n > 0) + roomleft = MAXASRBUF; } - if (n) { + if (roomleft > 0) { IOSKIP; } @@ -411,10 +422,8 @@ int devasr (int class, int func, int device) { fatal(NULL); } ttyflags = newflags; -#if 1 - if (doblock) - fflush(gvp->tracefile); /* hack to flush for 32i testing */ -#endif + if (doblock) /* doblock = no PX = running diags */ + fflush(gvp->tracefile); /* flush trace buffer when testing */ if (doblock && needflush) { if (fflush(stdout) == 0) { @@ -511,6 +520,7 @@ readasr: return; #endif putchar(ch); + roomleft--; if (ch != 015) putc(ch, conslog); needflush = 1; @@ -1628,7 +1638,7 @@ int devdisk (int class, int func, int device) { #define MAXDRIVES 8 #define HASHMAX 4451 -#if 0 +#if 1 #define CID4005 0100 #else #define CID4005 0 @@ -2199,9 +2209,11 @@ int devamlc (int class, int func, int device) { #define TS_OPTION 3 /* inside an option */ static short inited = 0; - static short devices[MAXBOARDS]; /* list of AMLC devices initialized */ - static int tsfd; /* socket fd for terminal server */ - static struct { /* maps socket fd to device & line */ + static char ttymsg[1024]; + static int ttymsglen = 0; + static short devices[MAXBOARDS]; /* list of AMLC devices initialized */ + static int tsfd; /* socket fd for terminal server */ + static struct { /* maps socket fd to device & line */ int device; int line; } socktoline[MAXLINES]; @@ -2241,6 +2253,7 @@ int devamlc (int class, int func, int device) { struct timeval timeout; unsigned char ch; int state; + int msgfd; switch (class) { @@ -2283,6 +2296,14 @@ int devamlc (int class, int func, int device) { perror("unable to set ts flags for AMLC"); fatal(NULL); } + if ((msgfd = open("ttymsg", O_RDONLY, 0)) >= 0) { + ttymsglen = read(msgfd, ttymsg, sizeof(ttymsg)-1); + if (ttymsglen >= 0) + ttymsg[ttymsglen] = 0; + close(msgfd); + } else if (errno != ENOENT) { + perror("Unable to open ttymsg file"); + } } else fprintf(stderr, "-tport is zero, can't start AMLC devices\n"); inited = 1; @@ -2528,19 +2549,7 @@ int devamlc (int class, int func, int device) { buf[7] = 253; /* do */ buf[8] = 0; /* binary mode */ write(fd, buf, 9); - strcpy((void *)buf,"\ -\r\n\ -Welcome to the Prime Computer 50-series emulator, running Primos rev 19.2!\r\n\ -\n\ - After logging in, use the Prime HELP command for assistance.\r\n\ - You are welcome to create a directory under GUEST for your files.\r\n\ - To report bugs or contact the author, send email to prirun@gmail.com\r\n\ -\n\ -Enjoy your time travels! -Jim Wilcoxson aka JIMMY\r\n\ -\r\n\ -Login please.\r\n\ -OK, "); - write(fd, buf, strlen((void *)buf)); + write(fd, ttymsg, ttymsglen); } }