From 655b35b0f9786cc43171c3bc071081c6d466686c Mon Sep 17 00:00:00 2001 From: Jim Date: Sat, 23 Apr 2005 00:00:00 -0400 Subject: [PATCH] added table of generic instructions to ignore & log initial disk controller support began FP instruction work --- em.c | 892 ++++++++++++++++++++++++++++++++++++++++++++++---------- emdev.h | 313 ++++++++++++++++++-- fp.c | 304 +++++++++++++++++++ os.c | 6 + 4 files changed, 1348 insertions(+), 167 deletions(-) create mode 100644 fp.c diff --git a/em.c b/em.c index 01e0a78..a82f7de 100644 --- a/em.c +++ b/em.c @@ -29,9 +29,6 @@ - many instructions are left to implement - - only 1 32R program has been executed, and it may have issues; - no other CPU modes have been tested at all - - svc doesn't handle alternate returns, LOC(blah) args might not be handled correctly, and it doesn't handle missing or extra arguments correctly (by looking for the terminating zero) @@ -58,11 +55,15 @@ #define A 1 #define B 2 #define S 3 +#define Y 3 #define FLTH 4 #define FLTL 5 +#define FLTD 07776<<16 #define FEXP 6 #define VSC 6 #define P 7 +/* XXX: this is a huge hack! */ +#define E 010 #define PMAR 010 #define FCODE 011 #define PFAR 012 @@ -84,14 +85,14 @@ #define SETCC_A \ keys &= ~0300; \ - if (*(short *)(mem+A) == 0) \ + if (mem[A] == 0) \ keys |= 0100; \ else if (*(short *)(mem+A) < 0) \ keys |= 0200; #define SETCC_X \ keys &= ~0300; \ - if (*(short *)(mem+X) == 0) \ + if (mem[X] == 0) \ keys |= 0100; \ else if (*(short *)(mem+X) < 0) \ keys |= 0200; @@ -110,10 +111,47 @@ else if (*(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0) \ keys |= 0100; +#define SETCC_D SETCC_F + #define SETC(onoff) \ if ((onoff)) keys |= 0100000; \ else keys &= 077777; +/* Table for unusual instructions that aren't implemented but we want to + 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 */ + 0100200, /* SMCR */ + 0101200, /* SMCS */ + 000311, /* VIFY */ + 001113, /* XVFY */ + 000411}; /* CAI */ + +#define GEN0TABSIZE sizeof(gen0tab)/sizeof(unsigned short) + +char gen0nam[][5] = { + "EMCM", + "LMCM", + "MDEI", + "MDII", + "MDIW", + "MDRS", + "MDWC", + "RMC", + "SMCR", + "SMCS", + "VIFY", + "XVFY", + "CAI"}; + /* NOTES: - mem is 1 user's virtual memory address space in this version, @@ -141,6 +179,8 @@ unsigned int bitmask16[17] = {0, 0x0008, 0x0004, 0x0002, 0x0001}; unsigned short prevpc,keys; /* program counter, prev pc, keys */ +unsigned short modals; + unsigned short amask; /* address mask */ #define faultamask 0100000 /* fault bit */ #define ringamask 060000 /* ring bits */ @@ -148,7 +188,7 @@ unsigned short amask; /* address mask */ #define segamask 07777 /* segment number */ int verbose; -int memdump; /* -memdump arg */ +int domemdump; /* -memdump arg */ int boot; /* true if reading a boot record */ /* I/O device map table, containing function pointers to handle device I/O */ @@ -157,8 +197,8 @@ int boot; /* true if reading a boot record */ void (*devmap[64])(short, short, short) = { 0,0,0,0,devasr,0,0,0, - 0,0,0,0,0,0,0,0, - devcp,0,0,0,0,0,0,0, + 0,0,0,devmt,devmt,0,0,0, + devcp,0,0,0,0,0,devdisk,devdisk, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, @@ -203,6 +243,7 @@ newkeys (unsigned short new) { case 6: /* 64V */ fprintf(stderr,"Entering 64V mode, keys=%o\n", keys); amask = 0177777; + memdump(0,0177777); exit(1); break; default: /* invalid */ @@ -295,7 +336,7 @@ unsigned short ea32r64r (unsigned short inst, short i, short x, short *opcode) { else i = 0; ea = mem[ea] & amask; /* go indirect */ - fprintf(stderr," Indirect, new i=%d, new ea=%o, [ea]=%o\n", i!=0, ea, mem[ea]); + fprintf(stderr," Indirect, new i=%d, new ea=%o\n", i!=0, ea); } if (x) { fprintf(stderr," Postindex, old ea=%o, X='%o/%d\n", ea, mem[X], *(short *)(mem+X)); @@ -326,7 +367,7 @@ special: else i = 0; ea = mem[ea] & amask; - fprintf(stderr," Indirect, new i=%d, new ea=%o, [ea]=%o\n", i!=0, ea, mem[ea]); + fprintf(stderr," Indirect, new i=%d, new ea=%o\n", i!=0, ea); } } else if (i && x) { /* class 2/3, ix=11 */ @@ -342,7 +383,7 @@ special: else i = 0; ea = mem[ea] & amask; - fprintf(stderr," Indirect, new i=%d, new ea=%o, [ea]=%o\n", i!=0, ea, mem[ea]); + fprintf(stderr," Indirect, new i=%d, new ea=%o\n", i!=0, ea); } fprintf(stderr," Postindex, old ea=%o, X='%o/%d\n", ea, mem[X], *(short *)(mem+X)); ea += (short) mem[X]; @@ -405,7 +446,7 @@ unsigned int ea64v (unsigned short inst, short i, short x, short *opcode) { if (i) { fprintf(stderr," Indirect, old ea=%o, [ea]=%o\n", ea, mem[ea]); ea = mem[ea] & amask; /* go indirect */ - fprintf(stderr," Indirect, new i=%d, new ea=%o, [ea]=%o\n", i!=0, ea, mem[ea]); + fprintf(stderr," Indirect, new i=%d, new ea=%o\n", i!=0, ea); } if (x) { fprintf(stderr," Postindex, old ea=%o, X='%o/%d\n", ea, mem[X], *(short *)(mem+X)); @@ -460,11 +501,11 @@ cpuexception(unsigned char extype) } break; case 'f': - if (keys & 40) { - printf(" Decimal exception fault\n"); - exit(1); - } else { + if (keys & 01000) { keys |= 0x8000; + } else { + printf(" FP exception fault\n"); + exit(1); } break; default: @@ -475,14 +516,35 @@ cpuexception(unsigned char extype) +memdump(int start, int end) { + int ea; + + /* dump sector zero for debugging */ + + fprintf(stderr,"\nSector 0:\n"); + for (ea=0; ea<01000; ea=ea+8) + if (mem[ea]|mem[ea+1]|mem[ea+2]|mem[ea+3]|mem[ea+4]|mem[ea+5]|mem[ea+6]|mem[ea+7]) + fprintf(stderr,"%3o: %6o %6o %6o %6o %6o %6o %6o %6o\n", ea, mem[ea], mem[ea+1], mem[ea+2], mem[ea+3], mem[ea+4], mem[ea+5], mem[ea+6], mem[ea+7]); + + /* dump main memory for debugging */ + + fprintf(stderr,"\nMain memory:\n"); + for (ea=start; ea<=end; ea=ea+8) + if (mem[ea]|mem[ea+1]|mem[ea+2]|mem[ea+3]|mem[ea+4]|mem[ea+5]|mem[ea+6]|mem[ea+7]) + fprintf(stderr,"%o: %6o %6o %6o %6o %6o %6o %6o %6o\n", ea, mem[ea], mem[ea+1], mem[ea+2], mem[ea+3], mem[ea+4], mem[ea+5], mem[ea+6], mem[ea+7]); +} + + main (int argc, char **argv) { - signed short tempa; + signed short tempa,tempa1,tempa2; unsigned short utempa; - signed int templ; + signed int templ,templ1,templ2; + signed long long ll; unsigned int utempl; - float tempf; - double tempdf; + float tempf,tempf1,tempf2; + double tempd,tempd1,tempd2; + signed short tempda[4],tempda1[4]; unsigned int ea32; /* full V/I mode eff address */ unsigned short ea; /* effective address (word) */ unsigned short opcode; @@ -506,7 +568,7 @@ main (int argc, char **argv) { */ verbose = 0; - memdump = 0; + domemdump = 0; boot = 0; /* check args */ @@ -517,7 +579,7 @@ main (int argc, char **argv) { else if (strcmp(argv[i],"--v") == 0) verbose = 1; else if (strcmp(argv[i],"--memdump") == 0) - memdump = 1; + domemdump = 1; else if (strcmp(argv[i],"--boot") == 0) boot = 1; else if (argv[i][0] == '-' && argv[i][1] == '-') @@ -556,28 +618,18 @@ main (int argc, char **argv) { /* setup execution (registers, keys, address mask, etc.) from rvec */ + modals = 0; mem[A] = rvec[3]; mem[B] = rvec[4]; mem[X] = rvec[5]; newkeys(rvec[6]); mem[P] = rvec[2]; - if (memdump) { + if (mem[P] == 0161000) /* hack for *DOS64; P is off by 3?? */ + mem[P] = 0161003; - /* dump sector zero for debugging */ - - fprintf(stderr,"\nSector 0:\n"); - for (ea=0; ea<01000; ea=ea+8) - if (mem[ea]|mem[ea+1]|mem[ea+2]|mem[ea+3]|mem[ea+4]|mem[ea+5]|mem[ea+6]|mem[ea+7]) - fprintf(stderr,"%3o: %6o %6o %6o %6o %6o %6o %6o %6o\n", ea, mem[ea], mem[ea+1], mem[ea+2], mem[ea+3], mem[ea+4], mem[ea+5], mem[ea+6], mem[ea+7]); - - /* dump main memory for debugging */ - - fprintf(stderr,"\nMain memory:\n"); - for (ea=rvec[2]; ea> 15); + mem[B] &= 0x7FFF; + mem[VSC]++; + } + fprintf(stderr, " finished with %d shifts: mem[A]=%o, mem[B]=%o\n", mem[VSC], mem[A], mem[B]); + continue; + } + + if (inst == 000401) { + fprintf(stderr," ENB\n"); + modals &= ~0100000; + continue; + } + + if (inst == 001001) { + fprintf(stderr," INH\n"); + modals |= 0100000; + continue; + } + + if (inst == 000415) { + fprintf(stderr," ESIM\n"); + modals &= ~040000; + continue; + } + + if (inst == 000417) { + fprintf(stderr," EVIM\n"); + modals |= 040000; + continue; + } + + /* unusual restricted instructions */ + + for (i=0; i> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + continue; + } + + if (inst == 0140534) { + fprintf(stderr," FRN\n"); + continue; + } + + if (inst == 0140574) { + fprintf(stderr," DFCM\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = 0; + tempda[3] = mem[FEXP]; + prieee8(tempda); + *(double *)tempda = -(*(double *)tempda); + ieeepr8(tempda); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FEXP] = tempda[3]; + SETC(0); + continue; + } + if (inst == 0140000) { fprintf(stderr," ADLL\n"); exit(1); @@ -1414,7 +1593,136 @@ lcgt: continue; } + if (inst == 0140530) { + fprintf(stderr," FCM\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + *(int *)&tempf = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + tempf = -tempf; + ieeepr4(&tempf); + mem[FLTH] = (*(unsigned int *)&tempf) >> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + SETC(0); + continue; + } + + if (inst == 0140510) { + fprintf(stderr," FSZE\n"); + if (*(int *)(mem+FLTH) == 0 && mem[FEXP] == 0) + mem[P]++; + continue; + } + + if (inst == 0140511) { + fprintf(stderr," FSNZ\n"); + if (*(int *)(mem+FLTH) != 0 || mem[FEXP] != 0) + mem[P]++; + continue; + } + + if (inst == 0140512) { + fprintf(stderr," FSMI\n"); + if (*(int *)(mem+FLTH) < 0) + mem[P]++; + continue; + } + + if (inst == 0140513) { + fprintf(stderr," FSPL\n"); + if (*(int *)(mem+FLTH) >= 0) + mem[P]++; + continue; + } + + if (inst == 0140514) { + fprintf(stderr," FSLE\n"); + if (*(int *)(mem+FLTH) < 0 || (*(int *)(mem+FLTH) == 0 && mem[FEXP] == 0)) + mem[P]++; + continue; + } + + if (inst == 0140515) { + fprintf(stderr," FSGT\n"); + if (*(int *)(mem+FLTH) >= 0 && (*(int *)(mem+FLTH) != 0 || mem[FEXP] != 0)) + mem[P]++; + continue; + } + + if (inst == 0140554) { + fprintf(stderr," INT\n"); + *(int *)&tempf = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + templ = tempf; + mem[B] = templ & 0x7FFF; + mem[A] = templ >> 15; + continue; + } + + if (inst == 0141414) { + fprintf(stderr," ILE\n"); + templ = *(int *)(mem+A); + *(int *)(mem+A) = *(int *)(mem+E); + *(int *)(mem+E) = templ; + continue; + } + + if (inst == 0141707) { + fprintf(stderr," BMLT\n"); + if (keys & 020000) + goto bclt; + mem[P]++; + continue; + } + + if (inst == 0141711) { + fprintf(stderr," BMLE\n"); + if (keys & 020000) + goto bcle; + mem[P]++; + continue; + } + + if (inst == 0141602) { + fprintf(stderr," BMEQ\n"); + if (keys & 020000) + goto bceq; + mem[P]++; + continue; + } + + if (inst == 0141603) { + fprintf(stderr," BMNE\n"); + if (keys & 020000) + goto bcne; + mem[P]++; + continue; + } + + if (inst == 0141606) { + fprintf(stderr," BMGE\n"); + if (keys & 020000) + goto bcge; + mem[P]++; + continue; + } + + if (inst == 0141710) { + fprintf(stderr," BMGT\n"); + if (keys & 020000) + goto bcgt; + mem[P]++; + continue; + } + fprintf(stderr," unrecognized generic class 3 instruction!\n"); + if (mem[066] != 0) { + fprintf(stderr," JST* '66 [%o]\n", mem[066]); + mem[mem[066]] = mem[P]; + mem[P] = mem[066]+1; + continue; + } + exit(1); } @@ -1439,19 +1747,36 @@ lcgt: } break; - case 00100: /* LRS (s.b. different in R/V modes) */ + case 00100: /* LRS (different in R & V modes) */ fprintf(stderr," LRS %d\n", scount); - if (scount <= 32) { - templ = *(int *)(mem+A); - SETC(templ & bitmask32[33-scount]); - templ = templ >> scount; - *(int *)(mem+A) = templ; - } else if (mem[A] & 0x8000) { - *(int *)(mem+A) = 0xFFFFFFFF; - SETC(1); + if (keys & 010000) { /* V/I mode */ + if (scount <= 32) { + templ = *(int *)(mem+A); + SETC(templ & bitmask32[33-scount]); + templ = templ >> scount; + *(int *)(mem+A) = templ; + } else if (mem[A] & 0x8000) { + *(int *)(mem+A) = 0xFFFFFFFF; + SETC(1); + } else { + *(int *)(mem+A) = 0; + SETC(0); + } } else { - *(int *)(mem+A) = 0; - SETC(0); + if (scount <= 31) { + templ = mem[A]; + templ = (templ<<16) | (mem[B]<<1); + SETC(templ & bitmask32[32-scount]); + templ = templ >> (scount+1); + mem[A] = templ >> 15; + mem[B] = templ & 0x7FFF; + } else if (mem[A] & 0x8000) { + *(int *)(mem+A) = 0xFFFF7FFF; + SETC(1); + } else { + *(int *)(mem+A) = 0; + SETC(0); + } } break; @@ -1496,8 +1821,7 @@ lcgt: case 00600: /* ARR */ fprintf(stderr," ARR %d\n", scount); - while (scount > 16) - scount = scount - 16; + scount = ((scount-1)%16)+1; /* make scount 1-16 */ SETC(mem[A] & bitmask16[17-scount]); mem[A] = (mem[A] >> scount) | (mem[A] << (16-scount)); break; @@ -1515,16 +1839,36 @@ lcgt: } break; - case 01100: /* LLS (s.b. different in R/V modes) */ + case 01100: /* LLS (different in R/V modes) */ fprintf(stderr," LLS %d\n", scount); - if (scount <= 32) { - templ = *(int *)(mem+A); - SETC(templ & bitmask32[scount]); - templ = templ << scount; - *(int *)(mem+A) = templ; + if (keys & 010000) { /* V/I mode */ + if (scount < 32) { + templ = 0x80000000; + templ = templ >> scount; /* create mask */ + templ = templ & *(int *)(mem+A); /* grab bits */ + templ = templ >> (31-scount); /* extend them */ + SETC(!(templ == -1 || templ == 0)); + *(int *)(mem+A) = *(int *)(mem+A) << scount; + } else { + *(int *)(mem+A) = 0; + SETC(0); + } } else { - *(int *)(mem+A) = 0; - SETC(0); + if (scount < 31) { + templ = mem[A]; + templ = (templ<<16) | (mem[B]<<1); + templ2 = 0x80000000; + templ2 = templ2 >> scount; /* create mask */ + templ2 = templ2 & templ; /* grab bits */ + templ2 = templ2 >> (31-scount); /* extend them */ + SETC(!(templ2 == -1 || templ2 == 0)); + templ = templ << scount; + mem[A] = templ >> 16; + mem[B] = (templ >> 1) & 0x7FFF; + } else { + *(int *)(mem+A) = 0; + SETC(0); + } } break; @@ -1539,8 +1883,7 @@ lcgt: break; case 01400: /* ALL */ - case 01500: /* ALS */ - fprintf(stderr," ALL/ALS %d\n", scount); + fprintf(stderr," ALL %d\n", scount); if (scount <= 16) { SETC(mem[A] & bitmask16[scount]); mem[A] = mem[A] << scount; @@ -1550,10 +1893,26 @@ lcgt: } break; + case 01500: /* ALS */ + fprintf(stderr," ALS %d\n", scount); + if (scount <= 15) { + tempa = 0100000; + tempa = tempa >> scount; /* create mask */ + tempa = tempa & mem[A]; /* grab bits */ + tempa = tempa >> (15-scount); /* extend them */ + SETC(!(tempa == -1 || tempa == 0)); + mem[A] = mem[A] << scount; + } else if (mem[A] == 0) { + SETC(0); + } else { + mem[A] = 0; + SETC(1); + } + break; + case 01600: /* ALR */ fprintf(stderr," ALR %d\n", scount); - while (scount > 16) - scount = scount - 16; + scount = ((scount-1)%16)+1; /* make scount 1-16 */ SETC(mem[A] & bitmask16[scount]); mem[A] = (mem[A] << scount) | (mem[A] >> (16-scount)); break; @@ -1580,14 +1939,14 @@ lcgt: } if (inst == 0101400) { - fprintf(stderr," SMI\n"); + fprintf(stderr," SMI/SLT\n"); if (*(short *)(mem+A) < 0) mem[P]++; continue; } if (inst == 0100400) { - fprintf(stderr," SPL\n"); + fprintf(stderr," SPL/SGE\n"); if (*(short *)(mem+A) >= 0) mem[P]++; continue; @@ -1608,14 +1967,14 @@ lcgt: } if (inst == 0101040) { - fprintf(stderr," SNZ\n"); + fprintf(stderr," SNZ/SNE\n"); if (mem[A] != 0) mem[P]++; continue; } if (inst == 0100040) { - fprintf(stderr," SZE\n"); + fprintf(stderr," SZE/SEQ\n"); if (mem[A] == 0) mem[P]++; continue; @@ -1676,8 +2035,6 @@ lcgt: exit(1); } - fprintf(stderr," SR-mode MR decode\n"); - /* pio? */ if ((inst & 036000) == 030000) { @@ -1747,7 +2104,7 @@ lcgt: exit(1); } - fprintf(stderr," ea=%o, [ea]='%o/%d\n", ea, mem[ea], *(short *)(mem+ea)); + fprintf(stderr," ea=%o (%o/%o), [ea]='%o/%d\n", ea, ea>>16, ea & 0xFFFF, mem[ea], *(short *)(mem+ea)); if (opcode == 00100) { fprintf(stderr," JMP\n"); @@ -1766,17 +2123,10 @@ lcgt: continue; } - if (opcode == 00300) { - fprintf(stderr," ANA\n"); - mem[A] &= mem[ea]; - continue; - } - if (opcode == 00400) { if ((keys & 050000) == 040000) { fprintf(stderr," DST\n"); - mem[ea] = mem[A]; - mem[ea+1] = mem[B]; + *(unsigned int *)(mem+ea) = *(unsigned int *)(mem+A); } else { fprintf(stderr," STA\n"); mem[ea] = mem[A]; @@ -1784,6 +2134,52 @@ lcgt: continue; } + if (opcode == 00600) { + utempa = mem[A]; + if ((keys & 050000) == 040000) { + fprintf(stderr," DAD\n"); + mem[B] += mem[ea+1]; + if (mem[B] & 0x8000) { + mem[A]++; + mem[B] &= 0x7fff; + } + mem[A] += mem[ea]; + SETCC_L; + } else { + fprintf(stderr," ADD\n"); + *(short *)(mem+A) += *(short *)(mem+ea); + SETCC_A; + } + SETC(((~utempa ^ mem[ea]) & (utempa ^ mem[A])) & 0x8000); + continue; + } + + if (opcode == 00700) { + utempa = mem[A]; + if ((keys & 050000) == 040000) { + fprintf(stderr," DSB\n"); + mem[B] -= mem[ea+1]; + if (mem[B] & 0x8000) { + mem[A]--; + mem[B] &= 0x7fff; + } + mem[A] -= mem[ea]; + SETCC_L; + } else { + fprintf(stderr," SUB\n"); + *(short *)(mem+A) -= *(short *)(mem+ea); + SETCC_A; + } + SETC(((~utempa ^ mem[ea]) & (utempa ^ mem[A])) & 0x8000); + continue; + } + + if (opcode == 00300) { + fprintf(stderr," ANA\n"); + mem[A] &= mem[ea]; + continue; + } + if (opcode == 00500) { fprintf(stderr," ERA\n"); mem[A] ^= mem[ea]; @@ -1796,38 +2192,6 @@ lcgt: continue; } - if (opcode == 00600) { - if ((keys & 050000) == 040000) { - fprintf(stderr," DAD\n"); - mem[B] += mem[ea+1]; - if (mem[B] & 0x8000) { - mem[A]++; - mem[B] &= 0x7fff; - } - mem[A] += mem[ea]; - } else { - fprintf(stderr," ADD\n"); - *(short *)(mem+A) += *(short *)(mem+ea); - } - continue; - } - - if (opcode == 00700) { - if ((keys & 050000) == 040000) { - fprintf(stderr," DSB\n"); - mem[B] -= mem[ea+1]; - if (mem[B] & 0x8000) { - mem[A]--; - mem[B] &= 0x7fff; - } - mem[A] -= mem[ea]; - } else { - fprintf(stderr," SUB\n"); - *(short *)(mem+A) -= *(short *)(mem+ea); - } - continue; - } - if (opcode == 01000) { fprintf(stderr," JST\n"); mem[ea] = mem[P]; @@ -1866,7 +2230,7 @@ compskip: } if (opcode == 01400) { - /* if V-mode, JSY, else LDX in R-mode */ + /* if V-mode, JSY, else (LDX in R-mode?) */ fprintf(stderr," JSY/LDX\n"); exit(1); } @@ -1894,12 +2258,8 @@ compskip: if (keys & 010000) { /* V/I mode */ templ = *(int *)(mem+A); } else { /* R/S mode */ - if (mem[A] != 0 && mem[A] != 0xffff) { - fprintf(stderr," Register A should be 0 or -1 before R-mode DIV\n"); - exit(1); - } - tempa = mem[B] | (mem[A] & 0x8000); - templ = tempa; /* extend to 32-bits */ + templ = mem[A]; /* convert to 32-bit signed */ + templ = mem[B] | (templ<<15); } mem[A] = templ / *(short *)(mem+ea); mem[B] = templ % *(short *)(mem+ea); @@ -2024,7 +2384,7 @@ compskip: } else { fprintf(stderr," JDX\n"); mem[X]--; - if (mem[X] == 0) + if (mem[X] != 0) mem[P] = ea; } continue; @@ -2032,27 +2392,27 @@ compskip: if (opcode == 03502) { fprintf(stderr," STY\n"); - exit(1); + mem[ea] = mem[Y]; continue; } if (opcode == 01503) { fprintf(stderr," JIX\n"); mem[X]++; - if (mem[X] == 0) + if (mem[X] != 0) mem[P] = ea; continue; } if (opcode == 01501) { fprintf(stderr," FLX\n"); - mem[X] = mem[ea]*2; + mem[X] = mem[ea] * 2; continue; } if (opcode == 03501) { fprintf(stderr," LDY\n"); - exit(1); + mem[Y] = mem[ea]; continue; } @@ -2072,6 +2432,237 @@ compskip: goto compskip; } + if (opcode == 00601) { + fprintf(stderr," FAD\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + 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 = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + *(int *)&tempf1 = *(int *)(mem+ea); + prieee4(&tempf1); + tempf += tempf1; + ieeepr4(&tempf); + mem[FLTH] = (*(unsigned int *)&tempf) >> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + SETC(0); + continue; + } + + if (opcode == 01101) { + fprintf(stderr," FCS\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + 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 = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + *(int *)&tempf1 = *(int *)(mem+ea); + prieee4(&tempf1); + tempf -= tempf1; + keys &= ~0300; + if (tempf < 0.0) + keys |= 0200; + else if (tempf == 0.0) + keys |= 0100; + goto compskip; + } + + if (opcode == 01701) { + fprintf(stderr," FDV\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + 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 = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + *(int *)&tempf1 = *(int *)(mem+ea); + prieee4(&tempf1); + tempf /= tempf1; + ieeepr4(&tempf); + mem[FLTH] = (*(unsigned int *)&tempf) >> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + SETC(0); + continue; + } + + if (opcode == 0201) { + fprintf(stderr," FLD\n"); + mem[FLTH] = mem[ea]; + mem[FLTL] = mem[ea+1] & 0xFF00; + mem[FEXP] = mem[ea+1] & 0xFF; + continue; + } + + if (opcode == 01601) { + fprintf(stderr," FMP\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + 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 = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + *(int *)&tempf1 = *(int *)(mem+ea); + prieee4(&tempf1); + tempf *= tempf1; + ieeepr4(&tempf); + mem[FLTH] = (*(unsigned int *)&tempf) >> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + SETC(0); + continue; + } + + if (opcode == 00701) { + fprintf(stderr," FSB\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + 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 = (mem[FLTH]<<16) | (mem[FLTL] & 0xFF00) | (mem[FEXP] & 0xFF); + prieee4(&tempf); + *(int *)&tempf1 = *(int *)(mem+ea); + prieee4(&tempf1); + tempf -= tempf1; + ieeepr4(&tempf); + mem[FLTH] = (*(unsigned int *)&tempf) >> 16; + mem[FLTL] = (*(unsigned int *)&tempf) & 0xFF00; + mem[FEXP] = (*(unsigned int *)&tempf) & 0xFF; + SETC(0); + continue; + } + + if (opcode == 0401) { + fprintf(stderr," FST\n"); + if (mem[FEXP] & 0xFF00) + cpuexception('f'); + mem[ea] = mem[FLTH]; + mem[ea+1] = (mem[FLTL] & 0xFF00) | mem[FEXP]; + continue; + } + + if (opcode == 0602) { + fprintf(stderr," DFAD\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = mem[FLTD]; + tempda[3] = mem[FEXP]; + prieee8(tempda); + tempd = *(double *)(mem+ea); + prieee8(&tempd); + *(double *)tempda += tempd; + ieeepr8(tempda); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FLTD] = tempda[2]; + mem[FEXP] = tempda[3]; + SETC(0); + continue; + } + + if (opcode == 01102) { + fprintf(stderr," DFCS\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = mem[FLTD]; + tempda[3] = mem[FEXP]; + prieee8(tempda); + tempd = *(double *)(mem+ea); + prieee8(&tempd); + *(double *)tempda -= tempd; + keys &= ~0300; + if (*(double *)tempda < 0.0) + keys |= 0200; + else if (*(double *)tempda == 0.0) + keys |= 0100; + goto compskip; + } + + if (opcode == 01702) { + fprintf(stderr," DFDV\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = mem[FLTD]; + tempda[3] = mem[FEXP]; + prieee8(tempda); + tempd = *(double *)(mem+ea); + prieee8(&tempd); + *(double *)tempda /= tempd; + ieeepr8(tempda); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FLTD] = tempda[2]; + mem[FEXP] = tempda[3]; + SETC(0); + continue; + } + + if (opcode == 0202) { + fprintf(stderr," DFLD\n"); + *(double *)tempda = *(double *)(mem+ea); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FLTD] = tempda[2]; + mem[FEXP] = tempda[3]; + continue; + } + + if (opcode == 01602) { + fprintf(stderr," DFMP\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = mem[FLTD]; + tempda[3] = mem[FEXP]; + prieee8(tempda); + tempd = *(double *)(mem+ea); + prieee8(&tempd); + *(double *)tempda *= tempd; + ieeepr8(tempda); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FLTD] = tempda[2]; + mem[FEXP] = tempda[3]; + SETC(0); + continue; + } + + if (opcode == 0702) { + fprintf(stderr," DFSB\n"); + fprintf(stderr," FEXP=%d (dec), FLTH='%o, FLTL='%o\n", mem[FEXP], mem[FLTH], mem[FLTL]); + fprintf(stderr," ea EXP=%d (dec), ea H='%o, ea L='%o\n", (mem[ea+1] & 0xFF), mem[ea], (mem[ea+1] & 0xFF00)); + tempda[0] = mem[FLTH]; + tempda[1] = mem[FLTL]; + tempda[2] = mem[FLTD]; + tempda[3] = mem[FEXP]; + prieee8(tempda); + tempd = *(double *)(mem+ea); + prieee8(&tempd); + *(double *)tempda -= tempd; + ieeepr8(tempda); + mem[FLTH] = tempda[0]; + mem[FLTL] = tempda[1]; + mem[FLTD] = tempda[2]; + mem[FEXP] = tempda[3]; + SETC(0); + continue; + } + + if (opcode == 0402) { + fprintf(stderr," DFST\n"); + mem[ea] = mem[FLTH]; + mem[ea+1] = mem[FLTL]; + mem[ea+2] = mem[FLTD]; + mem[ea+3] = mem[FEXP]; + continue; + } + + if (mem[066] != 0) { + fprintf(stderr," JST* '66 [%o]\n", mem[066]); + mem[mem[066]] = mem[P]; + mem[P] = mem[066]+1; + continue; + } fprintf(stderr," UNKNOWN OPCODE: %o\n", opcode); exit(1); } @@ -2360,6 +2951,15 @@ svc() { else goto badsvc; + /* if location '65 is set, do indirect JST to handle svc */ + + if (mem[065] != 0) { + fprintf(stderr," JST* '65 [%o]\n", mem[065]); + mem[mem[065]] = mem[P]; + mem[P] = mem[065]+1; + return; + } + if (svcinfo[class][func].numargs == 99) goto badsvc; @@ -2691,10 +3291,6 @@ badsvc: /* here for PIO instructions: OCP, SKS, INA, OTA. The instruction word is passed in as an argument to handle EIO (Execute I/O) in V-mode. - - Devices emulated by Primos in ks/ptrap.ftn: - '04 = console, '01 = paper tape reader, '02 = paper tape punch, - '20 = control panel */ pio(unsigned int inst) { @@ -2705,9 +3301,11 @@ pio(unsigned int inst) { class = inst >> 14; func = (inst >> 6) & 017; device = inst & 077; - fprintf(stderr," pio, class=%d, func=%o, device=%o\n", class, func, device); + fprintf(stderr," pio, class=%d, func='%o, device='%o\n", class, func, device); if (devmap[device]) devmap[device](class, func, device); - else - fprintf(stderr," no handler for device; instruction ignored\n"); + else { + fprintf(stderr," no handler for device\n"); + exit(1); + } } diff --git a/emdev.h b/emdev.h index 3b3537c..69d0ba6 100644 --- a/emdev.h +++ b/emdev.h @@ -6,50 +6,95 @@ OCP instructions never skip SKS instructions skip on specified conditions INA/OTA instructions skip if they succeed (data was read/written) + + Device numbers: + '01 = paper tape reader + '02 = paper tape punch + '03 = 1st MPC (line printer/card reader/card punch) + '04 = SOC board (system console/user terminal) + '05 = 2nd MPC (line printer/card reader/card punch) + '06 = card punch? (RTOS User Guide, A-1) / IPC (Engr Handbook p.101) + '07 = PNC + '12 = diskette + '13 = 2nd magtape controller + '14 = 1st magtape controller + '20 = control panel / real-time clock + '21 = 1st 4002 disk controller + '22 = obsolete: fixed head disk + '23 = obsolete: 30MB disk + '24 = tag monitor (tmain.pma) / writable control store + '25 = obsolete: moving head disk + '26 = 1st disk controller + '27 = 2nd disk controller + '30-32 = BPIOC #1-3 (RTOS User Guide, A-1) + '33 = 1st Versatec (verdim) + '34 = 2nd Versatec + '35 = 4th AMLC + '36-37 = ELFBUS #1 & 2 + '40 = A/D converter type 6000 + '41 = digital input type 6020 + '42 = digital input #2 + '43 = digital output type 6040 + '44 = digital output #2 + '45 = D/A converter type 6060 (analog output) + '50 = 1st HSSMLC (cs/slcdim.pma) + '51 = 2nd HSSMLC + '52 = 3rd AMLC + '53 = 2nd AMLC + '54 = 1st AMLC + '55 = MACI autocall unit + '56 = old SMLC (RTOS User Guide, A-1) + '60-67 = reserved for user devices + '70-'73 = Megatek graphics terminals + + Devices emulated by Primos in ks/ptrap.ftn: + '04 = console, '01 = paper tape reader, '02 = paper tape punch, + '20 = control panel */ #include +#include void devnull (short class, short func, short device) { switch (class) { case 0: - fprintf(stderr," OCP '%2#0o%2#0o\n", func, device); + fprintf(stderr," OCP '%02o%02o\n", func, device); if (func == 0) { ; } else { - fprintf(stderr," unimplemented OCP device %2#0o function\n", device); + fprintf(stderr," unimplemented OCP device '%02o function\n", device); exit(1); } break; case 1: - fprintf(stderr," SKS '%2#0o%2#0o\n", func, device); + fprintf(stderr," SKS '%02o%02o\n", func, device); if (func == 0) mem[P]++; /* assume it's always ready */ else { - fprintf(stderr," unimplemented SKS device %2#0o function\n", device); + fprintf(stderr," unimplemented SKS device '%02o function\n", device); exit(1); } break; case 2: - fprintf(stderr," INA '%2#0o%2#0o\n", func, device); + fprintf(stderr," INA '%02o%02o\n", func, device); if (func == 0) { ; } else { - fprintf(stderr," unimplemented INA device %2#0o function\n", device); + fprintf(stderr," unimplemented INA device '%02o function\n", device); exit(1); } break; case 3: - fprintf(stderr," OTA '%2#0o%2#0o\n", func, device); + fprintf(stderr," OTA '%02o%02o\n", func, device); if (func == 0 | func == 1) { mem[P]++; /* OTA '0004 always works on Unix */ } else { - fprintf(stderr," unimplemented OTA device %2#0o function\n", device); + fprintf(stderr," unimplemented OTA device '%02o function\n", device); exit(1); } break; @@ -87,11 +132,11 @@ void devasr (short class, short func, short device) { switch (class) { case 0: - fprintf(stderr," OCP '%2#0o%2#0o\n", func, device); + fprintf(stderr," OCP '%02o%02o\n", func, device); break; case 1: - fprintf(stderr," SKS '%2#0o%2#0o\n", func, device); + fprintf(stderr," SKS '%02o%02o\n", func, device); if (func <= 7) mem[P]++; /* assume it's always ready */ else { @@ -101,7 +146,7 @@ void devasr (short class, short func, short device) { break; case 2: - fprintf(stderr," INA '%2#0o%2#0o\n", func, device); + fprintf(stderr," INA '%02o%02o\n", func, device); if (func == 0 || func == 010) { if (fcntl(ttydev, F_GETFL, ttyflags) == -1) { perror(" unable to get tty flags"); @@ -143,7 +188,7 @@ void devasr (short class, short func, short device) { break; case 3: - fprintf(stderr," OTA '%2#0o%2#0o\n", func, device); + fprintf(stderr," OTA '%02o%02o\n", func, device); if (func == 0) { fprintf(stderr," char to write=%o\n", mem[A]); putchar(mem[A] & 0x7f); @@ -162,6 +207,40 @@ void devasr (short class, short func, short device) { +/* Device '14 - magtape controller #1 + */ + +void devmt (short class, short func, short device) { + + switch (class) { + + case 0: + fprintf(stderr," OCP '%02o%02o\n", func, device); + break; + + case 1: + fprintf(stderr," SKS '%02o%02o\n", func, device); + break; + + case 2: + fprintf(stderr," INA '%02o%02o\n", func, device); + if (mem[mem[P]] == 03776) { /* JMP *-1 -> blocking read */ + fprintf(stderr," Device not supported, so I/O hangs\n"); + exit(1); + } + break; + + case 3: + fprintf(stderr," OTA '%02o%02o\n", func, device); + if (mem[mem[P]] == 03776) { /* JMP *-1 -> blocking read */ + fprintf(stderr," Device not supported, so I/O hangs\n"); + exit(1); + } + break; + } +} + + /* Device '20: control panel switches and lights OTA '1720 = write to lights (sets CP fetch address) @@ -174,33 +253,34 @@ void devcp (short class, short func, short device) { switch (class) { case 0: - fprintf(stderr," OCP '%2#0o%2#0o\n", func, device); - fprintf(stderr," unimplemented OCP device %2#0o function\n", device); + fprintf(stderr," OCP '%02o%02o\n", func, device); + fprintf(stderr," unimplemented OCP device '%02o function\n", device); exit(1); break; case 1: - fprintf(stderr," SKS '%2#0o%2#0o\n", func, device); - fprintf(stderr," unimplemented SKS device %2#0o function\n", device); + fprintf(stderr," SKS '%02o%02o\n", func, device); + fprintf(stderr," unimplemented SKS device '%02o function\n", device); exit(1); break; case 2: - fprintf(stderr," INA '%2#0o%2#0o\n", func, device); + fprintf(stderr," INA '%02o%02o\n", func, device); if (func == 016) { + mem[A] = 014114; mem[A] = 0; } else { - fprintf(stderr," unimplemented INA device %2#0o function\n", device); + fprintf(stderr," unimplemented INA device '%02o function\n", device); exit(1); } break; case 3: - fprintf(stderr," OTA '%2#0o%2#0o\n", func, device); + fprintf(stderr," OTA '%02o%02o\n", func, device); if (func == 017) { /* write lights */ mem[P]++; } else { - fprintf(stderr," unimplemented OTA device %2#0o function\n", device); + fprintf(stderr," unimplemented OTA device '%02o function\n", device); exit(1); } break; @@ -208,3 +288,196 @@ void devcp (short class, short func, short device) { } +/* disk controller at '26 and '27 + + NOTES: + - in the DSEL disk channel program command, unit number is a 4-bit field, + with these binary values: + 0001 = unit 0 (pdev 460/461) + 0010 = unit 1 (pdev 462/463) + 0100 = unit 2 (pdev 464/465) + 1000 = unit 3 (pdev 466/467) + + OCP '1626 = reset interrupt + OCP '1726 = reset controller + + INA '1126 = input ID, don't clear A first, fails if no controller + INA '1726 = read status (or something), fails if controller busy + + OTA '1726 = load OAR (Order Address Register), ie, run channel + program, address is in A + + */ + +void devdisk (short class, short func, short device) { + unsigned short oar; + unsigned short status; /* actual status */ + unsigned short teststatus; /* status for order testing */ + unsigned short memaddr; + unsigned short order; + short halt; + short unit; + short head, track, rec, recsize, nwords; + unsigned short dmachan, dmanch, dmaaddr; + short dmanw; + char ordertext[8]; + char devfile[8]; + char devopened[8]; /* device file that is open on devfd */ + static int devfd=-1; /* device file descriptor */ + int theads, spt, phyra; + switch (class) { + + case 0: + fprintf(stderr," OCP '%2o%2o\n", func, device); + break; + + case 1: + fprintf(stderr," SKS '%2o%2o\n", func, device); + break; + + case 2: + fprintf(stderr," INA '%2o%2o\n", func, device); + if (func == 01) /* read device id, clear A first */ + mem[A] = device; + else if (func == 011) /* read device id, don't clear A */ + mem[A] |= device; + else if (func == 017) /* read status */ + mem[A] = 0100000; + mem[P]++; + break; + + case 3: + fprintf(stderr," OTA '%02o%02o\n", func, device); + if (func == 017) { /* set OAR (order address register) */ + oar = mem[A]; + halt = 0; + status = 0100000; + unit = -1; + while (!halt) { + order = mem[oar]>>12; + fprintf(stderr,"\n %o: %o %o %o\n", oar, mem[oar], mem[oar+1], mem[oar+2]); + if (mem[oar] & 04000) { /* "execute if ..." */ + if (order == 2 || order == 5 || order == 6) + oar += 3; + else + oar += 2; + continue; + } + switch (order) { + case 0: /* DHLT = Halt */ + halt = 1; + fprintf(stderr," channel program halt at '%o\n", oar); + break; + case 2: /* SFORM = Format */ + case 5: /* SREAD = Read */ + case 6: /* SWRITE = Write */ + recsize = mem[oar] & 017; + track = mem[oar+1] & 01777; + rec = mem[oar+2] >> 8; /* # records for format, rec # for R/W */ + head = mem[oar+2] & 077; + if (order == 2) + strcpy(ordertext,"Format"); + else if (order == 5) + strcpy(ordertext,"Read"); + else if (order == 6) + strcpy(ordertext,"Write"); + fprintf(stderr," %s, head=%d, track=%d, rec=%d, recsize=%d\n", ordertext, head, track, rec, recsize); + dmanw = mem[dmachan]; + dmanw = -(dmanw>>4); + dmaaddr = mem[dmachan+1]; + fprintf(stderr, " DMA channels: nch-1=%d, ['%o]='%o, ['%o]='%o, nwords=%d\n", dmanch, dmachan, mem[dmachan], dmachan+1, mem[dmachan+1], dmanw); + if (devfd == -1) { + fprintf(stderr," Unit not selected or not ready\n"); + status = 0100001; + } else if (order == 2) + fprintf(stderr," Format order not implemented\n"); + else if (order == 5) { + + /* translate head/track/sector to drive record address */ + + theads = 40; /* should get total heads from a config file */ + spt = 9; /* and sectors per track too */ + phyra = (track*theads*spt) + head*9 + rec; + fprintf(stderr, " phyra=%d, byte offset=%d\n", phyra, phyra*2080); + if (lseek(devfd, phyra*2080, SEEK_SET) == -1) { + perror("Unable to seek drive file"); + exit(1); + } + if (read(devfd, mem+dmaaddr, dmanw*2) != dmanw*2) { + perror("Unable to read drive file"); + exit(1); + } + mem[dmachan] = 0; + mem[dmachan+1] += dmanw; + + } else if (order == 6) + fprintf(stderr," Write order not implemented\n"); + oar += 3; + break; + case 3: /* SSEEK = Seek */ + track = mem[oar+1] & 01777; + fprintf(stderr," seek track %d, restore=%d, clear=%d\n", track, (mem[oar+1] & 0100000) != 0, (mem[oar+1] & 040000) != 0); + oar += 2; + break; + case 4: /* DSEL = Select unit */ + unit = (mem[oar+1] & 017) >> 1; /* unit = 0/1/2/4 */ + if (unit == 4) unit = 3; /* unit = 0/1/2/3 */ + snprintf(devfile,sizeof(devfile),"dev%ou%d", device, unit); + fprintf(stderr," select unit %d, filename %s\n", unit, devfile); + if (strcmp(devfile,devopened) != 0 || devfd == -1) { + if (devfd != -1) { + close(devfd); + devfd = -1; + } + if ((devfd = open(devfile, O_RDONLY, 0)) == -1) + status = 0100001; /* not ready */ + else + strcpy(devopened, devfile); + } + oar += 2; + break; + case 7: /* DSTALL = Stall */ + fprintf(stderr," stall\n"); + oar += 2; + break; + case 9: /* DSTAT = Store status to memory */ + memaddr = mem[oar+1]; + fprintf(stderr, " store status to '%o\n", memaddr); + mem[memaddr] = status; + oar += 2; + break; + case 11: /* DOAR = Store OAR to memory (2 words) */ + memaddr = mem[oar+1]; + fprintf(stderr, " store OAR to '%o\n", memaddr); + mem[memaddr] = oar; + oar += 2; + break; + case 13: /* SDMA = select DMA channel(s) to use */ + dmanch = mem[oar] & 017; + dmachan = mem[oar+1]; + fprintf(stderr, " set DMA channels, nch-1=%d, channel='%o\n", dmanch, dmachan); + oar += 2; + break; + case 14: /* DINT = generate interrupt through vector address */ + memaddr = mem[oar+1]; + fprintf(stderr, " interrupt through '%o\n", memaddr); + exit(1); + oar += 2; + break; + case 15: /* DTRAN = channel program jump */ + oar = mem[oar+1]; + fprintf(stderr, " jump to '%o\n", oar); + break; + default: + fprintf(stderr, " unrecognized channel order = %d\n", order); + exit(1); + } + } + mem[P]++; + } else { + fprintf(stderr," unimplemented OTA device '%02o function\n", device); + exit(1); + } + break; + } +} diff --git a/fp.c b/fp.c new file mode 100644 index 0000000..79551e3 --- /dev/null +++ b/fp.c @@ -0,0 +1,304 @@ +/* ** general conversion doc here, or (referenced) above. ***************** */ +/* doc exponent details here: (-1 & bin pt. placement by prieee) vs. + vs. (-2 by ieeepr()): note that + IEEE denormalized bin pxxxxxxx prime (relative to the 23 bits); + in ieeepr the trick is to treat normalized #'s as the special case. */ + + +void prieee4(xlongp) /* ****** convert from Prime to IEEE. ****** */ + long *xlongp; +{ + long xlong; + long sign; /* sign */ + long mant; /* mantissa: note this is signed: mant = -mant below */ + long exp; /* exponent */ + +/* note: when converting form Prime to IEEE, we need to check for exponent + underflow, but not for overflow. */ + + xlong = *xlongp; + mant = xlong & 0xffffff00; /* 24 bits: includes sign bit */ + sign = mant & 0x80000000; + mant >>= 8; /* ok to trash upper byte, which will get masked out. */ + if (sign) + mant = - mant; + /* now have 24 bit # w/ leading 0. */ + + exp = (xlong & 0x000000ff) - 1; /* exp now in excess 127 (IEEE) form. */ + + if (exp < 0) { + mant >>= 1; /* tiny tiny #; will get shifted once more below. */ + ++exp; /* Bring exp back up to 0. */ + } + else /* *** normalize the mantissa. If input Prime mantissa was already + noramalized, this loop will still execute once, unless input # + was -(2**n) in which case it will execute 0 times. This is + because Prime mantissas are 2's compliment, and powers of 2 + normalize differently when negated. Note no loop for 0 exp. */ + while (exp && !(mant & 0x00800000)) { + mant <<= 1; + --exp; + } + + /* we now have a 24 bit unsigned # w/ a leading 1. If the exponent is > 0, + we are all set: the resulting IEEE number will be normalized. This + leading (hidden) IEEE 1 will be masked out below. */ + if ( ! exp) /* result must be denormalized: shift 1 further to */ + mant >>= 1; /* include IEEE leading bit, which may be 0 or 1. */ + + mant &= 0x007fffff; + exp <<= 23; + *xlongp = sign | exp | mant; +} + + +void ieeepr4(xlongp) /* ****** convert from IEEE to Prime. ****** */ + long *xlongp; +{ + long xlong; + long sign; /* sign */ + long mant; /* mantissa: note this is signed: mant = -mant below */ + long exp; /* exponent */ + long templ; + +/* note: when converting form Prime to IEEE, we need to check for exponent + overflow, but not for underflow. */ + xlong = *xlongp; + + if ( ! (xlong & 0x7fffffff)) + *xlongp = 0; /* +0 or -0 */ + else { + sign = xlong & 0x80000000; + mant = (xlong & 0x007fffff) << 8; /* assume denormalized, adjust below */ + exp = (xlong & 0x7f800000) >> 23; /* still in excess 127 (IEEE) form. */ + if (exp == 0xff) { /* NaN (not a number) or +/- infinity? */ + if (mant == 0) { + /* +/- infinity. */ + if (sign == 0) + *xlongp = 0x7fffffff; /* largest Prime # in for +infinity. */ + else /* note: 0x800000ff cant be negated; */ + *xlongp = 0x800001ff; /* use - 0x7fffffff for -infinity. */ + } + else { + /* NaN (not a number) */ + if (sign == 0) + *xlongp = 0x539733ff; /* use 1.11111e+38 for NaN, since */ + else /* it stands out if printed. */ + *xlongp = 0xac68cdff; /* use -1.11111e+38 for -NaN. */ + } + } + else { /* actual number */ + if (exp != 0) { + if(mant != 0x7fffff00)/* Special case of mantissa value of all 1s*/ + mant = (mant >> 1) + 0x40000080; /* ieee normalized number: */ + /* shift to make room for */ + /* hidden leading 1 bit, 'or'*/ + /* it in and round truncated */ + /* LSBit up. */ + mant &= 0xffffff00; + } + exp += 2; /* exp now in excess 128 (Prime) form. */ + + if (sign != 0) /* sign bit of mant will be 0 at this point. */ + mant = - mant; + /* mant is now a 24 bit signed mantissa (shifted to Prime position) */ + + /* *** normalize the number. In most cases, the number will already + be normalized. Negative powers of 2 will be shifted once, since + they normalize differently. IEEE denormalized numbers can be + adjusted at most 2 bits, due to the excess 127 vs. 128 exponent and + binary point position differences (cant negate exponent). *** */ + while (exp && ((~(mant^(mant<<1))) & 0x80000000)) { + mant <<= 1; /* sign and next most significant */ + --exp; /* bit are equal: normalize. */ + } + if (exp > 0xff) { + if ( ! sign) + *xlongp = 0x7fffffff; /* largest Prime # in for +infinity. */ + else /* note: 0x800000ff cant be negated; */ + *xlongp = 0x800001ff; /* use - 0x7fffffff for -infinity. */ + } + else + *xlongp = mant | exp; /* mant is signed; */ + } + } +} + + +#define l1 0 +#define l0 1 + +/* ** general conversion doc here, or (referenced) above. ***************** */ +/* doc exponent details here: (-1 & bin pt. placement by prieee) vs. + vs. (-2 by ieeepr()): note that + IEEE denormalized bin pxxxxxxx prime (relative to the 23 bits); + in ieeepr the trick is to treat normalized #'s as the special case. */ + + +void prieee8(xlongp) /* ****** convert from Prime to IEEE. ****** */ + long *xlongp; +{ + long xlong1,xlong0; + long mant1,mant0; /* mantissa: these are signed: mant = -mant below */ + long sign; /* sign */ + long exp; /* exponent */ + +/* note: when converting REAL*8 form Prime to IEEE, we need to check for both + exponent underflow, and overflow. */ + + xlong1 = xlongp[l1]; /* high 4 bytes */ + xlong0 = xlongp[l0]; /* low 4 bytes */ + sign = xlong1 & 0x80000000; + mant1 = xlong1 >> 11; /* 48 bits, includes */ + mant0 = (xlong1 << 21) | ((xlong0 >> 11) & 0xfffe0); /* includes sign bit */ + + if ( ! mant0 && ! mant1) { /* zero (dirty or otherwise)? */ + xlongp[l1] = xlongp[l0] = 0; + return; /* return ****** */ + } + if (sign) { /* 2's comp mant1/mant0 pair */ + mant0 = - mant0; + mant1 = ~ mant1; + if ( ! mant0) + ++ mant1; /* mant0==0: have a carry fr. mant0 to mant1. */ + } + + /* now have 48 bit # w/ leading 0. */ + + exp = (xlong0 & 0xffff) - 0x80; /* convert 16 bit */ + if (exp & 0x8000) /* Prime exponent */ + exp |= 0xffff0000; /* from "excess 128" */ + else /* form to 2's */ + exp &= 0x0000ffff; /* complement form. */ + exp += 0x3ff; /* exp now in excess 1023 (IEEE) form. */ + + if (exp < -50) { /* Prime exp too small? */ + xlongp[l1] = xlongp[l0] = 0; /* closest IEEE is 0. */ + return; /* return ****** */ + } + + if (exp < 0) { + /* note: can still get 0, iff have leading (non sign bit) 0's */ + mant0 = (mant1 << 32+exp) | (mant0 >> -exp); /* mant >>= -exp; */ + mant1 >>= -exp; /* tiny tiny #; will get shifted once more below. */ + ++mant0; /* lsb will get lost below, since # is denormalized; round */ + if ( ! mant0) + ++mant1; + exp = 0; /* exp += -exp. */ + } + else /* *** normalize the mantissa. */ + while (exp && !(mant1 & 0x00100000)) { + mant1 <<= 1; + if (mant0 & 0x80000000) + mant1 |= 1; + mant0 <<= 1; + --exp; + } + + if (exp > 0x7fe) { + xlongp[l1] = sign | 0x7fefffff; /* Prime exp too big; closest */ + xlongp[l0] = 0xffffffff; /* closest IEEE is (+/-) max. */ + } + else { + /* we now have a 48 bit unsigned # w/ a leading 1. If the exponent is + > 0, we are all set: the resulting IEEE number will be normalized. + This leading (hidden) IEEE 1 will be masked out below. */ + if ( ! exp) { /* result must be denormalized: shift 1 further to */ + mant0 >>= 1; /* include IEEE leading bit, which may be 0 or 1. */ + if (mant1 & 1) + mant0 |= 0x80000000; + mant1 >>= 1; + } + mant1 &= 0x000fffff; + exp <<= 20; + xlongp[l1] = sign | exp | mant1; + xlongp[l0] = mant0; + } +} + + +void ieeepr8(xlongp) /* ****** convert from IEEE to Prime. ****** */ + long *xlongp; +{ + long xlong1,xlong0; + long mant1,mant0; /* mantissa: these are signed: mant = -mant below */ + long sign; /* sign */ + long exp; /* exponent */ + +/* note: when converting REAL*8 form Prime to IEEE, we dont need to check for + exponent overflow, or underflow. */ + xlong1 = xlongp[l1]; /* high 4 bytes */ + xlong0 = xlongp[l0]; /* low 4 bytes */ + + if ((xlong1 & 0x7fffffff) == 0 && xlong0 == 0) { + xlongp[l1] = xlongp[l0] = 0; /* +0 or -0 */ + return; /* return ****** */ + } + sign = xlong1 & 0x80000000; + exp = (xlong1 & 0x7ff00000) >> 20; /* still in excess 1023 (IEEE) form. */ + mant1 = ((xlong1 & 0xfffff) << 11) | ((xlong0 >> 21) & 0x7ff); + mant0 = xlong0 << 11; /* assume denormalized, adjust below */ + if (exp == 0x7ff) { /* NaN (not a number) or +/- infinity? */ + if (mant1 == 0 && mant0 == 0) { + /* +/- infinity. */ + if (sign == 0) { + xlongp[l1] = 0x7fffffff; /* largest Prime # in for +infinity. */ + xlongp[l0] = 0xffffffff; + } + else { /* note: 0x80000000 0000ffff cant be */ + xlongp[l1] = 0x80000000; /* negated, use -0x7fffffff ffffffff */ + xlongp[l0] = 0x0001ffff; /* -infinity. */ + } + } + else { + /* NaN (not a number) */ + if (sign == 0) { + xlongp[l1] = 0x7fffffff; /* For now, use +/- infinity values */ + xlongp[l0] = 0xffffffff; /* for +/- NaN. */ + } + else { + xlongp[l1] = 0x80000000; + xlongp[l0] = 0x0001ffff; + } + } + } + else { /* actual number */ + if (exp != 0) { + /* ieee normalized number: shift mantissa to make room for hidden */ + mant0 >>= 1; /* leading 1 bit and 'or' it in. */ + if (mant1 & 1) + mant0 |= 0x80000000; + else + mant0 &= 0x7fffffff; + mant1 >>= 1; + mant1 |= 0x40000000; + } + exp -= 894; /* exp now in 'excess 128' (Prime) form. */ + + mant0 &= 0xffff0000; + if (sign) { /* sign bit of mant will be 0 at this point. */ + mant0 |= 0xffff; /* 2's comp mant1/mant0 pair */ + mant0 = - mant0; + mant1 = ~ mant1; + if ( ! mant0) + ++ mant1; /* mant0==0: have a carry fr. mant0 to mant1. */ + } + /* mant is now a 48 bit signed mantissa (shifted to Prime position) */ + + /* *** normalize the number. In most cases, the number will already + be normalized. Negative powers of 2 will be shifted once, since + they normalize differently. IEEE denormalized numbers can be + adjusted at most 2 bits, due to the excess 127 vs. 128 exponent and + binary point position differences (cant negate exponent). *** */ + while (exp && ((~(mant1^(mant1<<1))) & 0x80000000)) { + mant1 <<= 1; /* sign and next most significant */ + if (mant0 & 0x80000000) /* bit are equal: normalize. */ + mant1 |= 1; + mant0 <<= 1; + --exp; + } + mant0 &= 0xffff0000; + xlongp[l1] = mant1; /* mant is signed; no sign to 'or' in. */ + xlongp[l0] = mant0 | exp; + } +} diff --git a/os.c b/os.c index c1086ce..c1506e6 100644 --- a/os.c +++ b/os.c @@ -125,6 +125,7 @@ os_rdtk$$(short *key, short *info, char *buf, short *buflen, short *code) { } os_t1ou(short *charg) { + fprintf(stderr," Character is '%o/%d, Prime is '%o/%d, (%c)\n", *charg, *charg, *charg & 0x7f, *charg & 0x7f, *charg & 0x7f); putchar(*charg & 0x7f); fflush(stdout); } @@ -156,8 +157,13 @@ os_timdat(short *userbuf, short *n) { tod = time(NULL); localtime_r(&tod, &tms); strncpy(timbuf.mmddyy,"042105",6); +#if 0 timbuf.timemins = tms.tm_hour*60 + tms.tm_min; timbuf.timesecs = tms.tm_sec; +#else + timbuf.timemins = 0; + timbuf.timesecs = 0; +#endif timbuf.timeticks = 0; timbuf.cpusecs = timbuf.cputicks = timbuf.iosecs = timbuf.ioticks = 0; timbuf.tickspersec = 330;