/* ** Code derived from program runoggin */ extern void exit(); /* ** Definitions for i/o */ # include typedef struct { FILE *fp; unsigned short eoln:1, eof:1, out:1, init:1, :12; char buf; } text; text input = { stdin, 0, 0 }; text output = { stdout, 0, 0 }; # define Fread(x, f) fread((char *)&x, sizeof(x), 1, f) # define Get(f) Fread((f).buf, (f).fp) # define Getx(f) (f).init = 1, (f).eoln = (((f).buf = fgetc((f).fp)) == '\n') ? (((f).buf = ' '), 1) : 0 # define Getchr(f) (f).buf, Getx(f) static FILE *Tmpfil; static long Tmplng; static double Tmpdbl; # define Fscan(f) (f).init ? ungetc((f).buf, (f).fp) : 0, Tmpfil = (f).fp # define Scan(p, a) Scanck(fscanf(Tmpfil, p, a)) void Scanck(); void Getl(); # define Eoln(f) ((f).eoln ? true : false) # define Eof(f) ((((f).init == 0) ? (Get(f)) : 0, ((f).eof ? 1 : feof((f).fp))) ? true : false) # define Fwrite(x, f) fwrite((char *)&x, sizeof(x), 1, f) # define Put(f) Fwrite((f).buf, (f).fp) # define Putx(f) (f).eoln = ((f).buf == '\n'), (void)fputc((f).buf, (f).fp) # define Putchr(c, f) (f).buf = (c), Putx(f) # define Putl(f, v) (f).eoln = v # define Finish(f) ((f).out && !(f).eoln) ? (Putchr('\n', f), 0) : 0, rewind((f).fp) # ifdef READONLY static char Rmode[] = "r"; # else static char Rmode[] = "r+"; # endif # define Reset(f, n) (f).init = (f).init ? rewind((f).fp) : (((f).fp = Fopen(n, Rmode)), 1), (f).eof = (f).out = 0, Get(f) # define Resetx(f, n) (f).init = (f).init ? (Finish(f)) : (((f).fp = Fopen(n, Rmode)), 1), (f).eof = (f).out = 0, Getx(f) FILE *Fopen(); # define MAXFILENAME 256 /* ** Definitions for case-statements ** and for non-local gotos */ # define Line __LINE__ void Caseerror(); /* ** Definitions for standard types */ typedef char boolean; # define false (boolean)0 # define true (boolean)1 extern char *Bools[]; typedef int integer; extern void abort(); extern char *strncpy(); /* ** Start of program definitions */ typedef struct { integer A[1023 + 1]; } memory; typedef text samplefile; typedef struct { char A[6 - 1 + 1]; } octalcode; typedef enum { lda, sta, ldi, add, sub, cmp, andd, ora, jsr, jmp } ingroup1; typedef enum { stp, rts, asr, asl, neg, psh, pul, clr, inc, lsr } ingroup2; typedef enum { beq, bne, bgt, bge, blt, ble, bcs, bcc } ingroup3; typedef enum { group1, group2, group3 } instructiongroup; typedef enum { immediate, direct, indirect, indexed } addressingmodes; typedef unsigned char statusword; typedef struct { statusword A[15 + 1]; } ogginword; integer *G59_operand; memory mm; integer blockaddress; integer blocksize; boolean errorstatus; integer bits12_14; addressingmodes addressmode; instructiongroup opcodegroup; integer operand; ingroup1 opcodeg1; ingroup2 opcodeg2; ingroup3 opcodeg3; integer pc; integer pcnew; integer mdr; integer acc; integer sp; integer ir; integer temp; statusword c; statusword z; statusword n; ogginword resultofoperation; ogginword valueinogg1; ogginword valueinogg2; boolean endofprogram; void readoct(f, buffer) samplefile *f; integer *buffer; { char ch; (*buffer) = 0; while (!Eoln((*f))) { ch = Getchr((*f)); (*buffer) = ((*buffer)) * 8 + ((unsigned)(ch) - (unsigned)('0')); } Getl(&(*f)); } void writecycle(address, datain, error) integer address, datain; boolean *error; { (*error) = (boolean)((address < 0) || (address > 1023)); if (!(*error)) mm.A[address] = datain; } void readfile(f) samplefile *f; { register integer count; integer data; integer blockaddress; integer blocksize; boolean errorstatus; Resetx((*f), NULL); readoct(&(*f), &blockaddress); pc = blockaddress; while (!Eof((*f))) { readoct(&(*f), &blocksize); { integer B1 = 1, B2 = blocksize; if (B1 <= B2) for (count = B1; ; count++) { readoct(&(*f), &data); writecycle(blockaddress, data, &errorstatus); if (errorstatus) { (void)fprintf(output.fp, "Invalid store address error in"), Putl(output, 0); (void)fprintf(output.fp, "%10d\n", blockaddress), Putl(output, 1); abort(); } blockaddress = blockaddress + 1; if (count == B2) break; } } if (!Eof((*f))) readoct(&(*f), &blockaddress); } } void initialise() { mdr = 0; acc = 0; sp = 1024; ir = 0; temp = 0; c = 0; n = 0; z = 0; } void readcycle(address, data, error) integer address; integer *data; boolean *error; { (*error) = (boolean)((address < 0) || (address > 1023)); if (!(*error)) (*data) = mm.A[address]; } void decoding(data, opg, rmdr, operand) integer data; instructiongroup *opg; integer *rmdr; integer *operand; { if (data < 4096) (*opg) = group2; else { (*operand) = data % 1024; data = data - (*operand); if (data >= 32768) { (*rmdr) = (data % 32768) / 4096; switch ((*rmdr)) { case 0: case 7: (*opg) = group3; break ; case 1: case 2: case 3: (*opg) = group1; break ; default: Caseerror(Line); } } else (*opg) = group1; } } void integertooggin(source, oggin) integer source; ogginword *oggin; { register integer i; { integer B3 = 0, B4 = 15; if (B3 <= B4) for (i = B3; ; i++) { oggin->A[i] = 0; if (i == B4) break; } } i = 0; do { oggin->A[i] = source % 2; source = source / 2; i = i + 1; } while (!(source == 0)); } void oggintointeger(source, result) ogginword source; integer *result; { register integer i; (*result) = 0; { integer B5 = 15, B6 = 0; if (B5 >= B6) for (i = B5; ; i--) { (*result) = ((*result) * 2) + source.A[i]; if (i == B6) break; } } } void addword(p, q, r) ogginword p, q; ogginword *r; { statusword c_bit; register integer i; c_bit = 0; { integer B7 = 0, B8 = 15; if (B7 <= B8) for (i = B7; ; i++) { r->A[i] = (p.A[i] + q.A[i] + c_bit) % 2; c_bit = (p.A[i] + q.A[i] + c_bit) / 2; if (i == B8) break; } } if (c_bit == 1) c = 1; else c = 0; } void onescomplement(result) ogginword *result; { register integer i; { integer B9 = 0, B10 = 15; if (B9 <= B10) for (i = B9; ; i++) { if (result->A[i] == 0) result->A[i] = 1; else result->A[i] = 0; if (i == B10) break; } } } void twoscomplement(source) ogginword *source; { ogginword result; register integer i; ogginword one; { integer B11 = 0, B12 = 15; if (B11 <= B12) for (i = B11; ; i++) { result.A[i] = 0; if (i == B12) break; } } one.A[0] = 1; { integer B13 = 1, B14 = 15; if (B13 <= B14) for (i = B13; ; i++) { one.A[i] = 0; if (i == B14) break; } } addword((*source), one, &result); (*source) = result; } void decidenzbits() { if (resultofoperation.A[15] == 1) n = 1; else n = 0; oggintointeger(resultofoperation, &acc); if (acc == 0) z = 1; else z = 0; } void dogroup1(); void degrp1(data, code, mode) integer data; ingroup1 *code; addressingmodes *mode; { integer i; i = data; switch (data / 4096) { case 1: (*code) = lda; break ; case 2: (*code) = sta; break ; case 3: (*code) = ldi; break ; case 4: (*code) = add; break ; case 5: (*code) = sub; break ; case 6: (*code) = cmp; break ; case 7: (*code) = andd; break ; case 9: (*code) = ora; break ; case 10: (*code) = jsr; break ; case 11: (*code) = jmp; break ; default: Caseerror(Line); } switch ((i % 4096) / 1024) { case 0: (*mode) = immediate; break ; case 1: (*mode) = direct; break ; case 2: (*mode) = indirect; break ; case 3: (*mode) = indexed; break ; default: Caseerror(Line); } } void exgrp1(); void getdata(mode, operand) addressingmodes mode; integer operand; { integer mdr; boolean errorstatus; switch (mode) { case immediate: temp = operand; break ; case direct: readcycle(operand, &mdr, &errorstatus); temp = mdr; break ; case indirect: readcycle(operand, &mdr, &errorstatus); operand = mdr; readcycle(operand, &mdr, &errorstatus); temp = mdr; break ; case indexed: operand = ir + operand; readcycle(operand, &mdr, &errorstatus); temp = mdr; break ; default: Caseerror(Line); } } void lda_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); acc = temp; integertooggin(acc, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void sta_p(mode, operand) addressingmodes mode; integer operand; { integer mdr; boolean errorstatus; switch (mode) { case direct: writecycle(operand, acc, &errorstatus); break ; case indirect: readcycle(operand, &mdr, &errorstatus); operand = mdr; writecycle(operand, acc, &errorstatus); break ; case indexed: operand = ir + operand; writecycle(operand, acc, &errorstatus); break ; default: Caseerror(Line); } integertooggin(acc, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void ldi_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); ir = temp; integertooggin(ir, &resultofoperation); if (resultofoperation.A[15] == 1) n = 1; else n = 0; if (ir == 0) z = 1; else z = 0; pcnew = pc + 1; } void andd_p(mode, operand) addressingmodes mode; integer operand; { register integer i; { integer B15 = 0, B16 = 15; if (B15 <= B16) for (i = B15; ; i++) { resultofoperation.A[i] = 0; if (i == B16) break; } } getdata(mode, operand); integertooggin(acc, &valueinogg1); integertooggin(temp, &valueinogg2); { integer B17 = 0, B18 = 15; if (B17 <= B18) for (i = B17; ; i++) { resultofoperation.A[i] = valueinogg1.A[i] * valueinogg2.A[i]; if (i == B18) break; } } decidenzbits(); pcnew = pc + 1; } void sub_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); integertooggin(acc, &valueinogg1); integertooggin(temp, &valueinogg2); onescomplement(&valueinogg2); twoscomplement(&valueinogg2); addword(valueinogg1, valueinogg2, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void cmp_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); integertooggin(acc, &valueinogg1); integertooggin(temp, &valueinogg2); onescomplement(&valueinogg2); twoscomplement(&valueinogg2); addword(valueinogg1, valueinogg2, &resultofoperation); if (resultofoperation.A[15] == 1) n = 1; else n = 0; oggintointeger(resultofoperation, &temp); if (temp == 0) z = 1; else z = 0; pcnew = pc + 1; } void ora_p(mode, operand) addressingmodes mode; integer operand; { register integer i; { integer B19 = 0, B20 = 15; if (B19 <= B20) for (i = B19; ; i++) { resultofoperation.A[i] = 1; if (i == B20) break; } } getdata(mode, operand); integertooggin(acc, &valueinogg1); integertooggin(temp, &valueinogg2); { integer B21 = 0, B22 = 15; if (B21 <= B22) for (i = B21; ; i++) { if ((valueinogg1.A[i] == 0) && (valueinogg2.A[i] == 0)) resultofoperation.A[i] = 0; if (i == B22) break; } } decidenzbits(); pcnew = pc + 1; } void jsr_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); sp = sp - 1; mm.A[sp] = pc + 1; pcnew = temp; } void jmp_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); pcnew = temp; } void add_p(mode, operand) addressingmodes mode; integer operand; { getdata(mode, operand); integertooggin(acc, &valueinogg1); integertooggin(temp, &valueinogg2); addword(valueinogg1, valueinogg2, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void exgrp1(code, mode, bits0_9) ingroup1 code; addressingmodes mode; integer bits0_9; { switch (code) { case lda: lda_p(mode, bits0_9); break ; case sta: sta_p(mode, bits0_9); break ; case ldi: ldi_p(mode, bits0_9); break ; case add: add_p(mode, bits0_9); break ; case sub: sub_p(mode, bits0_9); break ; case cmp: cmp_p(mode, bits0_9); break ; case andd: andd_p(mode, bits0_9); break ; case ora: ora_p(mode, bits0_9); break ; case jsr: jsr_p(mode, bits0_9); break ; case jmp: jmp_p(mode, bits0_9); break ; default: Caseerror(Line); } } void dogroup1(bits10_15, code1, mode, operand) integer bits10_15; ingroup1 *code1; addressingmodes *mode; integer operand; { degrp1(bits10_15, &(*code1), &(*mode)); exgrp1((*code1), (*mode), operand); } void dogroup2(); void degrp2(data, code) integer data; ingroup2 *code; { if (data == 14) (*code) = lsr; else if (data <= 8) switch (data) { case 0: (*code) = stp; break ; case 1: (*code) = rts; break ; case 2: (*code) = asr; break ; case 3: (*code) = asl; break ; case 4: (*code) = neg; break ; case 5: (*code) = psh; break ; case 6: (*code) = pul; break ; case 7: (*code) = clr; break ; case 8: (*code) = inc; break ; default: Caseerror(Line); } } void exgrp2(); void psh_group2() { sp = sp - 1; mm.A[sp] = acc; integertooggin(acc, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void pul_group2() { acc = mm.A[sp]; sp = sp + 1; integertooggin(acc, &resultofoperation); decidenzbits(); pcnew = pc + 1; } void asr_group2() { register integer i; integertooggin(acc, &resultofoperation); c = resultofoperation.A[0]; { integer B23 = 0, B24 = 14; if (B23 <= B24) for (i = B23; ; i++) { resultofoperation.A[i] = resultofoperation.A[i + 1]; if (i == B24) break; } } decidenzbits(); pcnew = pc + 1; } void asl_group2() { register integer i; integertooggin(acc, &resultofoperation); c = resultofoperation.A[15]; { integer B25 = 0, B26 = 14; if (B25 <= B26) for (i = B25; ; i++) { valueinogg1.A[i + 1] = resultofoperation.A[i]; if (i == B26) break; } } valueinogg1.A[0] = 0; resultofoperation = valueinogg1; decidenzbits(); pcnew = pc + 1; } void neg_group2() { integer i; integertooggin(acc, &resultofoperation); onescomplement(&resultofoperation); twoscomplement(&resultofoperation); decidenzbits(); if (acc == 0) c = 0; else c = 1; pcnew = pc + 1; } void lsr_group2() { register integer i; statusword ctemp; integertooggin(acc, &resultofoperation); ctemp = c; c = resultofoperation.A[0]; { integer B27 = 0, B28 = 14; if (B27 <= B28) for (i = B27; ; i++) { resultofoperation.A[i] = resultofoperation.A[i + 1]; if (i == B28) break; } } resultofoperation.A[15] = ctemp; decidenzbits(); pcnew = pc + 1; } void inc_group2() { ir = ir + 1; integertooggin(ir, &resultofoperation); if (resultofoperation.A[15] == 1) n = 1; else n = 0; if (ir == 0) z = 1; else z = 0; pcnew = pc + 1; } void exgrp2(code) ingroup2 code; { switch (code) { case stp: pcnew = pc + 1; break ; case rts: pcnew = mm.A[sp]; sp = sp + 1; break ; case psh: psh_group2(); break ; case pul: pul_group2(); break ; case asr: asr_group2(); break ; case asl: asl_group2(); break ; case neg: neg_group2(); break ; case lsr: lsr_group2(); break ; case inc: inc_group2(); break ; default: Caseerror(Line); } } void dogroup2(data, code2) integer data; ingroup2 *code2; { degrp2(data, &(*code2)); exgrp2((*code2)); if ((*code2) == stp) endofprogram = true; } void dogroup3(); void degrp3(r, data, code) integer r, data; ingroup3 *code; { switch (r) { case 0: switch ((data % 4096) / 512) { case 0: (*code) = beq; break ; case 2: (*code) = bne; break ; case 4: (*code) = bgt; break ; case 6: (*code) = bge; break ; default: Caseerror(Line); } break ; case 7: switch ((data % 4096) / 512) { case 0: (*code) = blt; break ; case 2: (*code) = ble; break ; case 4: (*code) = bcs; break ; case 6: (*code) = bcc; break ; default: Caseerror(Line); } break ; default: Caseerror(Line); } } void exgrp3(); void beq_group3() { if (z == 1) pcnew = (*G59_operand); else pcnew = pc + 1; } void bne_group3() { if (z == 0) pcnew = (*G59_operand); else pcnew = pc + 1; } void bgt_group3() { if ((z == 0) && (n == 0)) pcnew = (*G59_operand); else pcnew = pc + 1; } void bge_group3() { if (n == 0) pcnew = (*G59_operand); else pcnew = pc + 1; } void blt_group3() { if ((n == 1) && (z == 0)) pcnew = (*G59_operand); else pcnew = pc + 1; } void ble_group3() { if ((n == 1) || (z == 1)) pcnew = (*G59_operand); else pcnew = pc + 1; } void bcc_group3() { if (c == 0) pcnew = (*G59_operand); else pcnew = pc + 1; } void exgrp3(code, operand) ingroup3 code; integer operand; { integer *F60; F60 = G59_operand; G59_operand = &operand; switch (code) { case beq: beq_group3(); break ; case bne: bne_group3(); break ; case bgt: bgt_group3(); break ; case bge: bge_group3(); break ; case blt: blt_group3(); break ; case ble: ble_group3(); break ; case bcc: bcc_group3(); break ; default: Caseerror(Line); } G59_operand = F60; } void dogroup3(bits12_14, bits10_15, code3, operand) integer bits12_14; integer bits10_15; ingroup3 *code3; integer operand; { degrp3(bits12_14, bits10_15, &(*code3)); exgrp3((*code3), operand); } void writeoct(datain) integer datain; { integer i; integer no; octalcode oct; (void)strncpy(oct.A, "000000", sizeof(oct.A)); i = 6; do { no = datain % 8; oct.A[i - 1] = no + (unsigned)('0'); datain = datain / 8; i = i - 1; } while (!(datain == 0)); (void)fprintf(output.fp, "%.6s", oct.A), Putl(output, 0); } void writeline() { Putchr('\n', output); (void)fprintf(output.fp, "pc="), Putl(output, 0); writeoct(pc); (void)fprintf(output.fp, " instr="), Putl(output, 0); writeoct(mdr); (void)fprintf(output.fp, " acc="), Putl(output, 0); writeoct(acc); (void)fprintf(output.fp, " sp="), Putl(output, 0); writeoct(sp); (void)fprintf(output.fp, " index="), Putl(output, 0); writeoct(ir); (void)fprintf(output.fp, " CNZ=%1d%1d%1d", c, n, z), Putl(output, 0); pc = pcnew; (void)fprintf(output.fp, " pc<-"), Putl(output, 0); writeoct(pc); Putchr('\n', output); } void writestack() { register integer x; { integer B29 = 1023, B30 = sp; if (B29 >= B30) for (x = B29; ; x--) { writeoct(mm.A[x]); (void)fprintf(output.fp, " "), Putl(output, 0); if (x == B30) break; } } Putchr('\n', output); } /* ** Start of program code */ main() { readfile(&testfile); initialise(); endofprogram = false; do { readcycle(pc, &mdr, &errorstatus); if (errorstatus) { (void)fprintf(output.fp, " Invalid access address error in %10d\n", mm.A[pc]), Putl(output, 1); abort(); } decoding(mdr, &opcodegroup, &bits12_14, &operand); switch (opcodegroup) { case group1: dogroup1(mdr - operand, &opcodeg1, &addressmode, operand); break ; case group2: dogroup2(mdr, &opcodeg2); break ; case group3: dogroup3(bits12_14, mdr - operand, &opcodeg3, operand); break ; default: Caseerror(Line); } writeline(); writestack(); } while (!(endofprogram)); exit(0); } /* ** End of program code */ static void Getl(f) text *f; { while (f->eoln == 0) Getx(*f); Getx(*f); } static FILE * Fopen(n, m) char *n, *m; { FILE *f; register char *s; static char ch = 'A'; static char tmp[MAXFILENAME]; extern int unlink(); if (n == NULL) sprintf(tmp, "/tmp/ptc%d%c", getpid(), ch++); else { strncpy(tmp, n, sizeof(tmp)); for (s = &tmp[sizeof(tmp)-1]; *s == ' ' || *s == '\0'; ) *s-- = '\0'; if (tmp[sizeof(tmp)-1]) { (void)fprintf(stderr, "Too long filename '%s'\n", n); exit(1); } } s = tmp; if ((f = fopen(s, m)) == NULL) { (void)fprintf(stderr, "Cannot open: %s\n", s); exit(1); } if (n == NULL) unlink(tmp); return (f); } extern int rewind(); static void Caseerror(n) int n; { (void)fprintf(stderr, "Missing case limb: line %d\n", n); exit(1); }