mirror of
https://github.com/prirun/p50em.git
synced 2026-02-04 07:12:49 +00:00
address trap changes, trace format change, added warn(), FP fixes
This commit is contained in:
176
em.c
176
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);
|
||||
|
||||
158
emdev.h
158
emdev.h
@@ -57,6 +57,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
/* 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
|
||||
|
||||
Reference in New Issue
Block a user