From f09ac9eb902ce71e933dbb73163dd6c7bfa305b2 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 29 Jan 2017 23:26:24 +0100 Subject: [PATCH] work on assembler and linker --- tools/as6.c | 454 ++++++++++++++++++++++++++++++++++----------- tools/ld6.c | 107 ++++++++++- tools/pdp6common.c | 10 +- 3 files changed, 456 insertions(+), 115 deletions(-) diff --git a/tools/as6.c b/tools/as6.c index 99e2fe4..2167012 100644 --- a/tools/as6.c +++ b/tools/as6.c @@ -8,8 +8,7 @@ #include "pdp6bin.h" #include "args.h" -// TODO: "ABC" -// A,,B +// TODO: A,,B #define nil NULL @@ -138,8 +137,8 @@ int ctab[] = { Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, Unused, - Ignore, Exclam, Unused, Unused, Letter, Letter, Amper, Unused, - '(', ')', Star, Plus, Unused, Minus, Letter, Slash, + Ignore, Exclam, '"', Unused, Letter, Letter, Amper, '\'', + '(', ')', Star, Plus, ',', Minus, Letter, Slash, Digit, Digit, Digit, Digit, Digit, Digit, Digit, Digit, Digit, Digit, Unused, ';', '<', Unused, '>', Unused, @@ -202,6 +201,8 @@ void statement(void); void err(int n, char *fmt, ...) { + if(n == 0 && pass2) + return; va_list ap; va_start(ap, fmt); fprintf(stderr, "%s:%d: ", filename, lineno); @@ -652,6 +653,30 @@ symnum(void) return t; } +word +character(char delim, int sz) +{ + int mask; + word w; + char c; + + w = 0; + mask = (1<v = (Value){ 0, 0 }; return e; @@ -931,8 +969,7 @@ parseexpr(int i) e2->r = parseexpr(i+1); e = e2; } - if(t.type != Eol) - peekt = t; + peekt = t; return e; } @@ -1025,13 +1062,62 @@ splitop(void) nparn++; else if(*lp == ')') nparn--; + lp--; + }else if(*lp == '['){ + /* same as above */ + if(*ops[numops-1] == '\0') + ops[numops-1] = lp; + lp++; + nparn = 1; + for(; *lp && *lp != ';' && nparn != 0; lp++) + if(*lp == '[') + nparn++; + else if(*lp == ']') + nparn--; + lp--; }else{ if(*ops[numops-1] == '\0') ops[numops-1] = lp; } } *lp = '\0'; +} +/* parse an effective address of the form @Y(X) */ +Value +ea(void) +{ + word w; + Token t; + Sym *ext; + Value x, y; + + w = 0; + if(*lp == '@'){ + lp++; + w = 0000020000000; + } + ext = nil; + y = expr(0, &ext); + updateext(ext, &y, 0); + if(left(y.val)) + err(0, "warning: address truncated"); + w |= right(y.val); + + t = token(); + if(t.type == '('){ + /* TODO: this is probably a statement */ + x = expr(2, nil); + if(t = token(), t.type != ')'){ + err(1, "error: ')' expected"); + peekt = t; + } + if(x.rel) + err(0, "warning: index relocation ignored"); + w |= fw(right(x.val) & 017, left(x.val)); + }else + peekt = t; + return (Value){ w, y.rel }; } /* Primary and IO instruction statement */ @@ -1061,24 +1147,31 @@ opline(word w, int io) ep = ops[0]; break; default: - err(0, "warning: too many operands"); + err(0, "warning: too many operands: %d", numops); case 2: acp = ops[0]; ep = ops[1]; } lp = acp; + peekt.type = Unused; ac = expr(2, nil); i = 0; lp = ep; + peekt.type = Unused; if(*lp == '@'){ lp++; i = 1; } - ext = nil; - y = expr(0, &ext); - updateext(ext, &y, 0); + t = token(); + peekt = t; + if(peekt.type != '('){ + ext = nil; + y = expr(0, &ext); + updateext(ext, &y, 0); + }else + y = (Value){ 0, 0 }; x = (Value){ 0, 0 }; t = token(); @@ -1115,7 +1208,7 @@ opline(word w, int io) */ void -internal(void) +internOp(void) { Sym *s; int i; @@ -1132,7 +1225,7 @@ internal(void) } void -external(void) +externOp(void) { Sym *s; int i; @@ -1148,30 +1241,6 @@ external(void) } } -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(0, &exl); - lp = ops[1]; - 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); -} - void title(void) { @@ -1187,31 +1256,210 @@ subttl(void) } void -locOp(void) +radixOp(void) { + int r; + Value v; + skipwhite(); - if(dot->v.rel) reldot = dot->v; - else absdot = dot->v; - if(*lp && *lp != ';'){ - dot->v = expr(1, nil); - dot->v.val &= 0777777; - dot->v.rel = 0; - }else - dot->v = absdot; + if(*lp == '\0' || *lp == ';') + return; + r = radix; + radix = 10; + v = expr(1, nil); + radix = r; + if(v.val < 2 || v.val > 10) + err(1, "error: invalid radix %d", v.val); + else + radix = v.val; } void -relocOp(void) +endOp(void) { skipwhite(); - if(dot->v.rel) reldot = dot->v; - else absdot = dot->v; - if(*lp && *lp != ';'){ - dot->v = expr(1, nil); - dot->v.val &= 0777777; - dot->v.rel = 1; + start = expr(2, nil); + hadstart = 1; +} + +void +litOp(void) +{ + Litword *l, *next; + if(litlist) + littabs[nlit] = dot->v; + for(l = litlist; l; l = next){ + next = l->next; +// printf("L: %012lo %d\n", l->v.val, l->v.rel); + putv(l->v.val, l->v.rel); + free(l); + } + if(litlist) + nlit++; + litlist = nil; +} + +void +expOp(void) +{ + Value v; + Token t; + Sym *ext; + + do{ + ext = nil; + v = expr(0, &ext); + updateext(ext, &v, 0); + putv(v.val, v.rel); + }while(t = token(), t.type == ','); +} + +void +decOp(void) +{ + int r; + r = radix; + radix = 10; + expOp(); + radix = r; +} + +void +octOp(void) +{ + int r; + r = radix; + radix = 8; + expOp(); + radix = r; +} + +void +byteOp(void) +{ + Token t; + word b, w; + int sz; + int mask; + int r; + int pos; + + w = 0; + pos = 36; + sz = 6; + mask = 077; + for(;;){ + /* byte size change */ + if(t = token(), t.type == '('){ + r = radix; + radix = 10; + sz = expr(0, nil).val; + if(t = token(), t.type != ')'){ + err(1, "error: ')' expected"); + peekt = t; + } + radix = r; + mask = (1<v = reldot; + err(0, "warning: right operand missing"); + + putv(fw(right(l.val), right(r.val)), (l.rel<<1) | r.rel); +} + +void +iowd(void) +{ + Token t; + Value l, r; + Sym *exl, *exr; + + exl = nil; + exr = nil; + l = (Value){ 0, 0 }; + r = (Value){ 0, 0 }; + + l = expr(2, &exl); + if(t = token(), t.type == ','){ + r = expr(0, &exr); + updateext(exr, &r, 0); + }else + err(0, "warning: right operand missing"); + + putv(fw(right(-l.val), right(r.val-1)), (l.rel<<1) | r.rel); +} + +void +pointOp(void) +{ + Value v; + Token t; + word sz, pos; + int r; + + peekt.type = Unused; + + r = radix; + radix = 10; + sz = expr(2, nil).val & 077; + radix = r; + + if(t = token(), t.type != ','){ + peekt = t; + err(2, "error: ',' expected"); + } + + v = ea(); + + pos = 044; + if(t = token(), t.type == ','){ + r = radix; + radix = 10; + pos = expr(2, nil).val & 077; + radix = r; + }else + peekt = t; + + v.val |= sz<<24 | pos<<30; + putv(v.val, v.rel); } int asciiz; @@ -1308,25 +1556,6 @@ sixbitOp(void) putv(w, 0); } -void -radixOp(void) -{ - int r; - Value v; - - skipwhite(); - if(*lp == '\0' || *lp == ';') - return; - r = radix; - radix = 10; - v = expr(1, nil); - radix = r; - if(v.val < 2 || v.val > 10) - err(1, "error: invalid radix %d", v.val); - else - radix = v.val; -} - void blockOp(void) { @@ -1340,28 +1569,31 @@ blockOp(void) } void -endOp(void) +locOp(void) { skipwhite(); - start = expr(2, nil); - hadstart = 1; + if(dot->v.rel) reldot = dot->v; + else absdot = dot->v; + if(*lp && *lp != ';'){ + dot->v = expr(1, nil); + dot->v.val &= 0777777; + dot->v.rel = 0; + }else + dot->v = absdot; } void -litOp(void) +relocOp(void) { - Litword *l, *next; - if(litlist) - littabs[nlit] = dot->v; - for(l = litlist; l; l = next){ - next = l->next; - printf("L: %012lo %d\n", l->v.val, l->v.rel); - putv(l->v.val, l->v.rel); - free(l); - } - if(litlist) - nlit++; - litlist = nil; + skipwhite(); + if(dot->v.rel) reldot = dot->v; + else absdot = dot->v; + if(*lp && *lp != ';'){ + dot->v = expr(1, nil); + dot->v.val &= 0777777; + dot->v.rel = 1; + }else + dot->v = reldot; } void @@ -1440,15 +1672,18 @@ statement(void) }else if(s->type == Pseudo){ s->f(); return; - }else - goto exp; + }else{ + err(1, "error: unknown operator %s", name); + return; + } break; - exp: + case ',': + return; + case Word: case Radix10: case Radix8: case Radix2: case Minus: - case '[': peekt = t; ext = nil; val = expr(0, &ext); @@ -1744,29 +1979,32 @@ initsymtab(void) } Ps pslist[] = { - { "INTERNAL", internal }, - { "EXTERNAL", external }, - { "XWD", xwd }, + { "INTERN", internOp }, + { "EXTERN", externOp }, { "TITLE", title }, { "SUBTTL", subttl }, - { "LOC", locOp }, - { "RELOC", relocOp }, + { "RADIX", radixOp }, + { "END", endOp }, + { "LIT", litOp }, + + { "EXP", expOp }, + { "DEC", decOp }, + { "OCT", octOp }, + { "BYTE", byteOp }, + { "XWD", xwd }, + { "IOWD", iowd }, + { "POINT", pointOp }, + { "ASCII", ascii }, { "ASCIZ", asciz }, { "SIXBIT", sixbitOp }, - { "RADIX", radixOp }, { "BLOCK", blockOp }, - { "END", endOp }, - { "LIT", litOp }, + + { "LOC", locOp }, + { "RELOC", relocOp }, + /* - " ' RADIX50 SQUOZE - DEC - OCT - EXP - BYTE - POINT - IOWD INTEGER ARRAY ENTRY diff --git a/tools/ld6.c b/tools/ld6.c index 9ce5272..d989b66 100644 --- a/tools/ld6.c +++ b/tools/ld6.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -23,6 +24,12 @@ struct Add Add *next; }; +enum +{ + RIM = 0, + RIM10, + SAV, +}; char *argv0; FILE *in; @@ -35,6 +42,7 @@ Add *addlist; int error; char **files; int nfiles; +int fmt = RIM; FILE* mustopen(const char *name, const char *mode) @@ -406,10 +414,75 @@ saverim(const char *filename) fclose(out); } +/* Saves in RIM10 format. Only one block is written. + * IOWD count,origin + * word + * ... + * word + * checksum + * ... + * JRST start + */ +void +saverim10(const char *filename) +{ + FILE *out; + hword i; + word w; + word checksum; + + out = mustopen(filename, "wb"); + checksum = 0; + + w = fw(-(locmax+1-locmin), locmin-1); + writew(w, out); /* IOWD count,origin */ + checksum += w; + for(i = locmin; i <= locmax; i++){ + writew(mem[i], out); + checksum += mem[i]; + } + writew(-checksum, out); + + writew(fw(0254000, start), out); /* JRST start */ + fclose(out); +} + +void +writeww(word w, FILE *fp) +{ + unsigned char c; + putc((w >> 29) & 0177, fp); + putc((w >> 22) & 0177, fp); + putc((w >> 15) & 0177, fp); + putc((w >> 8) & 0177, fp); + putc((w>>1) & 0177 | (w & 1) << 7, fp); +} + +/* Saves in SAV format. Only one block is saved. + * IOWD count,origin + * word + * ... + * word + * ... + * JRST start + */ +void +savesav(const char *filename) +{ + FILE *out; + hword i; + out = mustopen(filename, "wb"); + writeww(fw(-(locmax+1-locmin), locmin-1), out); /* IOWD count,origin */ + for(i = locmin; i <= locmax; i++) + writeww(mem[i], out); + writeww(fw(0254000, start), out); /* JRST start */ + fclose(out); +} + void usage(void) { - fprintf(stderr, "usage: %s\n", argv0); + fprintf(stderr, "usage: %s [-r relbase] [-f fmt] [-o outfile] input1 input2 ...\n", argv0); exit(1); } @@ -420,6 +493,7 @@ main(int argc, char *argv[]) hword type; int i; char *outfile; + char *fmtstr; void (*typesw[8])(void) = { skipitem, handlecode, @@ -431,19 +505,41 @@ main(int argc, char *argv[]) handlestart, }; - outfile = "a.rim"; + outfile = nil; + rel = 0100; ARGBEGIN{ case 'r': rel = strtol(EARGF(usage()), NULL, 8); break; + + case 'f': + fmtstr = EARGF(usage()); + if(strcmp(fmtstr, "rim") == 0) + fmt = RIM; + if(strcmp(fmtstr, "rim10") == 0) + fmt = RIM10; + else if(strcmp(fmtstr, "sav") == 0) + fmt = SAV; + else + usage(); + break; + case 'o': outfile = EARGF(usage()); break; + default: usage(); }ARGEND; + if(outfile == nil){ + if(fmt == RIM || fmt == RIM10) + outfile = "a.rim"; + else if(fmt == SAV) + outfile = "a.sav"; + } + nfiles = argc; files = argv; @@ -474,7 +570,12 @@ main(int argc, char *argv[]) // disasmrange(0600+rel, 0603+rel); // disasmrange(0200+rel, 0212+rel); - saverim(outfile); + if(fmt == RIM) + saverim(outfile); + else if(fmt == RIM10) + saverim10(outfile); + else if(fmt == SAV) + savesav(outfile); return 0; } diff --git a/tools/pdp6common.c b/tools/pdp6common.c index 5c14e62..9c274c2 100644 --- a/tools/pdp6common.c +++ b/tools/pdp6common.c @@ -4,7 +4,7 @@ #include #include "pdp6common.h" -word fw(hword l, hword r) { return ((word)l << 18) | (word)r; } +word fw(hword l, hword r) { return ((word)right(l) << 18) | (word)right(r); } word point(word pos, word sz, hword p) { return (pos<<30)|(sz<<24)|p; } hword left(word w) { return (w >> 18) & 0777777; } hword right(word w) { return w & 0777777; } @@ -204,6 +204,7 @@ ascii2sixbit(char c) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 000, 001, 002, 003, 004, 005, 006, 007, 010, 011, 012, 013, 014, 015, 016, 017, 020, 021, 022, 023, 024, 025, 026, 027, @@ -211,11 +212,12 @@ ascii2sixbit(char c) 040, 041, 042, 043, 044, 045, 046, 047, 050, 051, 052, 053, 054, 055, 056, 057, 060, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 072, -1, -1, -1, -1, -1, - -1, 041, 042, 043, 044, 045, 046, 047, + 070, 071, 072, 073, 074, 075, 076, 077, + + 040, 041, 042, 043, 044, 045, 046, 047, 050, 051, 052, 053, 054, 055, 056, 057, 060, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 072, -1, -1, -1, -1, -1, + 070, 071, 072, 073, 074, 075, 076, 077, }; return tab[c&0177]; }