#include #include #include #include #include "pdp6common.h" #include "pdp6bin.h" #include "../args.h" char *argv0; enum { MAXSYM = 1000 }; FILE* mustopen(const char *name, const char *mode) { FILE *f; if(f = fopen(name, mode), f == NULL){ fprintf(stderr, "couldn't open file: %s\n", name); exit(1); } return f; } FILE *in; hword itemsz; word mem[01000000]; hword rel, loc; int error; char **files; int nfiles; /* * debugging helpers */ void printinst(hword p) { printf("%06o: %06o %06o %s\n", p, left(mem[p]), right(mem[p]), disasm(mem[p])); } void disasmrange(hword start, hword end) { for(; start < end; start++) printinst(start); } /* emulate PDP-6 IBP instruction */ word ibp(word bp) { word pos, sz, p; pos = (bp>>30)&077; sz = (bp>>24)&077; p = right(bp); if(pos >= sz) return point(pos-sz, sz, p); return point(36-sz, sz, p+1); } /* emulate PDP-6 LDB instruction */ word ldb(word bp) { word pos, sz, p; pos = (bp>>30)&077; sz = (bp>>24)&077; p = right(bp); return (mem[p]>>pos) & (1<>30)&074; if(sym == NULL){ /* Symbol not in table yet. * TODO: ignore locals? */ // if(newtype == SymGlobal || newtype == SymGlobalH || // newtype == SymUndef){ assert(symp < MAXSYM); symtab[symp++] = newsym[0]; symtab[symp++] = newsym[1]; // } return; } type = unrad50(sym[0], name); if(type == SymUndef){ /* global request is in table */ if(newtype == SymGlobal || newtype == SymGlobalH){ /* found definition, resolve request chain * and insert definition into table */ resolvereq(right(sym[1]), right(newsym[1])); sym[0] = newsym[0]; sym[1] = newsym[1]; }else if(newtype == SymUndef) /* extend request chain */ extendreq(right(sym[1]), right(newsym[1])); }else if(type == SymGlobal || type == SymGlobalH){ /* global definition is in table */ if(newtype == SymGlobal || newtype == SymGlobalH){ if(newtype == type && newsym[1] == sym[1]) return; fprintf(stderr, "Error: multiple definitions: %s\n", name); error = 1; }else if(newtype == SymUndef) /* just resolve request */ resolvereq(right(newsym[1]), right(sym[1])); } } /* print symbol table, not needed */ void dumpsym(void) { int type; char name[8]; word p; for(p = 0; p < symp; p += 2){ type = unrad50(symtab[p], name); printf(" %02o %s %012lo\n", type, name, symtab[p+1]); } } /* Make sure there are no undefined symbols left */ void checkundef(void) { int type; char name[8]; word p; for(p = 0; p < symp; p += 2){ type = unrad50(symtab[p], name); if(type != SymUndef) continue; error = 1; printf(" Error: undefined: %s %012lo\n", name, symtab[p+1]); } } word block[18]; hword blocksz; word getword(FILE *f) { int i, b; word w; w = 0; for(i = 0; i < 6; i++){ if(b = getc(f), b == EOF) return ~0; w = (w << 6) | (b & 077); } return w; } void readblock(int mode) { word reloc; hword i; hword l, r; int bits; blocksz = 0; if(itemsz == 0) return; reloc = getword(in); i = 18; while(itemsz && i--){ block[blocksz++] = getword(in); itemsz--; } /* relocate block */ for(i = 0; i < 18; i++){ bits = (reloc >> 34) & 03; reloc <<= 2; if(mode == 1){ l = left(block[i]); r = right(block[i]); if(bits & 1) r += rel; if(bits & 2) l += rel; block[i] = fw(l, r); /* This is weird but necessary for full word reloc */ }else if(mode == 2){ if(bits & 1) block[i] = (block[i] + rel) & 0777777777777; } } } void handlename(void) { word w; int id; char name[8]; readblock(0); w = block[0]; while(itemsz) readblock(0); id = unrad50(w, name); } void handlecode(void) { int i; readblock(1); loc = right(block[0]); i = 1; if(i < blocksz) // hacky goto loop; while(itemsz){ readblock(1); for(i = 0; i < blocksz; i++){ loop: mem[loc] = block[i]; loc++; } } } void handlestart(void) { word w; readblock(1); w = block[0]; while(itemsz) readblock(1); } void handlesym(void) { int i; while(itemsz){ readblock(2); i = 0; while(i < blocksz){ loadsym(&block[i]); i += 2; } } } void skipitem(void) { while(itemsz) readblock(0); } void save(const char *filename) { FILE *out; out = mustopen(filename, "wb"); fclose(out); } void usage(void) { fprintf(stderr, "usage: %s\n", argv0); exit(1); } int main(int argc, char *argv[]) { word w; hword type; int i; void (*typesw[8])(void) = { skipitem, handlecode, handlesym, skipitem, skipitem, skipitem, handlename, handlestart, }; ARGBEGIN{ case 'r': rel = strtol(EARGF(usage()), NULL, 8); break; default: usage(); }ARGEND; nfiles = argc; files = argv; for(i = 0; i < nfiles; i++){ in = mustopen(files[i], "rb"); while(w = getword(in), w != ~0){ type = left(w); itemsz = right(w); typesw[type](); } fclose(in); } checkundef(); if(error) return 1; // disasmrange(findsym(rad50(0, "LINKSR"))[1], // findsym(rad50(0, "LINEP"))[1]); // disasmrange(0600+rel, 0603+rel); save("a.dump"); return 0; }