/* * patch */ /*)BUILD $(TKBOPTIONS) = { TASK = ...ECH } */ #ifdef DOCUMENTATION title patch patch Test program for stream I/O patch index patch Test program for stream I/O patch synopsis patch [argument list] description patch writes its arguments on the standard output file. It then dumps the opfnb subroutine. It is used to debug the "suspicious" patch in init.mac author Martin Minow bugs #endif #include #define START 0 #define ENDLOC 02000 char *$$prmt = "patch: "; main(argc, argv) int argc; /* Number of arguments */ char *argv[]; /* Argument vector */ /* * Note: in order to print the program (or command) name, change START * from 1 to 0. */ { register int i; register int *pc; int *endloc; extern int _opfnb; printf("%d arguments\n", argc); for (i = START; i < argc; ++i) { printf("([%d] %s)", i, argv[i]); putchar(((i + 1) >= argc) ? '\n' : ' '); } endloc = &_opfnb; endloc += (ENDLOC / sizeof (int)); pc = &_opfnb; while (pc < endloc) { pc = pinst(pc); } } /* * Disassembler. * Based on old macro code I wrote * years ago. */ #include #define NONE 0 /* halt */ #define RTS 1 /* rts reg */ #define DOUBLE 2 /* mov src,dst */ #define SWBYTE 3 /* sop[b] dst */ #define SINGLE 4 /* sop dst */ #define JSR 5 /* jsr reg,dst */ #define MUL 6 /* mul src,reg */ #define BR 7 /* br addr */ #define SOB 8 /* sob reg,addr */ #define SPL 9 /* spl n */ #define MARK 10 /* mark n */ #define TRAP 11 /* trap n */ #define CODE 12 /* se[cvnz] */ struct tab { int t_mask; int t_op; char *t_str; int t_kind; }; static struct tab tab[] = { 0000000, 0000000, "halt", NONE, 0000000, 0000001, "wait", NONE, 0000000, 0000002, "rti", NONE, 0000000, 0000003, "bpt", NONE, 0000000, 0000004, "iot", NONE, 0000000, 0000005, "reset", NONE, 0000000, 0000006, "rtt", NONE, 0000007, 0000000, "illop", NONE, 0000077, 0000100, "jmp", SINGLE, 0000007, 0000200, "rts", RTS, 0000017, 0000210, "illop", NONE, 0000007, 0000230, "spl", SPL, 0000000, 0000240, "nop", NONE, 0000000, 0000241, "clc", NONE, 0000017, 0000240, "clear", CODE, 0000000, 0000261, "sec", NONE, 0000017, 0000260, "set", CODE, 0000077, 0000300, "swab", SINGLE, 0000377, 0000400, "br", BR, 0000377, 0001000, "bne", BR, 0000377, 0001400, "beq", BR, 0000377, 0002000, "bge", BR, 0000377, 0002400, "blt", BR, 0000377, 0003000, "bgt", BR, 0000377, 0003400, "ble", BR, 0000777, 0004000, "jsr", JSR, 0100077, 0005000, "clr", SWBYTE, 0100077, 0005100, "com", SWBYTE, 0100077, 0005200, "inc", SWBYTE, 0100077, 0005300, "dec", SWBYTE, 0100077, 0005400, "neg", SWBYTE, 0100077, 0005500, "adc", SWBYTE, 0100077, 0005600, "sbc", SWBYTE, 0100077, 0005700, "tst", SWBYTE, 0100077, 0006000, "ror", SWBYTE, 0100077, 0006100, "rol", SWBYTE, 0100077, 0006200, "asr", SWBYTE, 0100077, 0006300, "asl", SWBYTE, 0000077, 0006400, "mark", MARK, 0000077, 0006500, "mfpi", SINGLE, 0000077, 0006600, "mtpi", SINGLE, 0000077, 0006700, "sxt", SINGLE, 0000777, 0007000, "illop", NONE, 0107777, 0010000, "mov", DOUBLE, 0107777, 0020000, "cmp", DOUBLE, 0107777, 0030000, "bit", DOUBLE, 0107777, 0040000, "bic", DOUBLE, 0107777, 0050000, "bis", DOUBLE, 0007777, 0060000, "add", DOUBLE, 0007777, 0160000, "su", DOUBLE, 0000777, 0070000, "mul", MUL, 0000777, 0071000, "div", MUL, 0000777, 0072000, "ash", MUL, 0000777, 0073000, "ashc", MUL, 0000777, 0074000, "xor", JSR, 0000007, 0075000, "fadd", RTS, 0000007, 0075010, "fsub", RTS, 0000007, 0075020, "fmul", RTS, 0000007, 0075030, "fdiv", RTS, 0000777, 0077000, "sob", SOB, 0003777, 0074000, "illop", NONE, 0000377, 0100000, "bpl", BR, 0000377, 0100400, "bmi", BR, 0000377, 0101000, "bhi", BR, 0000377, 0101400, "blos", BR, 0000377, 0102000, "bvc", BR, 0000377, 0102400, "bvs", BR, 0000377, 0103000, "bhis", BR, 0000377, 0103400, "blo", BR, 0000377, 0104000, "emt", TRAP, 0000377, 0104400, "trap", TRAP, 0000077, 0106400, "illop", NONE, 0000077, 0106500, "mfpd", SINGLE, 0000077, 0106600, "mtpd", SINGLE, 0001777, 0106000, "illop", NONE, 0007777, 0170000, "45fpp", NONE, 0177777, 0000000, "illop", NONE }; #define NTAB (sizeof(tab) / sizeof(tab[0])) int * pinst(pc) register *pc; { register struct tab *tp; register op; int i, m; int *paddr(); printf("%06o\t", pc); op = *pc++; tp = &tab[0]; while (tp < &tab[NTAB]) { if ((op&~tp->t_mask) == tp->t_op) break; ++tp; } if (tp == &tab[NTAB]) { printf("[No match]\n"); return (pc); } printf("%s", tp->t_str); switch (tp->t_kind) { case SPL: printf("\t%d", op&07); break; case RTS: putchar('\t'); preg(op); break; case SWBYTE: if (op < 0) putchar('b'); case SINGLE: putchar('\t'); pc = paddr(pc, op); break; case DOUBLE: if (op < 0) putchar('b'); /* sub and bytes */ putchar('\t'); pc = paddr(pc, op>>6); putchar(','); pc = paddr(pc, op); break; case JSR: putchar('\t'); preg(op>>6); putchar(','); pc = paddr(pc, op); break; case MUL: putchar('\t'); pc = paddr(pc, op); putchar(','); preg(op>>6); break; case BR: putchar('\t'); op &= 0377; if ((op & 0200) != 0) op |= ~0377; printf("%o", (int)pc + (op<<1)); break; case SOB: putchar('\t'); preg(op>>6); putchar(','); printf("%o", (int)pc + ((op|~077)<<1)); break; case MARK: case TRAP: putchar('\t'); if (tp->t_kind == MARK) op &= 077; else op &= 0377; printf("%o", op); break; case CODE: putchar('\t'); m = 01; for (i=0; i<4; ++i) { if ((op & m) != 0) putchar("czvn"[i]); m <<= 1; } } putchar('\n'); return (pc); } int * paddr(pc, m) register *pc; { register r, x; r = m&07; switch (m&070) { case 0: /* r1 */ preg(r); break; case 010: /* (r1) */ putchar('('); preg(r); putchar(')'); break; case 030: /* @#foo */ putchar('@'); case 020: /* #foo or @#foo */ if (r == 7) { /* #123 */ putchar('#'); printf("%o", *pc++); break; } putchar('('); /* 123(r1) or @123(r1) */ preg(r); putchar(')'); putchar('+'); break; case 050: putchar('@'); /* @-(r1), */ case 040: /* -(r1) */ putchar('-'); putchar('('); preg(r); putchar(')'); break; case 070: putchar('@'); /* @(r1)+ */ case 060: /* (r1)+ */ x = *pc++; if (r == 7) { printf("%o", (int)pc + x); break; } printf("%o(", x); preg(r); putchar(')'); } return (pc); } preg(r) register r; { r &= 07; if (r == 7) printf("pc"); else if (r == 6) printf("sp"); else printf("r%d", r); }