From e20a46e1643121497f4e68fc041a72d904069c84 Mon Sep 17 00:00:00 2001 From: Jim Date: Mon, 12 Sep 2005 00:00:00 -0400 Subject: [PATCH] address trap changes, trace format change, added warn(), FP fixes --- em.c | 176 ++++++++++++++++++++++++++++++-------------------------- emdev.h | 158 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 202 insertions(+), 132 deletions(-) diff --git a/em.c b/em.c index cacf856..6eb3290 100644 --- a/em.c +++ b/em.c @@ -66,13 +66,6 @@ typedef unsigned int pa_t; /* physical address */ else if (*(int *)(crs+L) < 0) \ crs[KEYS] |= 0200; -#define SETCC_LE \ - crs[KEYS] &= ~0300; \ - if (*(int *)(crs+L) == 0 && *(int *)(crs+E) == 0) \ - crs[KEYS] |= 0100; \ - else if (*(int *)(crs+L) < 0) \ - crs[KEYS] |= 0200; - /* NOTE: in previous versions, exponent must be zero for 0.0, but DIAG test CPU.FLOAT.V considers a zero fraction and non-zero exponent to also be 0.0 (this is a "dirty zero") */ @@ -130,16 +123,16 @@ typedef unsigned int pa_t; /* physical address */ print something when they're encountered */ unsigned short gen0tab[] = { - 000503, /* EMCM */ - 000501, /* LMCM */ - 001304, /* MDEI */ - 001305, /* MDII */ - 001324, /* MDIW */ - 001306, /* MDRS */ - 001307, /* MDWC */ - 000021, /* RMC */ - 000311, /* VIFY */ - 001113}; /* XVFY */ + 000503, /* EMCM - enter machine check mode */ + 000501, /* LMCM - leave machine check mode */ + 001304, /* MDEI - memory diagnostic */ + 001305, /* MDII - memory diagnostic */ + 001324, /* MDIW - memory diagnostic */ + 001306, /* MDRS - memory diagnostic */ + 001307, /* MDWC - memory diagnostic */ + 000021, /* RMC - reset machine check */ + 000311, /* VIFY - ucode verify */ + 001113}; /* XVFY - extended ucode verify */ #define GEN0TABSIZE sizeof(gen0tab)/sizeof(unsigned short) @@ -218,7 +211,7 @@ unsigned long instcount=0; /* global instruction count */ unsigned short inhcount = 0; /* number of instructions to stay inhibited */ -unsigned int instpermsec = 2400; /* initial assumption for inst/msec */ +unsigned int instpermsec = 2600; /* initial assumption for inst/msec */ jmp_buf jmpbuf; /* for longjumps to the fetch loop */ @@ -598,7 +591,7 @@ unsigned short get16r(ea_t ea, ea_t rpring) { /* check for live register access */ - if (ea & 0x80000000 || (!(crs[KEYS] & 010000) && (ea & 0xFFFF) < 040)) { + if (ea & 0x80000000) { ea = ea & 0xFFFF; if (ea < 7) return crs[memtocrs[ea]]; @@ -623,7 +616,7 @@ unsigned int get32r(ea_t ea, ea_t rpring) { /* check for live register access */ if (ea & 0x80000000) - fatal("Address trap in get32!"); + warn("address trap in get32"); pa = mapva(ea, RACC, &access, rpring); @@ -644,7 +637,7 @@ double get64r(ea_t ea, ea_t rpring) { /* check for live register access */ if (ea & 0x80000000) - fatal("Address trap in get64!"); + warn("address trap in get64"); pa = mapva(ea, RACC, &access, rpring); if ((pa & 01777) <= 01774) @@ -663,7 +656,7 @@ put16r(unsigned short value, ea_t ea, ea_t rpring) { pa_t pa; unsigned short access; - if (ea & 0x80000000 || (!(crs[KEYS] & 010000) && (ea & 0xFFFF) < 040)) { + if (ea & 0x80000000) { ea = ea & 0xFFFF; if (ea < 7) crs[memtocrs[ea]] = value; @@ -694,7 +687,7 @@ put32r(unsigned int value, ea_t ea, ea_t rpring) { /* check for live register access */ if (ea & 0x80000000) - fatal("Address trap in put32!"); + warn("address trap in put32"); pa = mapva(ea, WACC, &access, rpring); if ((pa & 01777) <= 01776) @@ -714,7 +707,7 @@ put64r(double value, ea_t ea, ea_t rpring) { /* check for live register access */ if (ea & 0x80000000) - fatal("Address trap in put32!"); + warn("address trap in put32"); pa = mapva(ea, WACC, &access, rpring); if ((pa & 01777) <= 01774) @@ -917,13 +910,16 @@ void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { fatal(char *msg) { - printf("Fatal error: instruction #%d at %o/%o: %o %o\n", instcount, prevpc >> 16, prevpc & 0xFFFF, get16(prevpc), get16(prevpc+1)); + printf("Fatal error: instruction #%d at %o/%o %s: %o %o keys=%o, modals=%o\n", instcount, prevpc >> 16, prevpc & 0xFFFF, searchloadmap(prevpc,' '), get16(prevpc), get16(prevpc+1), crs[KEYS], crs[MODALS]); if (msg) printf("%s\n", msg); - printf("keys = %o, modals=%o\n", crs[KEYS], crs[MODALS]); /* should do a register dump, RL dump, PCB dump, etc. here... */ exit(1); } + +warn(char *msg) { + printf("emulator warning:\n instruction #%d at %o/%o: %o %o keys=%o, modals=%o\n %s\n", instcount, prevpc >> 16, prevpc & 0xFFFF, get16(prevpc), get16(prevpc+1),crs[KEYS], crs[MODALS], msg); +} /* I/O device map table, containing function pointers to handle device I/O */ @@ -955,9 +951,13 @@ unsigned short readshort () { ea_t ea16s (unsigned short inst, short i, short x) { - unsigned short ea, m, rpl, amask; + unsigned short ea, m, rpl, amask, live; ea_t va; + if (crs[MODALS] & 4) /* segmentation enabled? */ + live = 010; /* yes, limit register traps */ + else + live = 040; amask = 037777; rpl = prevpc; if (inst & 001000) @@ -969,8 +969,7 @@ ea_t ea16s (unsigned short inst, short i, short x) { ea += crs[X]; if (!i) /* not indirect */ break; - /* NOTE: this test is already in get16... */ - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(RPH,ea)); @@ -979,7 +978,7 @@ ea_t ea16s (unsigned short inst, short i, short x) { ea = m & 037777; /* go indirect */ } va = MAKEVA(RPH, ea); - if (ea < 040) /* flag live register ea */ + if (ea < live) /* flag live register ea */ return va | 0x80000000; return va; } @@ -989,9 +988,14 @@ ea_t ea16s (unsigned short inst, short i, short x) { ea_t ea32s (unsigned short inst, short i, short x) { - unsigned short ea, m,rpl,amask; + unsigned short ea, m,rpl, amask, live; ea_t va; + if (crs[MODALS] & 4) /* segmentation enabled? */ + live = 010; /* yes, limit register traps */ + else + live = 040; + amask = 077777; rpl = prevpc; if (inst & 001000) ea = (rpl & 077000) | (inst & 0777); /* current sector */ @@ -1014,7 +1018,7 @@ ea_t ea32s (unsigned short inst, short i, short x) { ea += crs[X]; ea &= amask; va = MAKEVA(RPH, ea); - if (ea < 040) /* flag live register ea */ + if (ea < live) /* flag live register ea */ return va | 0x80000000; return va; } @@ -1026,10 +1030,16 @@ ea_t ea32s (unsigned short inst, short i, short x) { ea_t ea32r64r (ea_t earp, unsigned short inst, short i, short x, unsigned short *opcode) { - short class; - unsigned short ea,m,rph,rpl; + unsigned short live, ea, m, rph, rpl, amask, class; ea_t va; + if (crs[MODALS] & 4) /* segmentation enabled? */ + live = 010; /* yes, limit register traps */ + else + live = 040; + amask = 0177777; + if ((crs[KEYS] & 016000) == 06000) /* 32R mode? */ + amask = 077777; rpl = earp; rph = (earp >> 16) & 0x7FFF; /* clear fault (live register) bit from RP */ if (T_EAR) fprintf(stderr," ea32r64r: i=%o, x=%o, amask=%o\n", i!= 0, x!=0, amask); @@ -1051,7 +1061,7 @@ ea_t ea32r64r (ea_t earp, unsigned short inst, short i, short x, unsigned short } } while (i) { - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(rph,ea)); @@ -1070,7 +1080,7 @@ ea_t ea32r64r (ea_t earp, unsigned short inst, short i, short x, unsigned short } ea &= amask; va = MAKEVA(rph, ea); - if (ea < 040) /* flag live register ea */ + if (ea < live) /* flag live register ea */ return va | 0x80000000; return va; @@ -1090,7 +1100,7 @@ special: if (T_EAR) fprintf(stderr," Preindex, new ea=%o\n", ea); } while (i) { - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(rph,ea)); @@ -1105,12 +1115,12 @@ special: } else if (i && x) { /* class 2/3, ix=11 */ if (T_EAR) fprintf(stderr," class 2/3, ix=11\n"); - ea = get16(MAKEVA(rph,RPL++)); /* get A from next word */ + ea = get16(MAKEVA(RPH,RPL++)); /* get A from next word */ if (T_EAR) fprintf(stderr," ea=%o\n", ea); if (class == 3) ea += (short) crs[S]; while (i) { - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(rph,ea)); @@ -1133,7 +1143,7 @@ special: ea = --crs[S]; if (T_EAR) fprintf(stderr," Class 2/3, new ea=%o, new S=%o\n", ea, crs[S]); if (x) { - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(rph,ea)); @@ -1142,7 +1152,7 @@ special: ea = m & amask; } while (i) { - if (ea < 040) + if (ea < live) m = get16(0x80000000|ea); else m = get16(MAKEVA(rph,ea)); @@ -1157,7 +1167,7 @@ special: } ea &= amask; va = MAKEVA(rph, ea); - if (ea < 040) /* flag live register ea */ + if (ea < live) /* flag live register ea */ return va | 0x80000000; return va; } @@ -2751,7 +2761,7 @@ main (int argc, char **argv) { traceflags = ~TB_MAP; #endif -#if 0 +#if 1 if (traceflags != 0) savetraceflags = traceflags; if (crs[OWNERL] == 0100100 && savetraceflags) @@ -3463,6 +3473,7 @@ stfa: stlb[utempa].valid = 0; if (T_INST) fprintf(stderr," invalidated STLB index %d\n", utempa); } +#if 0 /* HACK for DIAG to suppress ITLB loop in trace */ if (RP == 0106070) if (*(int *)(crs+L) == 0) { @@ -3473,6 +3484,7 @@ stfa: fprintf(stderr," Restoring DIAG trace\n"); traceflags = savetraceflags; } +#endif continue; case 000711: @@ -3497,8 +3509,8 @@ stfa: fault(UIIFAULT, RPL, RP); continue; - /* I think this is an invalid opcode that Prime uses when unexpected - things happen, for example: + /* JW: I think this is an invalid opcode that Prime uses when + unexpected things happen, for example: LDA modals get modals SAS 1 interrupts enabled? @@ -4391,13 +4403,16 @@ lcgt: case 0140550: if (T_FLOW) fprintf(stderr," FLOT\n"); - templ = crs[A]; + templ = *(short *)(crs+A); templ = crs[B] | (templ<<15); tempf = templ; + tempf1 = tempf; ieeepr4(&tempf); crs[FLTH] = (*(unsigned int *)&tempf) >> 16; crs[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; crs[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + crs[FLTD] = 0; + if (T_INST) fprintf(stderr," A|B=%d, conv=%f, FEXP=%d (dec), FLTH='%o, FLTL='%o\n", templ, tempf1, crs[FEXP], crs[FLTH], crs[FLTL]); continue; case 0140534: @@ -4499,13 +4514,15 @@ lcgt: tempda[2] = crs[FLTD]; tempda[3] = crs[FEXP]; prieee8(tempda); + if (T_INST) fprintf(stderr," DFAC value=%f, FEXP=%d (dec), FLTH='%o, FLTL='%o, fltd='%o\n", *(double *)tempda, crs[FEXP], crs[FLTH], crs[FLTL], crs[FLTD]); + templ = *(double *)tempda; + if (T_INST) fprintf(stderr," INT value=%d\n", templ); + crs[B] = templ & 0x7FFF; + crs[A] = templ >> 15; if (*(double *)tempda > 1073741823.0 || *(double *)tempda < -1073741824.0) mathexception('f', FC_DFP_OFLOW, ea); else CLEARC; - templ = *(double *)tempda; - crs[B] = templ & 0x7FFF; - crs[A] = templ >> 15; continue; case 0140531: @@ -4519,7 +4536,7 @@ lcgt: mathexception('f', FC_DFP_OFLOW, ea); else CLEARC; - tempa = *(double *)tempda; + *(short *)(crs+A) = *(double *)tempda; continue; case 0140532: @@ -4529,6 +4546,7 @@ lcgt: crs[FLTH] = (*(unsigned int *)&tempf) >> 16; crs[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; crs[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + crs[FLTD] = 0; continue; case 0140533: @@ -4542,7 +4560,7 @@ lcgt: mathexception('f', FC_DFP_OFLOW, ea); else CLEARC; - templ = *(double *)tempda; + *(int *)(crs+L) = *(double *)tempda; continue; case 0140535: @@ -4552,6 +4570,7 @@ lcgt: crs[FLTH] = (*(unsigned int *)&tempf) >> 16; crs[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; crs[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + crs[FLTD] = 0; continue; case 0141711: @@ -4563,7 +4582,7 @@ lcgt: continue; #if 0 - case 0141602: /* same opcode as BCNE */ + case 0141602: /* same opcode as BCEQ */ if (T_FLOW) fprintf(stderr," BMEQ\n"); goto bceq; @@ -4581,11 +4600,6 @@ lcgt: #endif case 0141710: -#if 0 - /* this is good for tracing the failure if cpuid is set to 15 in - Primos boot. Weird memory maps for 9950 16MB? */ - traceflags = -1; -#endif if (T_FLOW) fprintf(stderr," BMGT\n"); if (crs[KEYS] & 020000) goto bcne; @@ -4908,7 +4922,7 @@ lcgt: break; default: - printf("WARNING: unrecognized shift instruction %o at %o/%o\n", inst, RPH, RPL); + printf("emulator warning: unrecognized shift instruction %o at %o/%o\n", inst, RPH, RPL); if (T_INST) fprintf(stderr," unrecognized shift instruction!: %o\n", inst); } continue; @@ -5128,7 +5142,8 @@ keys = 14200, modals=100177 break; case 4: /* 32I */ ea = ea32i(earp, inst, i, x); - fatal("32I not supported"); + warn("32I mode not supported"); + fault(RESTRICTFAULT, 0, 0); break; case 6: /* 64V */ ea = ea64v(earp, inst, i, x, &opcode, &eabit); @@ -5208,7 +5223,7 @@ keys = 14200, modals=100177 crs[A] = utempl; if (utempl & 0x10000) /* set L-bit if carry */ crs[KEYS] |= 020000; - /* NOTE: the EQ test prevents use from reusing the ADD code :( */ + /* NOTE: this EQ test prevents reusing the ADD code :( */ if (*(int *)(crs+L) == 0) /* set EQ? */ crs[KEYS] |= 0100; if (((~utempa ^ m) & (utempa ^ crs[A])) & 0x8000) { @@ -5285,9 +5300,11 @@ keys = 14200, modals=100177 case 01000: if (T_FLOW) fprintf(stderr," JST\n"); -#if 0 - ea = MAKEVA(RPH, ea & 0xFFFF); -#endif + /* NOTE: amask should be recomputed here if in R/S mode, so it + can be removed as a global variable. Flaky errors occur if + keys are changed w/o calling newkeys(), because amask would + be wrong (see dispatcher comment) */ + if (amask == 0177777) m = RPL; else @@ -5298,8 +5315,6 @@ keys = 14200, modals=100177 inhcount = 1; continue; - /* this should set the C and L bits like subtract */ - case 01100: m = get16(ea); if (T_FLOW) fprintf(stderr," CAS ='%o/%d\n", m, *(short *)&m); @@ -5622,17 +5637,19 @@ keys = 14200, modals=100177 case 00601: if (T_FLOW) fprintf(stderr," FAD\n"); - if (T_INST) fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", crs[FEXP], crs[FLTH], crs[FLTL]); - //if (T_INST) fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); *(int *)&tempf = (crs[FLTH]<<16) | (crs[FLTL] & 0xFF00) | (crs[FEXP] & 0xFF); prieee4(&tempf); + if (T_INST) fprintf(stderr," FAC value=%f, FEXP=%d (dec), FLTH='%o, FLTL='%o\n", tempf, crs[FEXP], crs[FLTH], crs[FLTL]); *(int *)&tempf1 = get32(ea); prieee4(&tempf1); + if (T_INST) fprintf(stderr," ea value=%f, EXP=%d (dec), ea H='%o, ea L='%o\n", tempf1, get16(ea+1) & 0xFF, get16(ea), get16(ea+1) & 0xFF00); tempf += tempf1; + tempf1 = tempf; ieeepr4(&tempf); crs[FLTH] = (*(unsigned int *)&tempf) >> 16; crs[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; crs[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + if (T_INST) fprintf(stderr," FAC value=%f, FEXP=%d (dec), FLTH='%o, FLTL='%o\n", tempf1, crs[FEXP], crs[FLTH], crs[FLTL]); XEXPC(0); continue; @@ -5640,12 +5657,12 @@ keys = 14200, modals=100177 case 01101: if (T_FLOW) fprintf(stderr," FCS\n"); - if (T_INST) fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", crs[FEXP], crs[FLTH], crs[FLTL]); - //if (T_INST) fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); *(int *)&tempf = (crs[FLTH]<<16) | (crs[FLTL] & 0xFF00) | (crs[FEXP] & 0xFF); prieee4(&tempf); + if (T_INST) fprintf(stderr," FAC value=%f, FEXP=%d (dec), FLTH='%o, FLTL='%o\n", tempf, crs[FEXP], crs[FLTH], crs[FLTL]); *(int *)&tempf1 = get32(ea); prieee4(&tempf1); + if (T_INST) fprintf(stderr," ea value=%f, EXP=%d (dec), ea H='%o, ea L='%o\n", tempf1, get16(ea+1) & 0xFF, get16(ea), get16(ea+1) & 0xFF00); crs[KEYS] &= ~0300; if (tempf == tempf1) { RPL++; @@ -5674,10 +5691,12 @@ keys = 14200, modals=100177 case 0201: if (T_FLOW) fprintf(stderr," FLD\n"); - crs[FLTH] = get16(ea); - m = get16(ea+1); - crs[FLTL] = m & 0xFF00; - crs[FEXP] = m & 0xFF; + utempl = get32(ea); + crs[FLTH] = utempl >> 16; + crs[FLTL] = utempl & 0xFF00; + crs[FEXP] = utempl & 0xFF; + crs[FLTD] = 0; + if (T_INST) fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", crs[FEXP], crs[FLTH], crs[FLTL]); continue; case 01601: @@ -5714,6 +5733,7 @@ keys = 14200, modals=100177 case 0401: if (T_FLOW) fprintf(stderr," FST\n"); + if (T_INST) fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", crs[FEXP], crs[FLTH], crs[FLTL]); if (crs[FEXP] & 0xFF00) mathexception('f', FC_SFP_STORE, ea); put16(crs[FLTH],ea); @@ -5929,14 +5949,6 @@ keys = 14200, modals=100177 continue; default: -#if 0 - if (mem[066] != 0) { - if (T_FLOW) fprintf(stderr," JST* '66 [%o]\n", mem[066]); - mem[mem[066]] = RPL; - RPL = mem[066]+1; - continue; - } -#endif printf("Unknown memory reference opcode: %o\n", opcode); fatal(NULL); } @@ -6232,7 +6244,7 @@ svc() { /* if location '65 is set, do indirect JST to handle svc */ /* if the svc fault vector is zero, interpret the svc here. This - allows the emulator to run r-mode programs directly */ + allows the emulator to run R-mode programs directly */ if ((crs[MODALS] & 010) || get16(065) != 0) { fault(SVCFAULT, 0, 0); diff --git a/emdev.h b/emdev.h index 37fcb54..5b1e543 100644 --- a/emdev.h +++ b/emdev.h @@ -57,6 +57,7 @@ #include #include #include +#include /* this macro is used when I/O is successful. In VI modes, it sets the EQ condition code bit. In SR modes, it does a skip */ @@ -68,16 +69,20 @@ RPL++ /* macro to detect if an I/O instruction is followed by JMP *-1 (SR modes) - or BCNE *-2 (VI modes) */ + or BCNE *-2 (VI modes). If process exchange is enabled, I/O can never + block. */ #if 1 #define BLOCKIO \ - (get16(RP) == 03776 || (get16(RP) == 0141603 && get16(RP+1) == RPL-2)) + (!(crs[MODALS] & 010) && (get16(RP) == 03776 || (get16(RP) == 0141603 && get16(RP+1) == RPL-2))) #else #define BLOCKIO 0 #endif + +/* this is a template for device handlers */ + void devnull (short class, short func, short device) { switch (class) { @@ -128,8 +133,8 @@ void devnull (short class, short func, short device) { /* Device '4: system console NOTES: - - needs to set -icanon -icrnl on system console tty - - only works with ASRATE 3410 - not 7672 (19,200 bps) + - needs to reset tty attributes when emulator shuts down + - Primos only handles ASRATE 110 (10cps), 1010 (30cps), 3410 (960 cps) - input ID is wrong, causes OCP '0477 on clock interrupt - instruction counters on output are bogus, need to intercept TNOUA instead @@ -187,6 +192,7 @@ void devnull (short class, short func, short device) { */ + void devasr (short class, short func, short device) { static int ttydev; @@ -194,7 +200,8 @@ void devasr (short class, short func, short device) { static int needflush; /* true if data has been written but not flushed */ static int atbol=1; /* true if cursor is at bol */ static int atnewl=1; /* true if cursor is on a blank line */ - fd_set readfds; + static struct termios terminfo; + static fd_set fds; struct timeval timeout; unsigned char ch; int newflags; @@ -213,8 +220,19 @@ void devasr (short class, short func, short device) { perror(" unable to get tty flags"); fatal(NULL); } - FD_ZERO(&readfds); - FD_SET(ttydev, &readfds); + FD_ZERO(&fds); + if (tcgetattr(ttydev, &terminfo) == -1) { + perror(" unable to get tty attributes"); + fatal(NULL); + } + terminfo.c_iflag &= ~(INLCR | ICRNL); + terminfo.c_lflag &= ~(ECHOCTL | ICANON); + terminfo.c_cc[VMIN] = 0; + terminfo.c_cc[VTIME] = 0; + if (tcsetattr(ttydev, TCSANOW, &terminfo) == -1) { + perror(" unable to set tty attributes"); + fatal(NULL); + } break; case 0: @@ -223,27 +241,46 @@ void devasr (short class, short func, short device) { case 1: if (T_INST) fprintf(stderr," SKS '%02o%02o\n", func, device); - if (func == 7) { /* skip if received a char */ - timeout.tv_sec = 0; + + if (func == 6) { /* skip if room for a character */ #if 0 - timeout.tv_usec = 100000; -#else - timeout.tv_usec = 1; + timeout.tv_sec = 0; timeout.tv_usec = 0; -#endif - if (select(1, &readfds, NULL, NULL, &timeout) == 1) + FD_SET(ttydev, &fds); + n = select(ttydev+1, NULL, &fds, NULL, &timeout); + if (n == -1) { + perror(" unable to do write select on ttydev"); + fatal(NULL); + } + if (n) { IOSKIP; + } +#else + IOSKIP; /* assume there is room under Unix */ +#endif + + } else if (func == 7) { /* skip if received a char */ + if (crs[MODALS] & 010) /* PX enabled? */ + timeout.tv_sec = 0; /* yes, can't delay */ + else + timeout.tv_sec = 1; + timeout.tv_usec = 0; + FD_SET(ttydev, &fds); + n = select(ttydev+1, &fds, NULL, NULL, &timeout); + if (n == -1) { + perror(" unable to do select on tty"); + fatal(NULL); + } + if (n) { + IOSKIP; + } + } else if (func <= 014) IOSKIP; /* assume it's always ready */ break; case 2: if (T_INST) fprintf(stderr," INA '%02o%02o\n", func, device); - if (needflush) { - fflush(stdout); - needflush = 0; - devpoll[device] = 0; - } if (func == 0 || func == 010) { if (BLOCKIO) newflags = ttyflags & ~O_NONBLOCK; @@ -254,6 +291,11 @@ void devasr (short class, short func, short device) { fatal(NULL); } ttyflags = newflags; + if (needflush && BLOCKIO) { + fflush(stdout); + needflush = 0; + devpoll[device] = 0; + } readasr: n = read(ttydev, &ch, 1); if (n < 0) { @@ -263,16 +305,19 @@ readasr: } } else if (n == 1) { if (ch == '') { - traceflags = -1; - traceflags = ~TB_MAP; - fprintf(stderr,"\nTRACE ENABLED:\n\n"); - memdump(0, 0xFFFF); + traceflags = ~traceflags; + traceflags &= ~TB_MAP; + if (traceflags == 0) + fprintf(stderr,"\nTRACE DISABLED:\n\n"); + else + fprintf(stderr,"\nTRACE ENABLED:\n\n"); + //memdump(0, 0xFFFF); goto readasr; } if (func >= 010) crs[A] = 0; crs[A] = crs[A] | ch; - if (T_INST) fprintf(stderr," character read=%o: %c\n", crs[A], crs[A]); + if (T_INST) fprintf(stderr," character read=%o: %c\n", crs[A], crs[A] & 0x7f); IOSKIP; } else if (n != 0) { printf("Unexpected error reading from tty, n=%d", n); @@ -301,24 +346,39 @@ readasr: if (func == 0) { ch = crs[A] & 0x7f; if (T_INST) fprintf(stderr," char to write=%o: %c\n", crs[A], ch); - if (ch > 0) { -#if 0 - if (atbol && atnewl) - printf("%10d| ", instcount); -#endif - putchar(ch); - if (ch == 015) - atbol = 1; - else if (ch == 012) - atnewl = 1; - else { - atbol = 0; - atnewl = 0; - } - needflush = 1; - devpoll[device] = instpermsec*100; + if (ch == 0 || ch == 0x7f) { + IOSKIP; + return; } - IOSKIP; /* OTA '0004 always works on Unix */ +#if 0 + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_SET(2, &fds); + n = select(2+1, NULL, &fds, NULL, &timeout); + if (n == -1) { + perror(" unable to do write select on stdout"); + fatal(NULL); + } + if (!n) + return; +#endif +#if 0 + if (atbol && atnewl) + printf("%10d| ", instcount); +#endif + putchar(ch); + if (ch == 015) + atbol = 1; + else if (ch == 012) + atnewl = 1; + else { + atbol = 0; + atnewl = 0; + } + needflush = 1; + if (devpoll[device] == 0) + devpoll[device] = instpermsec*100; + IOSKIP; } else if (func == 1) { /* write control word */ IOSKIP; } else if (04 <= func && func <= 07) { /* write control register 1/2 */ @@ -336,10 +396,13 @@ readasr: break; case 4: + /* since the tty device is in non-blocking mode under Primos, keep + flushing output every .1 seconds for smoothest and fastest + output */ if (needflush) { fflush(stdout); - needflush = 0; - devpoll[device] = 0; + needflush = 1; + devpoll[device] = instpermsec*100; } } } @@ -655,11 +718,6 @@ void devdisk (short class, short func, short device) { if (func == 01) /* read device id, clear A first */ crs[A] = CID4005 + device; -#if 0 - /* this happens when the clock poll rate is set to 100000 (?) */ - else if (func == 06) /* don't know what this is... */ - return; -#endif else if (func == 011) /* read device id, don't clear A */ crs[A] |= (CID4005 + device); else if (func == 017) { /* read OAR */ @@ -727,7 +785,7 @@ void devdisk (short class, short func, short device) { dc[device].status = 0100001; } else if (order == 2) { if (T_INST || T_DIO) fprintf(stderr," Format order\n"); - fatal("DFORMAT channel order not implemented"); + //fatal("DFORMAT channel order not implemented"); } else { /* order = 5 (read) or 6 (write) */ /* translate head/track/sector to drive record address */ @@ -799,7 +857,7 @@ void devdisk (short class, short func, short device) { case 7: /* DSTALL = Stall */ if (T_INST || T_DIO) fprintf(stderr," stall\n"); -#if 1 +#if 0 devpoll[device] = instpermsec/5; /* 200 microseconds, sb 210 */ return; #else