From ff3fd6893587a3d9bda4738dcdbe363f828390d3 Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 28 Apr 2005 00:00:00 -0400 Subject: [PATCH] condition code macros mem array is segment addressable start of boot support use CC macros and BCxx to emulate Bxyy (eg, BFLT) use CC macros and LCxx to emulate Lxyy (eg, LFLT) shift instruction work --- em.c | 1474 ++++++++++++++++++++++++++++++++++++++++--------------- emdev.h | 150 +++++- os.c | 180 +++++++ os.h | 8 + 4 files changed, 1408 insertions(+), 404 deletions(-) create mode 100644 os.c create mode 100644 os.h diff --git a/em.c b/em.c index 9ee9eec..01e0a78 100644 --- a/em.c +++ b/em.c @@ -2,8 +2,7 @@ Copyright (C) 2005, Jim Wilcoxson (jim@meritnet.com). All Rights Reserved. Restores a Prime R-mode .save image from stdin to memory and - emulates execution. This version supports 16S, 32S, 32R, and 64R, - though only 1 32R program has been tested. + emulates execution. PLEASE NOTE: this is a very rough prototype still in development. The main goal for the prototype is to get an understanding of the @@ -62,6 +61,7 @@ #define FLTH 4 #define FLTL 5 #define FEXP 6 +#define VSC 6 #define P 7 #define PMAR 010 #define FCODE 011 @@ -81,20 +81,84 @@ see p. A-8 of Sys Arch */ -unsigned short mem[64*1024]; /* 64K words of main memory */ + +#define SETCC_A \ + keys &= ~0300; \ + if (*(short *)(mem+A) == 0) \ + keys |= 0100; \ + else if (*(short *)(mem+A) < 0) \ + keys |= 0200; + +#define SETCC_X \ + keys &= ~0300; \ + if (*(short *)(mem+X) == 0) \ + keys |= 0100; \ + else if (*(short *)(mem+X) < 0) \ + keys |= 0200; + +#define SETCC_L \ + keys & ~0300; \ + if (*(int *)(mem+A) == 0) \ + keys |= 0100; \ + else if (*(int *)(mem+A) < 0) \ + keys |= 0200; + +#define SETCC_F \ + keys & ~0300; \ + if (*(short *)(mem+FLTH) < 0) \ + keys |= 0200; \ + else if (*(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0) \ + keys |= 0100; + +#define SETC(onoff) \ + if ((onoff)) keys |= 0100000; \ + else keys &= 077777; + + +/* NOTES: + - mem is 1 user's virtual memory address space in this version, + but eventually should be the system's physical memory + - where to put the V/I mode live register file to make mapped + memory access to registers, easy? +*/ + +unsigned short mem[07776*64*1024]; /* 4095 segments of 64K words each */ + +unsigned int bitmask32[33] = {0, + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001}; + +unsigned int bitmask16[17] = {0, + 0x8000, 0x4000, 0x2000, 0x1000, + 0x0800, 0x0400, 0x0200, 0x0100, + 0x0080, 0x0040, 0x0020, 0x0010, + 0x0008, 0x0004, 0x0002, 0x0001}; + unsigned short prevpc,keys; /* program counter, prev pc, keys */ unsigned short amask; /* address mask */ +#define faultamask 0100000 /* fault bit */ +#define ringamask 060000 /* ring bits */ +#define extamask 010000 /* E-bit */ +#define segamask 07777 /* segment number */ + int verbose; int memdump; /* -memdump arg */ +int boot; /* true if reading a boot record */ /* I/O device map table, containing function pointers to handle device I/O */ #include "emdev.h" -void (*devmap[64])(unsigned short, unsigned short) = { +void (*devmap[64])(short, short, short) = { 0,0,0,0,devasr,0,0,0, 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, + devcp,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, @@ -134,10 +198,12 @@ newkeys (unsigned short new) { case 4: /* 32I */ fprintf(stderr,"Entering 32I mode, keys=%o\n", keys); amask = 0177777; + exit(1); break; case 6: /* 64V */ fprintf(stderr,"Entering 64V mode, keys=%o\n", keys); amask = 0177777; + exit(1); break; default: /* invalid */ fprintf(stderr,"Invalid CPU mode: %o\n", keys); @@ -306,11 +372,54 @@ special: return ea & amask; } -unsigned short ea64v (unsigned short inst, short i, short x, short *opcode) { - fprintf(stderr,"Mode 64V not implemented\n"); +unsigned int ea64v (unsigned short inst, short i, short x, short *opcode) { + + unsigned short ea_s; /* eff address segno */ + unsigned short ea_r; /* eff address ring */ + unsigned short ea_w; /* eff address wordno */ + unsigned short r; /* true if same ring */ + unsigned int ea; /* full seg/word va */ + + // ea_s = reg[pb.h] & segmask; + ea_w = mem[P]; + ea_r = 1; + if (inst & 001000) /* sector bit 7 set? */ + if ((inst & 0740) != 0400) { /* PC relative? */ + ea_w = mem[P] + (((short) (inst << 7)) >> 7); /* yes, sign extend D */ + fprintf(stderr," PC relative, P=%o, new ea_w=%o\n", mem[P], ea_w); + } + else + goto labB; /* special cases */ + else if (i) { + ea_w = (inst & 0777); /* sector 0 */ + fprintf(stderr," Sector 0, new ea_w=%o\n", ea_w); + if (ea_w < 0100 && x) { /* preindex by X */ + fprintf(stderr," Preindex, ea_w=%o, X='%o/%d\n", ea_w, mem[X], *(short *)(mem+X)); + ea_w += mem[X]; + fprintf(stderr," Preindex, new ea_w=%o\n", ea_w); + x = 0; + } + } else + goto labA; + + 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]); + } + if (x) { + fprintf(stderr," Postindex, old ea=%o, X='%o/%d\n", ea, mem[X], *(short *)(mem+X)); + ea += mem[X]; + fprintf(stderr," Postindex, new ea=%o\n", ea); + } + return ea; + +labA: +labB: + return ea; } -unsigned short ea32i (unsigned short inst, short i, short x) { +unsigned int ea32i (unsigned short inst, short i, short x) { fprintf(stderr,"Mode 32I not implemented\n"); } @@ -372,6 +481,8 @@ main (int argc, char **argv) { unsigned short utempa; signed int templ; unsigned int utempl; + float tempf; + double tempdf; unsigned int ea32; /* full V/I mode eff address */ unsigned short ea; /* effective address (word) */ unsigned short opcode; @@ -386,31 +497,53 @@ main (int argc, char **argv) { int instcount=0; + /* master clear: + - clear all registers + - set P to '1000 + - 16S mode, single precision + - interrupts and machine checks inhibited + - standard interrupt mode + */ + verbose = 0; memdump = 0; + boot = 0; /* check args */ for (i=1; i rvec[1]) { - fprintf(stderr,"Program start > EA: runfile is trashed\n"); - exit(1); + if (boot) { + rvec[0] = 0760; + rvec[1] = 0760+1040-1; + rvec[2] = 01000; + rvec[3] = rvec[4] = rvec[5] = 0; + rvec[6] = 0; + } else { + + /* read 9-word rvec header */ + + for (i=0; i<9; i++) + rvec[i] = readshort(); + fprintf(stderr,"SA=%o, EA=%o, P=%o, A=%o, B=%o, X=%o, K=%o\n\n", rvec[0], rvec[1], + rvec[2], rvec[3], rvec[4], rvec[5], rvec[6]); + if (rvec[2] > rvec[1]) { + fprintf(stderr,"Program start > EA: runfile is trashed\n"); + exit(1); + } } /* read memory image from SA to EA inclusive */ @@ -434,16 +567,16 @@ main (int argc, char **argv) { /* dump sector zero for debugging */ fprintf(stderr,"\nSector 0:\n"); - for (i=0; i<01000; i=i+8) - if (mem[i]|mem[i+1]|mem[i+2]|mem[i+3]|mem[i+4]|mem[i+5]|mem[i+6]|mem[i+7]) - fprintf(stderr,"%3o: %6o %6o %6o %6o %6o %6o %6o %6o\n", i, mem[i], mem[i+1], mem[i+2], mem[i+3], mem[i+4], mem[i+5], mem[i+6], mem[i+7]); + 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 (i=rvec[2]; i DLD (double load) + STA -> DST (double store) + ADD -> DAD (double add) + SUB -> DSB (double subtract) + + Other R-mode, 31-bit instructions include: + + PID, DIV, MPY, PIM, INT, FLOT + */ + if (inst == 000007) { /* DBL */ fprintf(stderr," DBL\n"); newkeys(keys | 040000); @@ -593,8 +735,7 @@ main (int argc, char **argv) { if (inst == 000115) { fprintf(stderr," PIDA\n"); - templ = *(short *)(mem+A); - *(int *)(mem+A) = templ; + *(int *)(mem+A) = *(short *)(mem+A); continue; } @@ -642,43 +783,61 @@ main (int argc, char **argv) { if (inst == 0141604) { fprintf(stderr," BCLT\n"); +bclt: if ((keys & 0300) == 0200) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0141600) { fprintf(stderr," BCLE\n"); +bcle: if (keys & 0300) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0141602) { fprintf(stderr," BCEQ\n"); +bceq: if (keys & 0100) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0141603) { fprintf(stderr," BCNE\n"); +bcne: if (!(keys & 0100)) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0141605) { fprintf(stderr," BCGE\n"); +bcge: if (!(keys & 0200) || (keys & 0100)) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0141601) { fprintf(stderr," BCGT\n"); +bcgt: if (!(keys & 0300)) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } @@ -686,6 +845,8 @@ main (int argc, char **argv) { fprintf(stderr," BCR\n"); if (!(keys & 0100000)) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } @@ -693,6 +854,8 @@ main (int argc, char **argv) { fprintf(stderr," BCS\n"); if (keys & 0100000) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } @@ -700,6 +863,8 @@ main (int argc, char **argv) { fprintf(stderr," BLR\n"); if (!(keys & 020000)) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } @@ -707,126 +872,116 @@ main (int argc, char **argv) { fprintf(stderr," BLS\n"); if (keys & 020000) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0140614) { fprintf(stderr," BLT\n"); - if (*(short *)(mem+A) < 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_A; + goto bclt; } if (inst == 0140610) { fprintf(stderr," BLE\n"); - if (*(short *)(mem+A) <= 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_A; + goto bcle; } if (inst == 0140612) { fprintf(stderr," BEQ\n"); - if (*(short *)(mem+A) == 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_A; + goto bceq; } if (inst == 0140613) { fprintf(stderr," BNE\n"); - if (*(short *)(mem+A) != 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_A; + goto bcne; } if (inst == 0140615) { fprintf(stderr," BGE\n"); - if (*(short *)(mem+A) >= 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_A; + goto bcge; } if (inst == 0140611) { fprintf(stderr," BGT\n"); - if (*(short *)(mem+A) > 0) - mem[P] = mem[mem[P]]; + SETCC_A; + goto bcgt; continue; } if (inst == 0140700) { fprintf(stderr," BLLE\n"); - if (*(int *)(mem+A) <= 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_L; + goto bcle; } if (inst == 0140702) { fprintf(stderr," BLEQ\n"); - if (*(int *)(mem+A) == 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_L; + goto bceq; } if (inst == 0140703) { fprintf(stderr," BLNE\n"); - if (*(int *)(mem+A) != 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_L; + goto bcne; } if (inst == 0140701) { fprintf(stderr," BLGT\n"); - if (*(int *)(mem+A) > 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_L; + goto bcgt; } if (inst == 0141614) { fprintf(stderr," BFLT\n"); - if (*(short *)(mem+FLTH) < 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bclt; } if (inst == 0141610) { fprintf(stderr," BFLE\n"); - if (*(int *)(mem+FLTH) < 0 || (*(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0)) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bcle; } if (inst == 0141612) { fprintf(stderr," BFEQ\n"); - if (*(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bceq; } if (inst == 0141613) { fprintf(stderr," BFNE\n"); - if (*(int *)(mem+FLTH) != 0 || *(short *)(mem+FEXP) != 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bcne; } if (inst == 0141615) { fprintf(stderr," BFGE\n"); - if (*(int *)(mem+FLTH) >= 0) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bcge; } if (inst == 0141611) { fprintf(stderr," BFGT\n"); - if (*(int *)(mem+FLTH) >= 0 && (*(int *)(mem+FLTH) != 0 || *(short *)(mem+FEXP) != 0)) - mem[P] = mem[mem[P]]; - continue; + SETCC_F; + goto bcgt; } if (inst == 0141334) { fprintf(stderr," BIX\n"); mem[X]++; +bidx: if (mem[X] == 0) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } @@ -834,56 +989,67 @@ main (int argc, char **argv) { if (inst == 0141324) { fprintf(stderr," BIY\n"); mem[Y]++; +bidy: if (mem[Y] == 0) mem[P] = mem[mem[P]]; + else + mem[P]++; continue; } if (inst == 0140724) { fprintf(stderr," BDY\n"); mem[Y]--; - if (mem[Y] == 0) - mem[P] = mem[mem[P]]; - continue; + goto bidy; } #endif if (inst == 0140734) { fprintf(stderr," BDX\n"); mem[X]--; - if (mem[X] == 0) - mem[P] = mem[mem[P]]; - continue; + goto bidx; } if (inst == 0141206) { /* A1A */ fprintf(stderr," A1A\n"); mem[A]++; + SETC(mem[A] == 32768); + SETCC_A; continue; } if (inst == 0140304) { /* A2A */ fprintf(stderr," A2A\n"); mem[A] += 2; + SETC(*(short *)(mem+A) <= -32767); + SETCC_A; continue; } if (inst == 0141216) { /* ACA */ fprintf(stderr," ACA\n"); - if (keys & 0100000) + if (keys & 0100000) { mem[A]++; + SETC(mem[A] == 32768); + } else + SETC(0); + SETCC_A; continue; } if (inst == 0140110) { /* S1A */ fprintf(stderr," S1A\n"); mem[A]--; + SETC(mem[A] == 32767); + SETCC_A; continue; } if (inst == 0140310) { /* S2A */ fprintf(stderr," S2A\n"); mem[A] -= 2; + SETC(*(short *)(mem+A) >= -32766); + SETCC_A; continue; } @@ -905,12 +1071,36 @@ main (int argc, char **argv) { continue; } + /* On the P300, the B register is the low-order word of the + DP floating pt fraction, so CRB was used to convert SPFP + numbers to DPFP. On the P400 and up, the B register and + DPFP accumulator do not overlap. For compatibility, there + are 3 related instructions: + + '14 clears B and the low-order DPFP register + '15 clears only B + '16 clears only the low-order DPFP register + */ + + if (inst == 0140014) { /* P300 CRB */ + fprintf(stderr," P300CRB\n"); + mem[B] = 0; + exit(1); + continue; + } + if (inst == 0140015) { /* CRB */ fprintf(stderr," CRB\n"); mem[B] = 0; continue; } + if (inst == 0140016) { /* FDBL */ + fprintf(stderr," FDBL\n"); + exit(1); + continue; + } + if (inst == 0140010) { /* CRL */ fprintf(stderr," CRL\n"); mem[A] = 0; mem[B] = 0; @@ -966,66 +1156,14 @@ main (int argc, char **argv) { if (inst == 0140417) { /* LT */ fprintf(stderr," LT\n"); mem[A] = 1; + keys = (keys & ~0300); continue; } if (inst == 0140416) { /* LF */ fprintf(stderr," LF\n"); mem[A] = 0; - continue; - } - - if (inst == 0140410) { /* LLT */ - fprintf(stderr," LLT\n"); - if (*(short *)(mem+A) < 0) - mem[A] = 1; - else - mem[A] = 0; - continue; - } - - if (inst == 0140411) { /* LLE */ - fprintf(stderr," LLE\n"); - if (*(short *)(mem+A) <= 0) - mem[A] = 1; - else - mem[A] = 0; - continue; - } - - if (inst == 0140412) { /* LNE */ - fprintf(stderr," LNE\n"); - if (*(short *)(mem+A) != 0) - mem[A] = 1; - else - mem[A] = 0; - continue; - } - - if (inst == 0140413) { /* LEQ */ - fprintf(stderr," LEQ\n"); - if (*(short *)(mem+A) == 0) - mem[A] = 1; - else - mem[A] = 0; - continue; - } - - if (inst == 0140414) { /* LGE */ - fprintf(stderr," LGE\n"); - if (*(short *)(mem+A) >= 0) - mem[A] = 1; - else - mem[A] = 0; - continue; - } - - if (inst == 0140411) { /* LGT */ - fprintf(stderr," LGT\n"); - if (*(short *)(mem+A) > 0) - mem[A] = 1; - else - mem[A] = 0; + keys = (keys & ~0300) | 0100; continue; } @@ -1130,102 +1268,147 @@ main (int argc, char **argv) { if (inst == 0141500) { fprintf(stderr," LCLT\n"); +lclt: mem[A] = ((keys & 0300) == 0200); continue; } if (inst == 0141501) { fprintf(stderr," LCLE\n"); - mem[A] = (keys & 0300); +lcle: + mem[A] = ((keys & 0300) != 0); continue; } if (inst == 0141503) { fprintf(stderr," LCEQ\n"); - mem[A] = (keys & 0100); +lceq: + mem[A] = ((keys & 0100) != 0); continue; } if (inst == 0141502) { fprintf(stderr," LCNE\n"); - mem[A] = !(keys & 0100); +lcne: + mem[A] = ((keys & 0100) == 0); continue; } if (inst == 0141504) { fprintf(stderr," LCGE\n"); +lcge: mem[A] = !(keys & 0200) || (keys & 0100); continue; } if (inst == 0141505) { fprintf(stderr," LCGT\n"); - mem[A] =!(keys & 0300); +lcgt: + mem[A] = ((keys & 0300) == 0); continue; } + if (inst == 0140410) { + fprintf(stderr," LLT\n"); + SETCC_A; + goto lclt; + } + + if (inst == 0140411) { + fprintf(stderr," LLE\n"); + SETCC_A; + goto lcle; + } + + if (inst == 0140412) { + fprintf(stderr," LNE\n"); + SETCC_A; + goto lcne; + } + + if (inst == 0140413) { + fprintf(stderr," LEQ\n"); + SETCC_A; + goto lceq; + } + + if (inst == 0140414) { + fprintf(stderr," LGE\n"); + SETCC_A; + goto lcge; + } + + if (inst == 0140415) { + fprintf(stderr," LGT\n"); + SETCC_A; + goto lcgt; + } + if (inst == 0140511) { fprintf(stderr," LLLE\n"); - mem[A] = *(int *)(mem+A) <= 0; - continue; + SETCC_L; + goto lcle; } if (inst == 0141513) { fprintf(stderr," LLEQ\n"); - mem[A] = *(int *)(mem+A) == 0; - continue; + SETCC_L; + goto lceq; } if (inst == 0141512) { fprintf(stderr," LLNE\n"); + SETCC_L; + goto lcne; mem[A] = *(int *)(mem+A) != 0; continue; } if (inst == 0141515) { fprintf(stderr," LLGT\n"); - mem[A] = *(int *)(mem+A) > 0; - continue; + SETCC_L; + goto lcgt; } if (inst == 0141110) { fprintf(stderr," LFLT\n"); - mem[A] = *(short *)(mem+FLTH) < 0; - continue; + SETCC_F; + goto lclt; } if (inst == 0141111) { fprintf(stderr," LFLE\n"); - mem[A] = *(int *)(mem+FLTH) < 0 || (*(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0); - continue; + SETCC_F; + goto lcle; } if (inst == 0141113) { fprintf(stderr," LFEQ\n"); - mem[A] = *(int *)(mem+FLTH) == 0 && *(short *)(mem+FEXP) == 0; - continue; + SETCC_F; + goto lceq; } if (inst == 0141112) { fprintf(stderr," LFNE\n"); - mem[A] = *(int *)(mem+FLTH) != 0 || *(short *)(mem+FEXP) != 0; - continue; + SETCC_F; + goto lcne; } if (inst == 0141114) { fprintf(stderr," LFGE\n"); - mem[A] = *(int *)(mem+FLTH) >= 0; - continue; + SETCC_F; + goto lcge; } if (inst == 0141115) { fprintf(stderr," LFGT\n"); - mem[A] = *(int *)(mem+FLTH) >= 0 && (*(int *)(mem+FLTH) != 0 || *(short *)(mem+FEXP) != 0); - continue; + SETCC_F; + goto lcgt; } if (inst == 0140000) { fprintf(stderr," ADLL\n"); + exit(1); if (keys & 020000) (*(int *)(mem+A))++; continue; @@ -1240,90 +1423,145 @@ main (int argc, char **argv) { if (class == 1) { fprintf(stderr," shift group\n"); scount = -inst & 077; - switch (inst & 01700) { + if (scount > 0) + switch (inst & 01700) { - case 00000: /* LRL */ - fprintf(stderr," LRL %d\n", scount); - utempl = *(unsigned int *)(mem+A); - utempl = utempl >> scount; - *(int *)(mem+A) = utempl; - break; + case 00000: /* LRL */ + fprintf(stderr," LRL %d\n", scount); + if (scount <= 32) { + utempl = *(unsigned int *)(mem+A); + SETC(utempl & bitmask32[33-scount]); + utempl = utempl >> scount; + *(unsigned int *)(mem+A) = utempl; + } else { + *(unsigned int *)(mem+A) = 0; + SETC(0); + } + break; - case 00100: /* LRS (s.b. different in R/V modes) */ - fprintf(stderr," LRS %d\n", scount); - templ = *(int *)(mem+A); - templ = templ >> scount; - *(int *)(mem+A) = templ; - break; + case 00100: /* LRS (s.b. 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); + } else { + *(int *)(mem+A) = 0; + SETC(0); + } + break; - case 00200: /* LRR */ - fprintf(stderr," LRR %d\n", scount); - scount = scount & 037; - utempl = *(unsigned int *)(mem+A); - utempl = (utempl >> scount) | (utempl << (32-scount)); - *(unsigned int *)(mem+A) = utempl; - break; + case 00200: /* LRR */ + fprintf(stderr," LRR %d\n", scount); + if (scount > 32) + scount = scount - 32; + utempl = *(unsigned int *)(mem+A); + SETC(utempl & bitmask32[33-scount]); + utempl = (utempl >> scount) | (utempl << (32-scount)); + *(unsigned int *)(mem+A) = utempl; + break; - case 00400: /* ARL */ - fprintf(stderr," ARL %d\n", scount); - utempa = mem[A]; - utempa = utempa >> scount; - mem[A] = utempa; - break; + case 00400: /* ARL */ + fprintf(stderr," ARL %d\n", scount); + if (scount <= 16) { + utempa = mem[A]; + SETC(utempa & bitmask16[17-scount]); + utempa = utempa >> scount; + mem[A] = utempa; + } else { + mem[A] = 0; + SETC(0); + } + break; - case 00500: /* ARS */ - fprintf(stderr," ARS %d\n", scount); - tempa = *(short *)(mem+A); - tempa = tempa >> scount; - *(short *)(mem+A) = tempa; - break; + case 00500: /* ARS */ + fprintf(stderr," ARS %d\n", scount); + if (scount <= 16) { + tempa = *(short *)(mem+A); + SETC(tempa & bitmask16[17-scount]); + tempa = tempa >> scount; + *(short *)(mem+A) = tempa; + } else if (mem[A] & 0x8000) { + *(short *)(mem+A) = 0xFFFF; + SETC(1); + } else { + *(short *)(mem+A) = 0; + SETC(0); + } + break; - case 00600: /* ARR */ - fprintf(stderr," ARR %d\n", scount); - scount = scount & 017; - mem[A] = (mem[A] >> scount) | (mem[A] << (16-scount)); - break; + case 00600: /* ARR */ + fprintf(stderr," ARR %d\n", scount); + while (scount > 16) + scount = scount - 16; + SETC(mem[A] & bitmask16[17-scount]); + mem[A] = (mem[A] >> scount) | (mem[A] << (16-scount)); + break; - case 01000: /* LLL */ - fprintf(stderr," LLL %d\n", scount); - utempl = *(unsigned int *)(mem+A); - utempl = utempl << scount; - *(unsigned int *)(mem+A) = utempl; - break; + case 01000: /* LLL */ + fprintf(stderr," LLL %d\n", scount); + if (scount <= 32) { + utempl = *(unsigned int *)(mem+A); + SETC(utempl & bitmask32[scount]); + utempl = utempl << scount; + *(unsigned int *)(mem+A) = utempl; + } else { + *(unsigned int *)(mem+A) = 0; + SETC(0); + } + break; - case 01100: /* LLS (s.b. different in R/V modes) */ - fprintf(stderr," LLS %d\n", scount); - templ = *(int *)(mem+A); - templ = templ << scount; - *(int *)(mem+A) = templ; - break; + case 01100: /* LLS (s.b. 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; + } else { + *(int *)(mem+A) = 0; + SETC(0); + } + break; - case 01200: /* LLR */ - fprintf(stderr," LLR %d\n", scount); - scount = scount & 037; - utempl = *(unsigned int *)(mem+A); - utempl = (utempl << scount) | (utempl >> (32-scount)); - *(unsigned int *)(mem+A) = utempl; - break; + case 01200: /* LLR */ + fprintf(stderr," LLR %d\n", scount); + if (scount > 32) + scount = scount - 32; + utempl = *(unsigned int *)(mem+A); + SETC(utempl & bitmask32[scount]); + utempl = (utempl << scount) | (utempl >> (32-scount)); + *(unsigned int *)(mem+A) = utempl; + break; - case 01400: /* ALL */ - case 01500: /* ALS */ - fprintf(stderr," ALL/ALS %d\n", scount); - utempa = *(short *)(mem+A); - utempa = utempa << scount; - *(short *)(mem+A) = utempa; - break; + case 01400: /* ALL */ + case 01500: /* ALS */ + fprintf(stderr," ALL/ALS %d\n", scount); + if (scount <= 16) { + SETC(mem[A] & bitmask16[scount]); + mem[A] = mem[A] << scount; + } else { + mem[A] = 0; + SETC(0); + } + break; - case 01600: /* ALR */ - fprintf(stderr," ALR %d\n", scount); - scount = scount & 017; - mem[A] = (mem[A] << scount) | (mem[A] >> (16-scount)); - break; + case 01600: /* ALR */ + fprintf(stderr," ALR %d\n", scount); + while (scount > 16) + scount = scount - 16; + SETC(mem[A] & bitmask16[scount]); + mem[A] = (mem[A] << scount) | (mem[A] >> (16-scount)); + break; - default: - fprintf(stderr," unrecognized shift instruction\n"); - exit(1); - } + default: + fprintf(stderr," unrecognized shift instruction\n"); + exit(1); + } continue; } @@ -1397,8 +1635,31 @@ main (int argc, char **argv) { continue; } - if (inst == 0101270) { /* weird combo skip for PSD */ - fprintf(stderr," weird skip\n"); + if (inst == 0101001) { + fprintf(stderr," SSC\n"); + if (keys & 0100000) + mem[P]++; + continue; + } + + if (inst == 0100001) { + fprintf(stderr," SRC\n"); + if (!(keys & 0100000)) + mem[P]++; + continue; + } + + if ((inst & 0177760) == 0100260) { + fprintf(stderr," SAR %d\n", (inst & 017)+1); + if (!(mem[A] & bitmask16[(inst & 017)+1])) + mem[P]++; + continue; + } + + if ((inst & 0177760) == 0101260) { + fprintf(stderr," SAS %d\n", (inst & 017)+1); + if (mem[A] & bitmask16[(inst & 017)+1]) + mem[P]++; continue; } @@ -1447,8 +1708,8 @@ main (int argc, char **argv) { x=1, opcode='15 01 -> ldy (V) (aka '35 01) x=0, opcode='15 02 -> dflx (V) + x=0, opcode='15 02 -> jdx (R) x=1, opcode='15 02 -> sty (V) (aka '35 02) - x=1, opcode='15 02 -> jdx (R) (aka '35 02) x=0, opcode='15 03 -> jix (R) x=1, opcode='15 03 -> jsx (RV) (aka '35 03) @@ -1495,7 +1756,7 @@ main (int argc, char **argv) { } if (opcode == 00200) { - if (keys & 040000) { + if ((keys & 050000) == 040000) { /* R-mode and DP */ fprintf(stderr," DLD\n"); *(unsigned int *)(mem+A) = *(unsigned int *)(mem+ea); } else { @@ -1505,26 +1766,14 @@ main (int argc, char **argv) { continue; } - if (opcode == 00203) { - fprintf(stderr," LDL\n"); - *(unsigned int *)(mem+A) = *(unsigned int *)(mem+ea); - continue; - } - if (opcode == 00300) { fprintf(stderr," ANA\n"); mem[A] &= mem[ea]; continue; } - if (opcode == 00303) { - fprintf(stderr," ANL\n"); - *(unsigned int *)(mem+A) &= *(unsigned int *)(mem+ea); - continue; - } - if (opcode == 00400) { - if (keys & 040000) { + if ((keys & 050000) == 040000) { fprintf(stderr," DST\n"); mem[ea] = mem[A]; mem[ea+1] = mem[B]; @@ -1535,51 +1784,47 @@ main (int argc, char **argv) { continue; } - if (opcode == 00403) { - fprintf(stderr," STL\n"); - *(int *)(mem+ea) = *(int *)(mem+A); - continue; - } - if (opcode == 00500) { fprintf(stderr," ERA\n"); mem[A] ^= mem[ea]; continue; } - if (opcode == 00503) { - fprintf(stderr," ERL\n"); - *(int *)(mem+A) ^= *(int *)(mem+ea); - continue; - } - if (opcode == 00302) { fprintf(stderr," ORA\n"); - *(short *)(mem+A) |= *(short *)(mem+ea); + mem[A] |= mem[ea]; continue; } if (opcode == 00600) { - fprintf(stderr," ADD\n"); - *(short *)(mem+A) += *(short *)(mem+ea); - continue; - } - - if (opcode == 00603) { - fprintf(stderr," ADL\n"); - *(int *)(mem+A) += *(int *)(mem+ea); + 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) { - fprintf(stderr," SUB\n"); - *(short *)(mem+A) -= *(short *)(mem+ea); - continue; - } - - if (opcode == 00703) { - fprintf(stderr," SBL\n"); - *(int *)(mem+A) -= *(int *)(mem+ea); + 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; } @@ -1592,10 +1837,15 @@ main (int argc, char **argv) { if (opcode == 01100) { fprintf(stderr," CAS\n"); - if (mem[A] == mem[ea]) - mem[P]++; - else if (*(short*)(mem+A) < *(short *)(mem+ea)) + utempa = mem[A]; + *(short *)(mem+A) -= *(short *)(mem+ea); + SETCC_A; + mem[A] = utempa; +compskip: + if (keys & 0200) mem[P] += 2; + else if (keys & 0100) + mem[P]++; continue; } @@ -1648,11 +1898,8 @@ main (int argc, char **argv) { fprintf(stderr," Register A should be 0 or -1 before R-mode DIV\n"); exit(1); } - if (mem[A]) { /* dividend was negative before PID */ - tempa = mem[B] | 0x8000; /* make 16-bit negative again */ - templ = tempa; /* extend to 32-bit negative */ - } else - templ = *(short *)(mem+B);/* make 32-bit positive */ + tempa = mem[B] | (mem[A] & 0x8000); + templ = tempa; /* extend to 32-bits */ } mem[A] = templ / *(short *)(mem+ea); mem[B] = templ % *(short *)(mem+ea); @@ -1660,7 +1907,7 @@ main (int argc, char **argv) { } if (opcode == 03500) { - fprintf(stderr," LDX instruction, new value=%o\n", mem[ea]); + fprintf(stderr," LDX\n"); mem[X] = mem[ea]; continue; } @@ -1683,53 +1930,109 @@ main (int argc, char **argv) { continue; } + /* NOTE: P300 u-code listings show CC set on Jxx instructions */ + if (opcode == 00203) { - fprintf(stderr," JEQ\n"); - if (*(short *)(mem+A) == 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," LDL\n"); + *(unsigned int *)(mem+A) = *(unsigned int *)(mem+ea); + } else { + fprintf(stderr," JEQ\n"); + if (*(short *)(mem+A) == 0) + mem[P] = ea; + } continue; } if (opcode == 00703) { - fprintf(stderr," JGE\n"); - if (*(short *)(mem+A) >= 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," SBL\n"); + *(int *)(mem+A) -= *(int *)(mem+ea); + } else { + fprintf(stderr," JGE\n"); + if (*(short *)(mem+A) >= 0) + mem[P] = ea; + } + continue; + } + + if (opcode == 01002) { + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," PCL\n"); + exit(1); + } else { + fprintf(stderr," CREP\n"); + exit(1); + } continue; } if (opcode == 00503) { - fprintf(stderr," JGT\n"); - if (*(short *)(mem+A) > 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," ERL\n"); + *(int *)(mem+A) ^= *(int *)(mem+ea); + } else { + fprintf(stderr," JGT\n"); + if (*(short *)(mem+A) > 0) + mem[P] = ea; + } continue; } if (opcode == 00403) { - fprintf(stderr," JLE\n"); - if (*(short *)(mem+A) <= 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," STL\n"); + *(int *)(mem+ea) = *(int *)(mem+A); + } else { + fprintf(stderr," JLE\n"); + if (*(short *)(mem+A) <= 0) + mem[P] = ea; + } continue; } if (opcode == 00603) { - fprintf(stderr," JLT\n"); - if (*(short *)(mem+A) < 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," ADL\n"); + *(int *)(mem+A) += *(int *)(mem+ea); + } else { + fprintf(stderr," JLT\n"); + if (*(short *)(mem+A) < 0) + mem[P] = ea; + } continue; } if (opcode == 00303) { - fprintf(stderr," JNE\n"); - if (*(short *)(mem+A) != 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," ANL\n"); + *(unsigned int *)(mem+A) &= *(unsigned int *)(mem+ea); + } else { + fprintf(stderr," JNE\n"); + if (*(short *)(mem+A) != 0) + mem[P] = ea; + } continue; } + /* NOTE: P300 u-code shows CC set for JIX/JDX */ + if (opcode == 01502) { - fprintf(stderr," JDX\n"); - mem[X]--; - if (mem[X] == 0) - mem[P] = ea; + if (keys & 010000) { /* V/I mode */ + fprintf(stderr," DFLX\n"); + mem[X] = mem[ea] * 4; + } else { + fprintf(stderr," JDX\n"); + mem[X]--; + if (mem[X] == 0) + mem[P] = ea; + } + continue; + } + + if (opcode == 03502) { + fprintf(stderr," STY\n"); + exit(1); continue; } @@ -1741,6 +2044,18 @@ main (int argc, char **argv) { continue; } + if (opcode == 01501) { + fprintf(stderr," FLX\n"); + mem[X] = mem[ea]*2; + continue; + } + + if (opcode == 03501) { + fprintf(stderr," LDY\n"); + exit(1); + continue; + } + if (opcode == 03503) { fprintf(stderr," JSX\n"); mem[X] = mem[P]; @@ -1750,11 +2065,11 @@ main (int argc, char **argv) { if (opcode == 01103) { fprintf(stderr," CLS\n"); - if (*(int *)(mem+A) == *(int *)(mem+ea)) - mem[P]++; - else if (*(int *)(mem+A) < *(int *)(mem+ea)) - mem[P] += 2; - continue; + utempl = *(unsigned int *)(mem+A); + *(int *)(mem+A) -= *(int *)(mem+ea); + SETCC_L; + *(unsigned int *)(mem+A) = utempl; + goto compskip; } fprintf(stderr," UNKNOWN OPCODE: %o\n", opcode); @@ -1826,32 +2141,285 @@ main (int argc, char **argv) { svc() { +#define MAXCLASS 015 +#define MAXFUNC 027 +#define MAXSVCARGS 10 + unsigned short code; /* code word following SVC instruction */ unsigned short argl; /* address of argument list */ - unsigned short a1,a2,a3,a4,a5,a6; /* args */ - short i,tempa; - char *bp; + void *arg[MAXSVCARGS]; /* arg address array */ + short actargs; /* number of actual arguments */ short class; /* SVC class, from bits 5-10 */ short func; /* SVC func within class, bits 11-16 */ - + short temp16; + + static struct { + char name[8]; /* svc routine name */ + char numargs; /* number of arguments for this svc */ + short locargs; /* bit mask for LOC(X) arguments */ + } svcinfo[MAXCLASS+1][MAXFUNC+1] = { + + /* class 0 is a dummy: it's mapped to class 1 below */ + + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 1 */ + + "ATTACH", -5, 0, /* func 0 */ + "SEARCH", -4, 0, /* func 1 */ + "SAVE ", 2, 0, /* func 2 */ + "RESTOR", -3, 0, /* func 3 */ + "RESUME", 1, 0, /* func 4 */ + "EXIT ", 0, 0, /* func 5 */ + "ERRRTN", 4, 0, /* func 6 */ + "UPDATE", 99, 0, /* func 7 */ + "GETERR", 2, 0, /* func 010 */ + "PRERR ", 0, 0, /* func 011 */ + "GINFO ", 2, 0, /* func 012 */ + "CNAME$", -3, 0, /* func 013 */ + "ERRSET", 5, 0, /* func 014 */ + "FORCEW", 2, 0, /* func 015 */ + "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 2 */ + + "READ ", 99, 0, /* func 0 */ + "WRITE ", 99, 0, /* func 1 */ + "RDLIN ", -4, 0, /* func 2 */ + "WTLIN ", -4, 0, /* func 3 */ + "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 3 */ + + "PRWFIL", -6, 020000, /* func 0 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 4 */ + + "FAMSVC", 99, 0, /* func 0 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 5 */ + + "RREC ", -6, 0, /* func 0 */ + "WREC ", -6, 0, /* func 1 */ + "TIMDAT", 2, 0, /* func 2 */ + "DIGIN ", -4, 0, /* func 3 */ + "DIGINW", -4, 0, /* func 4 */ + "RCYCL ", 0, 0, /* func 5 */ + "D$INIT", 1, 0, /* func 6 */ + "BREAK$", 1, 0, /* func 7 */ + "T$MT ", 6, 040000, /* func 010 */ + "T$LMPC", 5, 040000, /* func 011 */ + "T$CMPC", 5, 040000, /* func 012 */ + "T$AMLC", 5, 040000, /* func 013 */ + "T$VG ", 5, 040000, /* func 014 */ + "T$PMPC", 5, 040000, /* func 015 */ + "RRECL ", -6, 0, /* func 016 */ + "WRECL ", -6, 0, /* func 017 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 6 */ + + "COMANL", 0, 0, /* func 0 */ + "C1IN ", 1, 0, /* func 1 */ + "CMREAD", 1, 0, /* func 2 */ + "COMINP", -3, 0, /* func 3 */ + "CNIN$ ", 3, 0, /* func 4 */ + "PHANT$", 5, 0, /* func 5 */ + "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 7 */ + + "T1IN ", 1, 0, /* func 0 */ + "T1OU ", 1, 0, /* func 1 */ + "TNOU ", 2, 0, /* func 2 */ + "TNOUA ", 2, 0, /* func 3 */ + "TOOCT ", 1, 0, /* func 4 */ + "DUPLX$", 1, 0, /* func 5 */ + "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 010 */ + + "T$MT ", 6, 040000, /* func 0 */ + "T$SMLC", 4, 020000, /* func 1 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 011 */ + + "T$LMPC", 6, 040000, /* func 0 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 012 */ + + "T$CMPC", 6, 040000, /* func 0 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 013 (user defined) */ + + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 014 */ + + "ATTAC$", 6, 002000, /* func 0 */ + "CREAT$", 5, 004000, /* func 1 */ + "ERRPR$", 6, 0, /* func 2 */ + "ERRST$", 99, 0, /* func 3 */ + "GPASS$", 5, 004000, /* func 4 */ + "GQUOT$", 99, 0, /* func 5 */ + "PRWFL$", 7, 021000, /* func 6 */ + "RDENT$", 8, 000400, /* func 7 */ + "SATTR$", 5, 004000, /* func 010 */ + "SEARC$", 6, 002000, /* func 011 */ + "SEGDR$", 5, 004000, /* func 012 */ + "SPASS$", 3, 020000, /* func 013 */ + "SQUOT$", 99, 0, /* func 014 */ + "CNGNM$", 5, 004000, /* func 015 */ + "COMIN$", 4, 010000, /* func 016 */ + "RDTKN$", 5, 004000, /* func 017 */ + "RESTO$", 4, 010000, /* func 020 */ + "RESUM$", 2, 0, /* func 021 */ + "SAVE$ ", 4, 010000, /* func 022 */ + "",99,0, "",99,0, "",99,0, "",99,0, "",99,0, + + /* class 015 */ + + "ATCH$$", 6, 0, /* func 0 */ + "CREA$$", 5, 0, /* func 1 */ + "",99,0, /* func 2 */ + "",99,0, /* func 3 */ + "GPAS$$", 5, 0, /* func 4 */ + "",99,0, /* func 5 */ + "PRWF$$", 7, 020000, /* func 6 */ + "RDEN$$", 8, 0, /* func 7 */ + "SATR$$", 5, 0, /* func 010 */ + "SRCH$$", 6, 0, /* func 011 */ + "SGDR$$", 5, 0, /* func 012 */ + "SPAS$$", 3, 0, /* func 013 */ + "",99,0, /* func 014 */ + "CNAM$$", 5, 0, /* func 015 */ + "COMI$$", 4, 0, /* func 016 */ + "RDTK$$", 5, 0, /* func 017 */ + "REST$$", 4, 0, /* func 020 */ + "RESU$$", 2, 0, /* func 021 */ + "SAVE$$", 4, 0, /* func 022 */ + "COMO$$", 5, 0, /* func 023 */ + "ERKL$$", 4, 0, /* func 024 */ + "RDLIN$", 4, 0, /* func 025 */ + "WTLIN$", 4, 0, /* func 026 */ + "",99,0 + }; + +#if 0 + for (class=0; class<=MAXCLASS; class++) + for (func=0; func<=MAXFUNC; func++) + printf("Class %o, func %o: %s %d args %o\n", class,func, svcinfo[class][func].name, svcinfo[class][func].numargs, svcinfo[class][func].locargs); +#endif + + /* get svc code word, break into class and function */ + code = mem[mem[P]]; + class = (code >> 6) & 077; + if (class == 0) + class = 1; + func = code & 077; + + /* determine argument list location and create arg list vector */ + if (code & 0100000) argl = mem[mem[P]-2]; else if (code & 040000) argl = mem[P]+2; else argl = mem[P]+1; - class = (code >> 6) & 077; - func = code & 077; - fprintf(stderr," code=%o, class=%o, func=%o, arglist=%o\n", code, class, func, argl); + + fprintf(stderr," code=%o, class=%o, func=%o, argl=%o\n", code, class, func, argl); + if (class <= MAXCLASS && func <= MAXFUNC) + fprintf(stderr," name=%s, #args=%d, LOC args=%o\n", svcinfo[class][func].name, svcinfo[class][func].numargs, svcinfo[class][func].locargs); + else + goto badsvc; + + if (svcinfo[class][func].numargs == 99) + goto badsvc; + + if (svcinfo[class][func].locargs != 0) { + fprintf(stderr," Can't handle LOC() args\n"); + exit(1); + } + + actargs = 0; + if (svcinfo[class][func].numargs == 1) { + actargs = 1; + arg[0] = mem+mem[argl++]; + if (mem[argl] == 0) /* single arg: terminating zero is optional */ + argl++; + } else if (svcinfo[class][func].numargs > 0) { + while (mem[argl] != 0) { + if (actargs < MAXSVCARGS) + arg[actargs++] = mem+mem[argl]; + argl++; + } + argl++; /* skip terminating zero */ + while (actargs < svcinfo[class][func].numargs) + arg[actargs++] == NULL; + } + + fprintf(stderr," return=%o, actargs=%d\n", argl, actargs); switch (class) { case 0: /* same as class 1 */ case 1: /* funcs 0-'15 */ switch (func) { - case 5: /* EXIT */ - fprintf(stderr,"\nProgram called EXIT\n"); - exit(1); + case 0: /* ATTACH (NAME,DEV,PASSWD,HOMESET,ALTRTN) */ + goto unimp; + case 1: /* SEARCH (KEY,NAME,UNIT,ALTRTN) */ + goto unimp; + case 2: /* SAVE (RVEC,NAME) */ + goto unimp; + case 3: /* RESTOR (RVEC,NAME,ALTRTN) */ + goto unimp; + case 4: /* RESUME (NAME) */ + goto unimp; + case 5: /* EXIT () */ + os_exit(); + case 6: /* ERRRTN (ALTRTN,'XXXXXX',MSG,MSGLEN) */ + goto unimp; + case 7: /* UPDATE */ + goto unimp; + case 010: /* GETERR (BUFF,N) */ + goto unimp; + case 011: /* PRERR () */ + goto unimp; + case 012: /* GINFO (BUFF,N) */ + os_ginfo(arg[0], arg[1]); + break; + case 013: /* CNAME$ (OLDNAM,NEWNAM,ALTRTN) */ + goto unimp; + case 014: /* ERRSET (ALTVAL,ALTRTN,'XXXXXX','MSG',MSGLEN) */ + goto unimp; + case 015: /* FORCEW (KEY,UNIT) */ + goto unimp; default: goto unimp; } @@ -1862,7 +2430,12 @@ svc() { break; case 3: /* func 0 = PRWFIL */ - goto unimp; + switch (func) { + case 0: /* PRWFIL (KEY,UNIT,LOC(BUF),N,POS,ALTRTN) */ + goto unimp; + default: + goto unimp; + } break; case 4: /* func 0 = FAMSVC (obsolete) */ @@ -1870,20 +2443,64 @@ svc() { break; case 5: /* funcs 0-'17 */ - goto unimp; + switch (func) { + case 0: /* RREC (PBAV,NWV,N,RA16,PDEV,ALTRTN) */ + goto unimp; + case 1: /* WREC (PBAV,NWV,N,RA16,PDEV,ALTRTN) */ + goto unimp; + case 2: /* TIMDAT (BUFF,N) */ + os_timdat(arg[0], arg[1]); + break; + case 3: /* DIGIN (N,ADRVEC,DATVEC,ALTRTN) */ + goto unimp; + case 4: /* DIGINW (same, but initial arg of 1 instead of 0 to DIGIN) */ + goto unimp; + case 5: /* RECYCL */ + goto unimp; + case 6: /* D$INIT (PDEV) */ + goto unimp; + case 7: /* BREAK$ (ONOFF) */ + os_break$(arg[0]); + break; + case 010: /* T$MT (UNIT,LOC(BUF),NW,INST,STATV,CODE) */ + goto unimp; + case 011: /* T$LMPC (UNIT,LOC(BUF),NW,INST,STATV) */ + goto unimp; + case 012: /* T$CMPC (UNIT,LOC(BUF),NW,INST,STATV) */ + goto unimp; + case 013: /* T$AMLC (LINE,LOC(BUF),NW,INST,STATV) */ + goto unimp; + case 014: /* T$VG (UNIT,LOC(BUF),NW,INST,STATV) */ + goto unimp; + case 015: /* T$PMPC (UNIT,LOC(BUF),NW,INST,STATV) */ + goto unimp; + case 016: /* RRECL (PBAV,NWV,N,RA32,PDEV,ALTRTN) */ + goto unimp; + case 017: /* WRECL (PBAV,NWV,N,RA32,PDEV,ALTRTN) */ + goto unimp; + default: + goto unimp; + } break; case 6: /* funcs 0-5 */ switch (func) { - case 0: /* comanl, 0 args */ - goto unimp; - case 1: /* c1in, 1 arg */ - fprintf(stderr," c1in - enter a character!\n"); - goto badsvc; - a1 = mem[argl++]; - tempa=getchar() | 0x80; /* WRONG - needs to read from /dev/tty */ - mem[a1] = tempa; + case 0: /* COMANL () */ + os_comanl(); break; + case 1: /* C1IN (CHAR) */ + os_c1in(arg[0]); + break; + case 2: /* CMREAD (BUFF) */ + strncpy(arg[0], " ", 6); + break; + case 3: /* COMINP (FILNAM,UNIT,ALTRTN) */ + goto unimp; + case 4: /* CNIN$ (BUF,MAXCHARS,ACTCHARS) */ + os_cnin$(arg[0], arg[1], arg[2]); + break; + case 5: /* PHANT$ (FILNAM,NAMLEN,UNIT,USER,CODE) */ + goto unimp; default: goto unimp; } @@ -1891,75 +2508,147 @@ svc() { case 7: switch (func) { - case 0: - fprintf(stderr," t1in\n"); - exit(1); + case 0: /* T1IN (CHAR) */ + os_c1in(arg[0]); break; - case 1: - fprintf(stderr," t1ou\n"); - a1 = mem[argl++]; /* get address of arg1 */ - a1 = mem[a1]; /* get the character to print */ - putchar(a1 & 0x7f); /* write the character w/o parity */ + case 1: /* T1OU (CHAR) */ + os_t1ou(arg[0]); break; case 2: /* TNOU */ case 3: /* TNOUA */ - a1 = mem[argl++]; - a2 = mem[argl++]; - bp = (char *)(mem+a1); - fprintf(stderr," tnou/a, arg1 @ %o, arg2 @ %o\n", a1, a2); - for (i=0; i < mem[a2]; i++,bp++) - putchar(*bp & 0x7f); - if (func == 2) - putchar('\n'); - fflush(stdout); - break; - case 4: - fprintf(stderr," tooct\n"); - exit(1); - break; - case 5: - fprintf(stderr," duplx$\n"); - exit(1); + os_tnoua(arg[0],arg[1]); + if (func == 2) { + temp16 = 1; + os_tnoua("\n", &temp16); + } break; + case 4: /* TOOCT (NUMBER) */ + goto unimp; + case 5: /* DUPLX$ (KEY) */ + goto unimp; default: goto unimp; } break; case 010: - goto unimp; + switch (func) { + case 0: /* T$MT (UNIT,LOC(BUF),NW,INST,STATV,CODE) */ + goto unimp; + case 1: /* T$SLC1 (KEY,LINE,LOC(BUF),NWORDS) */ + goto unimp; + default: + goto unimp; + } break; case 011: - goto unimp; + switch (func) { + case 0: /* T$LMPC (UNIT,LOC(BUF),NW,INST,STATV,CODE) */ + goto unimp; + default: + goto unimp; + } break; case 012: - goto unimp; + switch (func) { + case 0: /* T$CMPC (UNIT,LOC(BUF),NW,INST,STATV,CODE) */ + goto unimp; + default: + goto unimp; + } break; case 013: - goto unimp; + switch (func) { /* func is 0-2 */ + default: + goto unimp; + } break; case 014: - goto unimp; + switch (func) { + case 0: /* ATTAC$ (NAME,NAMLEN,LDEV,PASSWD,KEY,LOC(CODE)) */ + goto unimp; + case 1: /* CREAT$ (NAME,NAMLEN,OWNER,NONOWNER,LOC(CODE)) */ + goto unimp; + case 2: /* ERRPR$ (KEY,CODE,TEXT,TEXTLEN,PROGNAME,NAMLEN) */ + os_errpr$ (arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); + break; + case 4: /* GPASS$ (NAME,NAMLEN,OWNER,NONOWNER,LOC(CODE) */ + goto unimp; + case 6: /* PRWFL$ (KEY,UNIT,LOC(BUF),NW,POS,RNW,LOC(CODE)) */ + goto unimp; + case 7: /* RDENT$ (KEY,UNIT,BUF,BUFSIZ,RNW,NAME,NAMLEN,LOC(CODE)) */ + goto unimp; + case 010: /* SATTR$ (KEY,NAME,NAMLEN,ARRAY,LOC(CODE)) */ + goto unimp; + case 011: /* SEARC$ (KEY,NAME,NAMLEN,UNIT,TYPE,LOC(CODE) */ + goto unimp; + case 012: /* SEGDR$ (KEY,UNIT,ENTRYA,ENTRYB,LOC(CODE)) */ + goto unimp; + case 013: /* SPASS$ (OWNER,NONOWNER,LOC(CODE)) */ + goto unimp; + case 015: /* CNGNM$ (OLDNAM,OLDLEN,NEWNAM,NEWLEN,LOC(CODE)) */ + goto unimp; + case 016: /* COMIN$ (FILNAM,NAMLEN,UNIT,LOC(CODE)) */ + goto unimp; + case 017: /* RDTKN$ (KEY,INFO(5),BUF,BUFLEN,LOC(CODE)) */ + goto unimp; + case 020: /* RESTO$ (RVEC(9),FILNAM,NAMLEN,LOC(CODE)) */ + goto unimp; + case 021: /* RESUM$ (NAME,NAMLEN) */ + goto unimp; + case 022: /* SAVE$ (RVEC,FILNAM,NAMLEN,LOC(CODE)) */ + goto unimp; + default: + goto unimp; + } break; case 015: switch (func) { - case 024: /* ERKL$$(KEY,ERASECH,KILLCH,CODE) */ - fprintf(stderr," erlk$$\n"); - a1 = mem[argl++]; - a2 = mem[argl++]; - a3 = mem[argl++]; - a4 = mem[argl++]; - if (mem[a1] == k$read) { - mem[a2] = 0210; - mem[a3] = 0377; - } - mem[a4] = 0; + case 0: /* ATCH$$ (UFDNAM,NAMLEN,LDEV,PASSWD,KEY,CODE) */ + goto unimp; + case 1: /* CREA$$ (NAME,NAMLEN,OPASS,NPASS,CODE) */ + goto unimp; + case 4: /* GPAS$$ (UFDNAM,NAMLEN,OPASS,NPASS,CODE) */ + goto unimp; + case 6: /* PRWF$$ (KEY,FUNIT,LOC(BUF),BUFLEN,POS32,RNW,CODE) */ + goto unimp; + case 7: /* RDEN$$ (KEY,FUNIT,BUF,BUFLEN,RNW,NAME32,NAMLEN,CODE) */ + goto unimp; + case 010: /* SATR$$ (KEY,NAME,NAMLEN,ARRAY,CODE) */ + goto unimp; + case 011: /* SRCH$$ (KEY,NAME,NAMLEN,FUNIT,TYPE,CODE) */ + goto unimp; + case 012: /* SGDR$$ (KEY,FUNIT,ENTRYA,ENTRYB,CODE) */ + goto unimp; + case 013: /* SPAS$$ (OWNER,NON-OWNER,CODE) */ + goto unimp; + case 015: /* CNAM$$ (OLDNAM,OLDLEN,NEWNAM,NEWLEN,CODE) */ + goto unimp; + case 016: /* COMI$$ (FILNAM,NAMLEN,UNIT,CODE) */ + goto unimp; + case 017: /* RDTK$$ (KEY,INFO(5),BUF,BUFLEN,CODE) */ + os_rdtk$$ (arg[0], arg[1], arg[2], arg[3], arg[4]); break; + case 020: /* REST$$ (RVEC,NAME,NAMLEN,CODE) */ + goto unimp; + case 021: /* RESU$$ (NAME,NAMLEN) */ + goto unimp; + case 022: /* SAVE$$ (RVEC,NAME,NAMLEN,CODE) */ + goto unimp; + case 023: /* COMO$$ (KEY,NAME,NAMLEN,XXXXXX,CODE) */ + goto unimp; + case 024: /* ERKL$$ (KEY,ERASECH,KILLCH,CODE) */ + os_erkl$$(arg[0], arg[1], arg[2], arg[3]); + break; + case 025: /* RDLIN$ (UNIT,LINE,NWDS,CODE) */ + goto unimp; + case 026: /* WTLIN$ (UNIT,LINE,NWDS,CODE) */ + goto unimp; default: goto unimp; } @@ -1969,11 +2658,8 @@ svc() { goto unimp; /* bad class */ } - /* after the SVC, argl is the return address; look for zero arg list - terminator and ignore it) */ + /* after the SVC, argl is the return address */ - if (mem[argl] == 0) - argl++; fprintf(stderr," returning from SVC to %o\n", argl); mem[P] = argl; return; @@ -1981,7 +2667,7 @@ svc() { unimp: - fprintf(stderr," svc class '%o function '%o is not implemented\n", class, func); + fprintf(stderr," svc not implemented\n", class, func); exit(1); /* here on a bad svc; if the bounce bit (bit 2) is set in the code word, @@ -1996,7 +2682,7 @@ badsvc: return; } - fprintf(stderr," halting on bad svc\n"); + fprintf(stderr," halting on bad svc, class=%o, func=%o\n", class, func); exit(1); } @@ -2005,19 +2691,23 @@ 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) { - unsigned short class; - unsigned short func; - unsigned short device; + short class; + short func; + short device; class = inst >> 14; func = (inst >> 6) & 017; device = inst & 077; fprintf(stderr," pio, class=%d, func=%o, device=%o\n", class, func, device); if (devmap[device]) - devmap[device](class, func); + devmap[device](class, func, device); else fprintf(stderr," no handler for device; instruction ignored\n"); } diff --git a/emdev.h b/emdev.h index 89c148e..3b3537c 100644 --- a/emdev.h +++ b/emdev.h @@ -1,3 +1,62 @@ +/* emdev.h, Jim Wilcoxson, April 17, 2005 + Device handlers for pio instructions. Use devnull as a template for + new handlers. + NOTES: + + OCP instructions never skip + SKS instructions skip on specified conditions + INA/OTA instructions skip if they succeed (data was read/written) +*/ + +#include + +void devnull (short class, short func, short device) { + + switch (class) { + + case 0: + fprintf(stderr," OCP '%2#0o%2#0o\n", func, device); + if (func == 0) { + ; + } else { + fprintf(stderr," unimplemented OCP device %2#0o function\n", device); + exit(1); + } + break; + + case 1: + fprintf(stderr," SKS '%2#0o%2#0o\n", func, device); + if (func == 0) + mem[P]++; /* assume it's always ready */ + else { + fprintf(stderr," unimplemented SKS device %2#0o function\n", device); + exit(1); + } + break; + + case 2: + fprintf(stderr," INA '%2#0o%2#0o\n", func, device); + if (func == 0) { + ; + } else { + fprintf(stderr," unimplemented INA device %2#0o function\n", device); + exit(1); + } + break; + + case 3: + fprintf(stderr," OTA '%2#0o%2#0o\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); + exit(1); + } + break; + } +} + + /* Device '4: system console OCP '0004 = initialize for input only, echoplex, 110 baud, 8-bit, no parity @@ -10,16 +69,15 @@ */ -#include - -void devasr (unsigned short class, unsigned short func) { +void devasr (short class, short func, short device) { static int ttydev=-1; unsigned char ch; + int ttyflags, newflags; int n; if (ttydev < 0) { - ttydev = open("/dev/tty", O_RDWR+O_NONBLOCK, 0); + ttydev = open("/dev/tty", O_RDWR, 0); if (ttydev < 0) { perror(" error opening /dev/tty"); exit(1); @@ -29,11 +87,11 @@ void devasr (unsigned short class, unsigned short func) { switch (class) { case 0: - fprintf(stderr," OCP '%o04\n", func); + fprintf(stderr," OCP '%2#0o%2#0o\n", func, device); break; case 1: - fprintf(stderr," SKS\n"); + fprintf(stderr," SKS '%2#0o%2#0o\n", func, device); if (func <= 7) mem[P]++; /* assume it's always ready */ else { @@ -43,9 +101,20 @@ void devasr (unsigned short class, unsigned short func) { break; case 2: - fprintf(stderr," INA\n"); + fprintf(stderr," INA '%2#0o%2#0o\n", func, device); if (func == 0 || func == 010) { - usleep(100000); + if (fcntl(ttydev, F_GETFL, ttyflags) == -1) { + perror(" unable to get tty flags"); + exit(1); + } + if (mem[mem[P]] == 03776) /* JMP *-1 -> blocking read */ + newflags = ttyflags & ~O_NONBLOCK; + else + newflags = ttyflags | O_NONBLOCK; + if (fcntl(ttydev, F_SETFL, newflags) == -1) { + perror(" unable to set tty flags"); + exit(1); + } n = read(ttydev, &ch, 1); if (n < 0) { if (errno != EAGAIN) { @@ -53,13 +122,19 @@ void devasr (unsigned short class, unsigned short func) { exit(1); } } else if (n == 1) { - mem[A] = ch | 0x80; + if (func >= 010) + mem[A] = 0; + mem[A] = mem[A] | ch | 0x80; mem[P]++; } else if (n != 0) { fprintf(stderr," unexpected error reading from tty, n=%d", n); exit(1); } - } else if (func == 012) { /* no idea what this does... */ + } else if (func == 011) { /* read device id? */ + mem[A] = 4; + mem[P]++; + } else if (func == 012) { /* read control word */ + mem[A] = 04110; mem[P]++; } else { fprintf(stderr," unimplemented INA '04 function\n"); @@ -68,12 +143,14 @@ void devasr (unsigned short class, unsigned short func) { break; case 3: - fprintf(stderr," OTA\n"); - if (func == 0 | func == 1) { + fprintf(stderr," OTA '%2#0o%2#0o\n", func, device); + if (func == 0) { fprintf(stderr," char to write=%o\n", mem[A]); putchar(mem[A] & 0x7f); fflush(stdout); mem[P]++; /* OTA '0004 always works on Unix */ + } else if (func == 1) { /* write control word */ + mem[P]++; } else { fprintf(stderr," unimplemented OTA '04 function\n"); exit(1); @@ -82,3 +159,52 @@ void devasr (unsigned short class, unsigned short func) { } } + + + +/* Device '20: control panel switches and lights + + OTA '1720 = write to lights (sets CP fetch address) + INA '1420 = read location from CP ROM (not implemented, used to boot) + INA '1620 = read control panel switches +*/ + +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); + 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); + exit(1); + break; + + case 2: + fprintf(stderr," INA '%2#0o%2#0o\n", func, device); + if (func == 016) { + mem[A] = 0; + } else { + fprintf(stderr," unimplemented INA device %2#0o function\n", device); + exit(1); + } + break; + + case 3: + fprintf(stderr," OTA '%2#0o%2#0o\n", func, device); + if (func == 017) { /* write lights */ + mem[P]++; + } else { + fprintf(stderr," unimplemented OTA device %2#0o function\n", device); + exit(1); + } + break; + } +} + + diff --git a/os.c b/os.c new file mode 100644 index 0000000..c1086ce --- /dev/null +++ b/os.c @@ -0,0 +1,180 @@ +/* os.c, Jim Wilcoxson, 4/15/2005 + Emulations of Primos Operating System routines for Unix. +*/ + +#include +#include +#include +#include +#include + +#include "os.h" +#include "syscom/keys.ins.cc" +#include "syscom/errd.ins.cc" + + +os_init() { + + os.ttydev = open("/dev/tty", O_RDWR, 0); + if (os.ttydev < 0) { + perror(" error opening /dev/tty"); + exit(1); + } +} + + +os_break$(short *onoff) { +} + +os_c1in(short *charg) { + unsigned char ch; + int n; + + fprintf(stderr," c1in waiting for data\n"); + n = read(os.ttydev, &ch, 1); + if (n < 0) { + perror(" error reading from tty"); + exit(1); + } + if (n != 1) { + fprintf(stderr," unexpected error reading from tty, n=%d", n); + exit(1); + } + *charg = ch | 0x80; +} + + +os_comanl() { +} + + +os_cnin$(unsigned char *buf, short *maxchars, short *n) { + short ch; + + *n = 0; + while (*n < *maxchars) { + os_c1in(&ch); + buf[*n] = ch; + (*n)++; + if (ch == 0212) break; + } +} + + +os_exit() { + fprintf(stderr,"\nProgram called EXIT\n"); + exit(1); +} + + +os_erkl$$(short *key, short *erasech, short *killch, short *code) { + if (*key == k$read) { + *erasech = 0210; + *killch = 0377; + *code = 0; + } +} + + +os_errpr$ (short *key, short *code, char *msg, short *msglen, char *prog, short *proglen) { + if (*code == 0) return; + fprintf (stderr, " key=%d, code=%d, msglen=%d, proglen=%d\n", *key, *code, *msglen, *proglen); + exit(1); +} + +os_ginfo (short *buf, short *bufsiz) { + int i; + + fprintf(stderr," ginfo bufsiz=%d\n", *bufsiz); + if (*bufsiz <= 0) return; + buf[0] = 0; + if (*bufsiz > 1) buf[1] = 0; + if (*bufsiz > 2) buf[2] = 61; /* max device # */ + for (i=0; i < *bufsiz-3; i++) + buf[i+3] = 440; /* disk record size */ +} + +/* RDTK$$ + + key - 1=read UC, 2=read, 3=reset, 4=rest, 5=init + info - output array + [0] = type - 1=normal, 2=regular, 5=null, 6=eol + info[1] = length + info[2] = flags + :100000=decimal, :40000=octal, :20000=dash, :10000=info[3] < 8 + info[3] = positional token's position 0-9 (1/44, 4/20, etc) + info[4] = positional token's value + buf - output token buffer + buflen - size in words of buf (in) + code - return code + +*/ + +os_rdtk$$(short *key, short *info, char *buf, short *buflen, short *code) { + fprintf(stderr," key=%d\n", *key); + *code = 0; + if (*key = 1) { + info[0] = 6; + info[1] = 0; + info[2] = 0; + info[3] = 0; + info[4] = 0; + } else { + exit(1); + } +} + +os_t1ou(short *charg) { + putchar(*charg & 0x7f); + fflush(stdout); +} + + +os_timdat(short *userbuf, short *n) { + clock_t tod; + struct tm tms; + struct { + char mmddyy[6]; + short timemins; /* minutes since midnight */ + short timesecs; /* plus seconds (0-50) */ + short timeticks; /* plus ticks (0-329 330ths of a second) */ + short cpusecs; + short cputicks; + short iosecs; + short ioticks; + short tickspersec; + short userno; + char username[32]; + } timbuf; + + if (sizeof(timbuf) != sizeof(short)*28) { + fprintf(stderr," sizeof(timebuf)=%d, size of 28-word array=%d\n", + sizeof(timbuf), sizeof(short)*28); + exit(1); + } + + tod = time(NULL); + localtime_r(&tod, &tms); + strncpy(timbuf.mmddyy,"042105",6); + timbuf.timemins = tms.tm_hour*60 + tms.tm_min; + timbuf.timesecs = tms.tm_sec; + timbuf.timeticks = 0; + timbuf.cpusecs = timbuf.cputicks = timbuf.iosecs = timbuf.ioticks = 0; + timbuf.tickspersec = 330; + timbuf.userno = 1; + strncpy(timbuf.username,"SYSTEM ",32); + memcpy(userbuf, &timbuf, *n*2); +} + + +os_tnoua(unsigned char *s, short *len) { + int i; + fprintf(stderr," writing %d char string \"", *len); + for (i=0; i < *len; i++) + fputc(s[i] & 0x7f,stderr); + fprintf(stderr,"\"\n"); + + for (i=0; i < *len; i++) + putchar(s[i] & 0x7f); + fflush(stdout); +} diff --git a/os.h b/os.h new file mode 100644 index 0000000..c6ff5fa --- /dev/null +++ b/os.h @@ -0,0 +1,8 @@ +/* os.h, Jim Wilcoxson, April 15, 2005 + Include file for Primos Operating System data structures. +*/ + +static struct { + int ttydev; +} os; +