mirror of
https://github.com/aap/pdp6.git
synced 2026-01-11 23:53:31 +00:00
assembler & linker basically working
This commit is contained in:
parent
8342f86563
commit
3df4051093
302
tools/as6.c
302
tools/as6.c
@ -69,6 +69,14 @@ struct Value
|
||||
int rel; /* 0 = absolute, else relative */
|
||||
};
|
||||
|
||||
typedef struct Additive Additive;
|
||||
struct Additive
|
||||
{
|
||||
int l;
|
||||
Value v;
|
||||
Additive *next;
|
||||
};
|
||||
|
||||
typedef struct Sym Sym;
|
||||
struct Sym
|
||||
{
|
||||
@ -78,8 +86,8 @@ struct Sym
|
||||
Value v;
|
||||
void (*f)(void);
|
||||
};
|
||||
Additive *add;
|
||||
};
|
||||
Sym symtab[MAXSYM];
|
||||
|
||||
typedef struct Token Token;
|
||||
struct Token
|
||||
@ -117,7 +125,11 @@ char *argv0;
|
||||
char *filename;
|
||||
char **files;
|
||||
int nfiles;
|
||||
FILE *infp, *tmpfp, *lstfp;
|
||||
FILE *infp, *tmpfp, *relfp, *lstfp;
|
||||
char progtitle[MAXLINE];
|
||||
char progsubtitle[MAXLINE];
|
||||
int hadstart;
|
||||
Value start;
|
||||
char line[MAXLINE];
|
||||
char curline[MAXLINE]; /* unmodified line for listing */
|
||||
char *lp; /* pointer to input */
|
||||
@ -126,17 +138,29 @@ int numops;
|
||||
int lineno;
|
||||
int pass2;
|
||||
int error;
|
||||
Sym symtab[MAXSYM];
|
||||
Sym *dot;
|
||||
Value absdot, reldot; /* saved values of dot */
|
||||
int radix = 8;
|
||||
Token peekt;
|
||||
|
||||
/*
|
||||
* for REL output
|
||||
*/
|
||||
word item[01000000];
|
||||
hword itemp;
|
||||
hword itemtype, itemsz;
|
||||
|
||||
hword relocp;
|
||||
word blockreloc;
|
||||
int blocksz;
|
||||
|
||||
/* Helpers */
|
||||
|
||||
void
|
||||
err(int n, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
// if(pass2 && n < 2)
|
||||
// return;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s:%d: ", filename, lineno);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
@ -165,6 +189,60 @@ mustopen(const char *name, const char *mode)
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Output/listing */
|
||||
|
||||
void
|
||||
writeout(void)
|
||||
{
|
||||
hword i;
|
||||
for(i = 0; i < itemp-1; i++){
|
||||
writew(item[i], relfp);
|
||||
// printf("\t\tDUMP: %06o %06o\n", left(item[i]), right(item[i]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Start a REL block */
|
||||
void
|
||||
startblock(void)
|
||||
{
|
||||
if(blocksz){
|
||||
blockreloc <<= 2*(18-blocksz);
|
||||
item[relocp] = blockreloc;
|
||||
relocp = itemp++;
|
||||
blockreloc = 0;
|
||||
blocksz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put a relocated word into REL block */
|
||||
void
|
||||
putword(word w, int reloc)
|
||||
{
|
||||
item[itemp++] = w;
|
||||
blockreloc = blockreloc<<2 | reloc;
|
||||
blocksz++;
|
||||
itemsz++;
|
||||
if(blocksz == 18)
|
||||
startblock();
|
||||
}
|
||||
|
||||
/* Start a REL item and write out the last one */
|
||||
void
|
||||
startitem(hword it)
|
||||
{
|
||||
startblock();
|
||||
if(itemsz){
|
||||
item[0] = fw(itemtype, itemsz);
|
||||
writeout();
|
||||
}
|
||||
|
||||
itemtype = it;
|
||||
itemsz = 0;
|
||||
itemp = 1;
|
||||
relocp = itemp++;
|
||||
}
|
||||
|
||||
int lastline; /* last line number printed in listing */
|
||||
void
|
||||
listline(void)
|
||||
@ -176,24 +254,45 @@ listline(void)
|
||||
lastline = lineno;
|
||||
}
|
||||
|
||||
word relbreak, absbreak;
|
||||
Value lastdot;
|
||||
|
||||
/* Emit a relocated word at dot and advance dot */
|
||||
void
|
||||
putv(word w, int rel)
|
||||
{
|
||||
printf("\t%06o%c\t%06o%c%06o%c\n",
|
||||
right(dot->v.val), dot->v.rel ? '\'' : ' ',
|
||||
left(w), rel & 2 ? '\'' : ' ',
|
||||
right(w), rel & 1 ? '\'' : ' ');
|
||||
if(pass2){
|
||||
/* TODO: actually put a word */
|
||||
fprintf(lstfp, "%06o%c\t%06o%c%06o%c\t",
|
||||
right(dot->v.val), dot->v.rel ? '\'' : ' ',
|
||||
left(w), rel & 2 ? '\'' : ' ',
|
||||
right(w), rel & 1 ? '\'' : ' ');
|
||||
listline();
|
||||
|
||||
if(dot->v.rel != lastdot.rel ||
|
||||
dot->v.val != lastdot.val+1){
|
||||
startitem(Code);
|
||||
putword(dot->v.val, dot->v.rel);
|
||||
}
|
||||
putword(w, rel);
|
||||
}else{
|
||||
printf("\t%06o%c\t%06o%c%06o%c\n",
|
||||
right(dot->v.val), dot->v.rel ? '\'' : ' ',
|
||||
left(w), rel & 2 ? '\'' : ' ',
|
||||
right(w), rel & 1 ? '\'' : ' ');
|
||||
}
|
||||
lastdot = dot->v;
|
||||
dot->v.val++;
|
||||
if(dot->v.rel){
|
||||
if(dot->v.val > relbreak)
|
||||
relbreak = dot->v.val;
|
||||
}else{
|
||||
if(dot->v.val > absbreak)
|
||||
absbreak = dot->v.val;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input */
|
||||
|
||||
char*
|
||||
getln(void)
|
||||
{
|
||||
@ -201,8 +300,15 @@ getln(void)
|
||||
char *s;
|
||||
static char filen[MAXLINE];
|
||||
|
||||
if(pass2){
|
||||
if(pass2)
|
||||
for(;;){
|
||||
/* if no words were produced,
|
||||
* list the original line here */
|
||||
if(lastline == lineno-1){
|
||||
fprintf(lstfp, "\t%14s\t", "");
|
||||
listline();
|
||||
}
|
||||
|
||||
c = getc(tmpfp);
|
||||
if(c == 1){ /* filename */
|
||||
s = filen;
|
||||
@ -214,13 +320,6 @@ getln(void)
|
||||
lineno = 0;
|
||||
lastline = 0;
|
||||
}else if(c == 2){ /* line */
|
||||
/* if no words were produced,
|
||||
* list the original line here */
|
||||
if(lastline == lineno-1){
|
||||
fprintf(lstfp, "\t%14s\t", "");
|
||||
listline();
|
||||
}
|
||||
|
||||
s = line;
|
||||
while(c = getc(tmpfp), c)
|
||||
*s++ = c;
|
||||
@ -231,7 +330,6 @@ getln(void)
|
||||
}else if(c == 3) /* EOF */
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
s = line;
|
||||
lineno++;
|
||||
@ -264,6 +362,8 @@ skipwhite(void)
|
||||
lp++;
|
||||
}
|
||||
|
||||
/* Symbols */
|
||||
|
||||
/* Just find symbol, or return nil.
|
||||
* TODO: improve linear search... */
|
||||
Sym*
|
||||
@ -295,6 +395,37 @@ found:
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
updateext(Sym *s, Value *v, int l)
|
||||
{
|
||||
Additive *a;
|
||||
|
||||
if(!pass2 || s == nil)
|
||||
return;
|
||||
|
||||
if(l){
|
||||
a = malloc(sizeof(Additive));
|
||||
a->l = 1;
|
||||
a->v = dot->v;
|
||||
a->next = s->add;
|
||||
s->add = a;
|
||||
}else{
|
||||
if(v->val == 0 && v->rel == 0){
|
||||
/* add to request chain */
|
||||
*v = s->v;
|
||||
s->v = dot->v;
|
||||
}else{
|
||||
a = malloc(sizeof(Additive));
|
||||
a->l = 0;
|
||||
a->v = dot->v;
|
||||
a->next = s->add;
|
||||
s->add = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Token parsing */
|
||||
|
||||
/* parse a potential number, fall back to symbol */
|
||||
Token
|
||||
symnum(char *s)
|
||||
@ -387,6 +518,8 @@ token(void)
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Expressions */
|
||||
|
||||
/* This holds an expression AST */
|
||||
typedef struct Expr Expr;
|
||||
struct Expr
|
||||
@ -449,8 +582,8 @@ eval(Expr *e, Sym **ext, int pass)
|
||||
return v;
|
||||
|
||||
case 1:
|
||||
if(pass == 1 && (e->s->type & Def) == 0 ||
|
||||
pass == 2 && e->s->type & Extern){
|
||||
if(!pass2 && pass == 1 && (e->s->type & Def) == 0 ||
|
||||
pass2 && pass == 2 && e->s->type & Extern){
|
||||
unsixbit(e->s->name, name);
|
||||
err(1, "error: symbol %s must be defined", name);
|
||||
return (Value){ 0, 0 };
|
||||
@ -629,7 +762,7 @@ printexpr(Expr *e)
|
||||
}
|
||||
|
||||
Value
|
||||
expr(int pass)
|
||||
expr(int pass, Sym **s)
|
||||
{
|
||||
/* - 5
|
||||
* ^D ^O ^B ^F ^L 4
|
||||
@ -645,21 +778,27 @@ expr(int pass)
|
||||
Value v;
|
||||
char name[8];
|
||||
|
||||
printf("EXP LINE: %s %o\n", lp, peekt.type);
|
||||
/* printf("EXP LINE: %s %o\n", lp, peekt.type); */
|
||||
ext = nil;
|
||||
e = parseexpr(0);
|
||||
printf("EXPR: ");
|
||||
/* printf("EXPR: ");
|
||||
printexpr(e);
|
||||
printf("\n");
|
||||
printf("\n");*/
|
||||
v = eval(e, &ext, pass);
|
||||
if(s)
|
||||
*s = ext;
|
||||
/*
|
||||
if(ext){
|
||||
unsixbit(ext->name, name);
|
||||
printf("SAW EXTERNAL: %s\n", name);
|
||||
}
|
||||
*/
|
||||
freeexpr(e);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Statements */
|
||||
|
||||
/* split operands separated by ',' starting at lp; remove whitespace */
|
||||
void
|
||||
splitop(void)
|
||||
@ -710,6 +849,7 @@ void
|
||||
opline(word w, int io)
|
||||
{
|
||||
char *acp, *ep;
|
||||
Sym *ext;
|
||||
Value ac, x, y;
|
||||
Token t;
|
||||
int i;
|
||||
@ -738,7 +878,7 @@ opline(word w, int io)
|
||||
}
|
||||
|
||||
lp = acp;
|
||||
ac = expr(2);
|
||||
ac = expr(2, nil);
|
||||
|
||||
i = 0;
|
||||
lp = ep;
|
||||
@ -746,13 +886,15 @@ opline(word w, int io)
|
||||
lp++;
|
||||
i = 1;
|
||||
}
|
||||
y = expr(0);
|
||||
ext = nil;
|
||||
y = expr(0, &ext);
|
||||
updateext(ext, &y, 0);
|
||||
|
||||
x = (Value){ 0, 0 };
|
||||
t = token();
|
||||
if(t.type == '('){
|
||||
/* TODO: this is probably a statement */
|
||||
x = expr(2);
|
||||
x = expr(2, nil);
|
||||
t = token();
|
||||
if(t.type != ')')
|
||||
err(1, "error: ')' expected");
|
||||
@ -820,16 +962,22 @@ void
|
||||
xwd(void)
|
||||
{
|
||||
Value l, r;
|
||||
Sym *exl, *exr;
|
||||
|
||||
splitop();
|
||||
l = (Value){ 0, 0 };
|
||||
r = (Value){ 0, 0 };
|
||||
if(numops != 2)
|
||||
err(0, "warning: need two operands");
|
||||
else{
|
||||
exl = nil;
|
||||
exr = nil;
|
||||
lp = ops[0];
|
||||
l = expr(2);
|
||||
l = expr(0, &exl);
|
||||
lp = ops[1];
|
||||
r = expr(0);
|
||||
r = expr(0, &exr);
|
||||
updateext(exl, &l, 1);
|
||||
updateext(exr, &r, 0);
|
||||
}
|
||||
putv(fw(right(l.val), right(r.val)), (l.rel<<1) | r.rel);
|
||||
}
|
||||
@ -837,17 +985,15 @@ xwd(void)
|
||||
void
|
||||
title(void)
|
||||
{
|
||||
/* TODO */
|
||||
skipwhite();
|
||||
printf("TITLE: %s\n", lp);
|
||||
strncpy(progtitle, lp, MAXLINE);
|
||||
}
|
||||
|
||||
void
|
||||
subttl(void)
|
||||
{
|
||||
/* TODO */
|
||||
skipwhite();
|
||||
printf("SUBTTL: %s\n", lp);
|
||||
strncpy(progsubtitle, lp, MAXLINE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -857,7 +1003,7 @@ locOp(void)
|
||||
if(dot->v.rel) reldot = dot->v;
|
||||
else absdot = dot->v;
|
||||
if(*lp && *lp != ';'){
|
||||
dot->v = expr(1);
|
||||
dot->v = expr(1, nil);
|
||||
dot->v.val &= 0777777;
|
||||
dot->v.rel = 0;
|
||||
}else
|
||||
@ -871,7 +1017,7 @@ relocOp(void)
|
||||
if(dot->v.rel) reldot = dot->v;
|
||||
else absdot = dot->v;
|
||||
if(*lp && *lp != ';'){
|
||||
dot->v = expr(1);
|
||||
dot->v = expr(1, nil);
|
||||
dot->v.val &= 0777777;
|
||||
dot->v.rel = 1;
|
||||
}else
|
||||
@ -958,6 +1104,14 @@ sixbitOp(void)
|
||||
putv(w, 0);
|
||||
}
|
||||
|
||||
void
|
||||
endOp(void)
|
||||
{
|
||||
skipwhite();
|
||||
start = expr(2, nil);
|
||||
hadstart = 1;
|
||||
}
|
||||
|
||||
void
|
||||
radixOp(void)
|
||||
{
|
||||
@ -969,7 +1123,7 @@ radixOp(void)
|
||||
return;
|
||||
r = radix;
|
||||
radix = 10;
|
||||
v = expr(1);
|
||||
v = expr(1, nil);
|
||||
radix = r;
|
||||
if(v.val < 2 || v.val > 10)
|
||||
err(1, "error: invalid radix %d", v.val);
|
||||
@ -977,17 +1131,13 @@ radixOp(void)
|
||||
radix = v.val;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
statement(void)
|
||||
{
|
||||
Token t;
|
||||
Value val;
|
||||
int type;
|
||||
Sym *s;
|
||||
Sym *s, *ext;
|
||||
char name[8];
|
||||
|
||||
while(t = token(), t.type != Eol)
|
||||
@ -1017,7 +1167,7 @@ statement(void)
|
||||
err(1, "error: redefinition of %s", name);
|
||||
return;
|
||||
}
|
||||
s->type = type;
|
||||
s->type = (s->type&(Intern|Extern|Hide)) | type;
|
||||
s->v = dot->v;
|
||||
}
|
||||
}else if(*lp == '='){
|
||||
@ -1037,13 +1187,13 @@ statement(void)
|
||||
lp++;
|
||||
type |= Intern;
|
||||
}
|
||||
val = expr(1);
|
||||
val = expr(1, nil);
|
||||
if(!pass2){
|
||||
if(s->type & Label){
|
||||
err(1, "error: redefinition of %s", name);
|
||||
return;
|
||||
}
|
||||
s->type = type;
|
||||
s->type = (s->type&(Intern|Extern|Hide)) | type;
|
||||
s->v = val;
|
||||
}
|
||||
}else if(s->type == Operator){
|
||||
@ -1066,7 +1216,9 @@ statement(void)
|
||||
case Radix10: case Radix8: case Radix2:
|
||||
case Minus:
|
||||
peekt = t;
|
||||
val = expr(0);
|
||||
ext = nil;
|
||||
val = expr(0, &ext);
|
||||
updateext(ext, &val, 0);
|
||||
putv(val.val, val.rel);
|
||||
break;
|
||||
|
||||
@ -1092,6 +1244,9 @@ resetdot(void)
|
||||
absdot = (Value){ 0, 0 };
|
||||
reldot = (Value){ 0, 1 };
|
||||
dot->v = reldot;
|
||||
lastdot = dot->v;
|
||||
/* invalidate lastdot */
|
||||
lastdot.val = 0777777777777;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1122,13 +1277,16 @@ symcmp(const void *a, const void *b)
|
||||
}
|
||||
|
||||
void
|
||||
listsymtab(void)
|
||||
writesymtab(void)
|
||||
{
|
||||
hword l, r;
|
||||
char name[8];
|
||||
Sym *s;
|
||||
Sym *sortlist[MAXSYM];
|
||||
Additive *add;
|
||||
word rad;
|
||||
int i, nsym;
|
||||
int type;
|
||||
|
||||
nsym = 0;
|
||||
for(s = symtab; s < &symtab[MAXSYM]; s++){
|
||||
@ -1140,9 +1298,21 @@ listsymtab(void)
|
||||
qsort(sortlist, nsym, sizeof(Sym*), symcmp);
|
||||
|
||||
|
||||
startitem(Symbols);
|
||||
fprintf(lstfp, "\nSYMBOL TABLE\n\n");
|
||||
for(i = 0; i < nsym; i++){
|
||||
s = sortlist[i];
|
||||
|
||||
type = 0;
|
||||
if(s->type & Intern)
|
||||
type = SymGlobal;
|
||||
else if(s->type & Local)
|
||||
type = SymLocal;
|
||||
if(s->type & Hide)
|
||||
type |= 040;
|
||||
if(s->type & Extern)
|
||||
type = SymUndef;
|
||||
|
||||
unsixbit(s->name, name);
|
||||
l = left(s->v.val);
|
||||
r = right(s->v.val);
|
||||
@ -1158,10 +1328,23 @@ listsymtab(void)
|
||||
fprintf(lstfp, "INT");
|
||||
fprintf(lstfp, "\n");
|
||||
|
||||
rad = rad50(type, name);
|
||||
putword(rad, 0);
|
||||
putword(fw(0, right(s->v.val)), s->v.rel);
|
||||
|
||||
printf("%s %3o: %012lo %o\n", name, s->type, s->v.val, s->v.rel);
|
||||
for(add = s->add; add; add = add->next){
|
||||
printf(" %c %06o\n", "rl"[add->l], right(add->v.val));
|
||||
|
||||
putword(rad, 0);
|
||||
putword(fw(0400000 | (add->l ? 0200000 : 0), right(add->v.val)),
|
||||
add->v.rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic program flow */
|
||||
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
@ -1176,12 +1359,17 @@ usage(void)
|
||||
|
||||
void initsymtab(void);
|
||||
|
||||
char *outfile = "a.rel";
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'o':
|
||||
outfile = EARGF(usage());
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
@ -1195,7 +1383,7 @@ main(int argc, char *argv[])
|
||||
|
||||
initsymtab();
|
||||
|
||||
{
|
||||
if(0){
|
||||
Sym *s;
|
||||
s = getsym(sixbit("HELLO"));
|
||||
s->type = Local | Def;
|
||||
@ -1214,7 +1402,7 @@ main(int argc, char *argv[])
|
||||
s->v.val = 0;
|
||||
s->v.rel = 0;
|
||||
s = getsym(sixbit("QWERTY"));
|
||||
s->type = Label | Def;
|
||||
s->type = Label | Local | Def;
|
||||
s->v.val = 010;
|
||||
s->v.rel = 1;
|
||||
s = getsym(sixbit("QWERTYUIOP"));
|
||||
@ -1253,17 +1441,32 @@ main(int argc, char *argv[])
|
||||
panic("Error\n*****");
|
||||
|
||||
lstfp = mustopen("a.lst", "w");
|
||||
relfp = mustopen(outfile, "w");
|
||||
tmpfp = mustopen("a.tmp", "r");
|
||||
|
||||
resetdot();
|
||||
pass2 = 1;
|
||||
printf("\n PASS2\n\n");
|
||||
|
||||
startitem(Name);
|
||||
putword(rad50(0, progtitle), 0);
|
||||
|
||||
assemble();
|
||||
|
||||
listsymtab();
|
||||
writesymtab();
|
||||
|
||||
if(hadstart){
|
||||
startitem(Start);
|
||||
putword(right(start.val), start.rel);
|
||||
}
|
||||
|
||||
startitem(End);
|
||||
putword(right(relbreak), 1);
|
||||
putword(right(absbreak), 0);
|
||||
startitem(Nothing);
|
||||
|
||||
fclose(tmpfp);
|
||||
fclose(relfp);
|
||||
fclose(lstfp);
|
||||
|
||||
return 0;
|
||||
@ -1323,6 +1526,7 @@ Ps pslist[] = {
|
||||
{ "ASCIZ", asciz },
|
||||
{ "SIXBIT", sixbitOp },
|
||||
{ "RADIX", radixOp },
|
||||
{ "END", endOp },
|
||||
/*
|
||||
" '
|
||||
RADIX50 SQUOZE
|
||||
|
||||
256
tools/ld6.c
256
tools/ld6.c
@ -1,18 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include "pdp6common.h"
|
||||
#include "pdp6bin.h"
|
||||
#include "../args.h"
|
||||
|
||||
char *argv0;
|
||||
#define nil NULL
|
||||
|
||||
enum
|
||||
{
|
||||
MAXSYM = 1000
|
||||
};
|
||||
|
||||
typedef struct Add Add;
|
||||
struct Add
|
||||
{
|
||||
word name;
|
||||
int l;
|
||||
hword addr;
|
||||
Add *next;
|
||||
};
|
||||
|
||||
|
||||
char *argv0;
|
||||
FILE *in;
|
||||
hword itemsz;
|
||||
word mem[01000000];
|
||||
hword rel, loc;
|
||||
hword locmax, locmin;
|
||||
hword start;
|
||||
Add *addlist;
|
||||
int error;
|
||||
char **files;
|
||||
int nfiles;
|
||||
|
||||
FILE*
|
||||
mustopen(const char *name, const char *mode)
|
||||
{
|
||||
@ -24,16 +47,17 @@ mustopen(const char *name, const char *mode)
|
||||
return f;
|
||||
}
|
||||
|
||||
FILE *in;
|
||||
hword itemsz;
|
||||
|
||||
word mem[01000000];
|
||||
hword rel, loc;
|
||||
|
||||
int error;
|
||||
|
||||
char **files;
|
||||
int nfiles;
|
||||
void
|
||||
err(int n, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "error: ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
error |= n;
|
||||
}
|
||||
|
||||
/*
|
||||
* debugging helpers
|
||||
@ -131,6 +155,28 @@ resolvereq(hword p, hword hw)
|
||||
}while(next);
|
||||
}
|
||||
|
||||
/* Perform additive external fixup */
|
||||
void
|
||||
fixadd(void)
|
||||
{
|
||||
Add *a;
|
||||
word *s;
|
||||
char name[8];
|
||||
|
||||
for(a = addlist; a; a = a->next){
|
||||
s = findsym(a->name);
|
||||
if(s == nil){
|
||||
unrad50(a->name, name);
|
||||
fprintf(stderr, "Need symbol %s\n", name);
|
||||
continue;
|
||||
}
|
||||
if(a->l)
|
||||
mem[a->addr] += fw(right(s[1]), 0);
|
||||
else
|
||||
mem[a->addr] += fw(0, right(s[1]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert a symbol into the symbol table. Handle linking. */
|
||||
void
|
||||
loadsym(word *newsym)
|
||||
@ -139,8 +185,20 @@ loadsym(word *newsym)
|
||||
int type, newtype;
|
||||
char name[8];
|
||||
|
||||
sym = findsym(newsym[0]);
|
||||
newtype = (newsym[0]>>30)&074;
|
||||
if(newtype == SymUndef && left(newsym[1]) & 0400000){
|
||||
/* Additive fixup */
|
||||
Add *a;
|
||||
a = malloc(sizeof(Add));
|
||||
a->name = newsym[0];
|
||||
a->l = !!(left(newsym[1]) & 0200000);
|
||||
a->addr = right(newsym[1]);
|
||||
a->next = addlist;
|
||||
addlist = a;
|
||||
return;
|
||||
}
|
||||
|
||||
sym = findsym(newsym[0]);
|
||||
if(sym == NULL){
|
||||
/* Symbol not in table yet.
|
||||
* TODO: ignore locals? */
|
||||
@ -171,8 +229,7 @@ loadsym(word *newsym)
|
||||
if(newtype == type &&
|
||||
newsym[1] == sym[1])
|
||||
return;
|
||||
fprintf(stderr, "Error: multiple definitions: %s\n", name);
|
||||
error = 1;
|
||||
err(1, "multiple definitions: %s", name);
|
||||
}else if(newtype == SymUndef)
|
||||
/* just resolve request */
|
||||
resolvereq(right(newsym[1]), right(sym[1]));
|
||||
@ -203,44 +260,28 @@ checkundef(void)
|
||||
type = unrad50(symtab[p], name);
|
||||
if(type != SymUndef)
|
||||
continue;
|
||||
error = 1;
|
||||
printf(" Error: undefined: %s %012lo\n", name, symtab[p+1]);
|
||||
err(1, "undefined: %s %012lo", 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)
|
||||
readblock(int doreloc)
|
||||
{
|
||||
word reloc;
|
||||
hword i;
|
||||
hword l, r;
|
||||
int bits;
|
||||
|
||||
blocksz = 0;
|
||||
if(itemsz == 0)
|
||||
return;
|
||||
|
||||
reloc = getword(in);
|
||||
reloc = readw(in);
|
||||
i = 18;
|
||||
while(itemsz && i--){
|
||||
block[blocksz++] = getword(in);
|
||||
block[blocksz++] = readw(in);
|
||||
itemsz--;
|
||||
}
|
||||
|
||||
@ -248,20 +289,73 @@ readblock(int mode)
|
||||
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(doreloc){
|
||||
if(bits & 1)
|
||||
block[i] = (block[i] + rel) & 0777777777777;
|
||||
block[i] += fw(0, rel);
|
||||
if(bits & 2)
|
||||
block[i] += fw(rel, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
skipitem(void)
|
||||
{
|
||||
while(itemsz)
|
||||
readblock(0);
|
||||
}
|
||||
|
||||
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];
|
||||
if(loc < locmin) locmin = loc;
|
||||
if(loc > locmax) locmax = loc;
|
||||
loc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handlesym(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while(itemsz){
|
||||
readblock(1);
|
||||
i = 0;
|
||||
while(i < blocksz){
|
||||
loadsym(&block[i]);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handleend(void)
|
||||
{
|
||||
word abs;
|
||||
char name[8];
|
||||
|
||||
readblock(1);
|
||||
rel = block[0];
|
||||
/* not sure what to do with this... */
|
||||
abs = block[1];
|
||||
while(itemsz)
|
||||
readblock(0);
|
||||
}
|
||||
|
||||
void
|
||||
handlename(void)
|
||||
{
|
||||
@ -277,63 +371,38 @@ handlename(void)
|
||||
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];
|
||||
start = right(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);
|
||||
}
|
||||
|
||||
/* Saves in RIM format. Read with this:
|
||||
* LOC 20
|
||||
* CONO PTR,60
|
||||
* A: CONSO PTR,10
|
||||
* JRST .-1
|
||||
* DATAI PTR,B
|
||||
* CONSO PTR,10
|
||||
* JRST .-1
|
||||
* B: 0
|
||||
* JRST !
|
||||
*/
|
||||
void
|
||||
save(const char *filename)
|
||||
{
|
||||
FILE *out;
|
||||
hword i;
|
||||
out = mustopen(filename, "wb");
|
||||
for(i = locmin; i <= locmax; i++){
|
||||
writew(fw(0710440, i), out); /* DATAI PTR,i */
|
||||
writew(mem[i], out);
|
||||
}
|
||||
writew(fw(0254200, start), out); /* HALT start */
|
||||
writew(0, out);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
@ -356,7 +425,7 @@ main(int argc, char *argv[])
|
||||
handlesym,
|
||||
skipitem,
|
||||
skipitem,
|
||||
skipitem,
|
||||
handleend,
|
||||
handlename,
|
||||
handlestart,
|
||||
};
|
||||
@ -372,23 +441,32 @@ main(int argc, char *argv[])
|
||||
nfiles = argc;
|
||||
files = argv;
|
||||
|
||||
locmax = 0;
|
||||
locmin = 0777777;
|
||||
|
||||
for(i = 0; i < nfiles; i++){
|
||||
in = mustopen(files[i], "rb");
|
||||
while(w = getword(in), w != ~0){
|
||||
while(w = readw(in), w != ~0){
|
||||
type = left(w);
|
||||
itemsz = right(w);
|
||||
typesw[type]();
|
||||
}
|
||||
fclose(in);
|
||||
}
|
||||
fixadd();
|
||||
|
||||
// dumpsym();
|
||||
|
||||
checkundef();
|
||||
if(error)
|
||||
return 1;
|
||||
|
||||
printf("%06o %06o\n", locmin, locmax);
|
||||
|
||||
// disasmrange(findsym(rad50(0, "LINKSR"))[1],
|
||||
// findsym(rad50(0, "LINEP"))[1]);
|
||||
// disasmrange(0600+rel, 0603+rel);
|
||||
// disasmrange(0200+rel, 0212+rel);
|
||||
|
||||
save("a.dump");
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ enum SymType
|
||||
SymGlobal = 004,
|
||||
SymLocal = 010,
|
||||
SymBlock = 014,
|
||||
SymGlobalH = 044, /* hidden
|
||||
SymLocalH = 050, */
|
||||
SymGlobalH = 044, /* hidden */
|
||||
SymLocalH = 050, /* */
|
||||
SymUndef = 060,
|
||||
};
|
||||
|
||||
@ -11,6 +11,32 @@ hword right(word w) { return w & 0777777; }
|
||||
word negw(word w) { return (~w + 1) & 0777777777777; }
|
||||
int isneg(word w) { return !!(w & 0400000000); }
|
||||
|
||||
void
|
||||
writew(word w, FILE *fp)
|
||||
{
|
||||
int j;
|
||||
w &= 0777777777777;
|
||||
for(j = 5; j >= 0; j--)
|
||||
putc(0200 | (w>>j*6)&077, fp);
|
||||
}
|
||||
|
||||
word
|
||||
readw(FILE *fp)
|
||||
{
|
||||
int i, b;
|
||||
word w;
|
||||
w = 0;
|
||||
for(i = 0; i < 6; i++){
|
||||
cont:
|
||||
if(b = getc(fp), b == EOF)
|
||||
return ~0;
|
||||
if((b & 0200) == 0)
|
||||
goto cont;
|
||||
w = (w << 6) | (b & 077);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
/* map ascii to radix50/squoze, also map lower to upper case */
|
||||
char
|
||||
ascii2rad(char c)
|
||||
|
||||
@ -7,6 +7,8 @@ hword left(word w);
|
||||
hword right(word w);
|
||||
word negw(word w);
|
||||
int isneg(word w);
|
||||
void writew(word w, FILE *fp);
|
||||
word readw(FILE *fp);
|
||||
|
||||
char ascii2rad(char c);
|
||||
char rad2ascii(char c);
|
||||
|
||||
12
tools/ptdump.c
Normal file
12
tools/ptdump.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "pdp6common.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
word w;
|
||||
while(w = readw(stdin), w != ~0)
|
||||
printf("%012lo\n", w);
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user