diff options
Diffstat (limited to 'asm/assem.c')
| -rw-r--r-- | asm/assem.c | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/asm/assem.c b/asm/assem.c new file mode 100644 index 00000000..9b12c503 --- /dev/null +++ b/asm/assem.c @@ -0,0 +1,672 @@ +#include "asm.h" +#include "y.tab.h" + +typedef struct Exc Exc; +typedef struct Etab Etab; +typedef struct Ldts Ldts; +typedef struct Ldt Ldt; + +struct Ldts +{ + int n; + Ldt *ldt; + Ldts *next; +}; + +struct Ldt{ + int sign; + char *name; + Ldt *next; +}; + +struct Exc +{ + int n1, n2, n3, n4, n5, n6; + Etab *etab; + Exc *next; +}; + +struct Etab +{ + int n; + char *name; + Etab *next; +}; + +static int inldt; +static int nldts; +static Ldts *aldts; +static Ldts *curl; +static int nexcs; +static Exc* aexcs; +static Exc* cure; +static char *srcpath; + +static void ldtw(int); +static void ldte(int, char*); + +List* +newa(int i, int size) +{ + List *l; + Array *a; + + a = malloc(sizeof(Array)); + a->i = i; + a->size = size; + l = malloc(sizeof(List)); + l->u.a = a; + l->link = nil; + + return l; +} + +List* +newi(vlong v, List *l) +{ + List *n, *t; + + n = malloc(sizeof(List)); + if(l == nil) + l = n; + else { + for(t = l; t->link; t = t->link) + ; + t->link = n; + } + n->link = nil; + n->u.ival = v; + n->addr = -1; + + return l; +} + +List* +news(String *s, List *l) +{ + List *n; + + n = malloc(sizeof(List)); + n->link = l; + l = n; + n->u.str = s; + n->addr = -1; + return l; +} + +int +digit(char x) +{ + if(x >= 'A' && x <= 'F') + return x - 'A' + 10; + if(x >= 'a' && x <= 'f') + return x - 'a' + 10; + if(x >= '0' && x <= '9') + return x - '0'; + diag("bad hex value in pointers"); + return 0; +} + +void +heap(int id, int size, String *ptr) +{ + Desc *d, *f; + char *p; + int k, i; + + d = malloc(sizeof(Desc)); + d->id = id; + d->size = size; + size /= IBY2WD; + d->map = malloc(size); + d->np = 0; + if(dlist == nil) + dlist = d; + else { + for(f = dlist; f->link != nil; f = f->link) + ; + f->link = d; + } + d->link = nil; + dcount++; + + if(ptr == 0) + return; + if(--ptr->len & 1) { + diag("pointer descriptor has bad length"); + return; + } + + k = 0; + p = ptr->string; + for(i = 0; i < ptr->len; i += 2) { + d->map[k++] = (digit(p[0])<<4)|digit(p[1]); + if(k > size) { + diag("pointer descriptor too long"); + break; + } + p += 2; + } + d->np = k; +} + +void +conout(int val) +{ + if(val >= -64 && val <= 63) { + Bputc(bout, val & ~0x80); + return; + } + if(val >= -8192 && val <= 8191) { + Bputc(bout, ((val>>8) & ~0xC0) | 0x80); + Bputc(bout, val); + return; + } + if(val < 0 && ((val >> 29) & 0x7) != 7 + || val > 0 && (val >> 29) != 0) + diag("overflow in constant 0x%lux\n", val); + Bputc(bout, (val>>24) | 0xC0); + Bputc(bout, val>>16); + Bputc(bout, val>>8); + Bputc(bout, val); +} + +void +aout(Addr *a) +{ + if(a == nil) + return; + if(a->mode & AIND) + conout(a->off); + conout(a->val); +} + +void +lout(void) +{ + char *p; + Link *l; + + if(module == nil) + module = enter("main", 0); + + for(p = module->name; *p; p++) + Bputc(bout, *p); + Bputc(bout, '\0'); + + for(l = links; l; l = l->link) { + conout(l->addr); + conout(l->desc); + Bputc(bout, l->type>>24); + Bputc(bout, l->type>>16); + Bputc(bout, l->type>>8); + Bputc(bout, l->type); + for(p = l->name; *p; p++) + Bputc(bout, *p); + Bputc(bout, '\0'); + } +} + +void +ldtout(void) +{ + Ldts *ls; + Ldt *l; + char *p; + + conout(nldts); + for(ls = aldts; ls != nil; ls = ls->next){ + conout(ls->n); + for(l = ls->ldt; l != nil; l = l->next){ + Bputc(bout, l->sign>>24); + Bputc(bout, l->sign>>16); + Bputc(bout, l->sign>>8); + Bputc(bout, l->sign); + for(p = l->name; *p; p++) + Bputc(bout, *p); + Bputc(bout, '\0'); + } + } + conout(0); +} + +void +excout(void) +{ + Exc *e; + Etab *et; + char *p; + + if(nexcs == 0) + return; + conout(nexcs); + for(e = aexcs; e != nil; e = e->next){ + conout(e->n3); + conout(e->n1); + conout(e->n2); + conout(e->n4); + conout(e->n5|(e->n6<<16)); + for(et = e->etab; et != nil; et = et->next){ + if(et->name != nil){ + for(p = et->name; *p; p++) + Bputc(bout, *p); + Bputc(bout, '\0'); + } + conout(et->n); + } + } + conout(0); +} + +void +srcout(void) +{ + char *p; + + for(p = srcpath; *p; p++) + Bputc(bout, *p); + Bputc(bout, '\0'); +} + +void +assem(Inst *i) +{ + Desc *d; + Inst *f, *link; + int pc, n, hints, o; + + f = 0; + while(i) { + link = i->link; + i->link = f; + f = i; + i = link; + } + i = f; + + pc = 0; + for(f = i; f; f = f->link) { + f->pc = pc++; + if(f->sym != nil) + f->sym->value = f->pc; + } + + if(pcentry >= pc) + diag("entry pc out of range"); + if(dentry >= dcount) + diag("entry descriptor out of range"); + + conout(XMAGIC); + hints = 0; + if(mustcompile) + hints |= MUSTCOMPILE; + if(dontcompile) + hints |= DONTCOMPILE; + hints |= HASLDT; + if(nexcs > 0) + hints |= HASEXCEPT; + conout(hints); /* Runtime flags */ + conout(1024); /* default stack size */ + conout(pc); + conout(dseg); + conout(dcount); + conout(nlink); + conout(pcentry); + conout(dentry); + + for(f = i; f; f = f->link) { + if(f->dst && f->dst->sym) { + f->dst->mode = AIMM; + f->dst->val = f->dst->sym->value; + } + o = opcode(f); + if(o == IRAISE){ + f->src = f->dst; + f->dst = nil; + } + Bputc(bout, o); + n = 0; + if(f->src) + n |= SRC(f->src->mode); + else + n |= SRC(AXXX); + if(f->dst) + n |= DST(f->dst->mode); + else + n |= DST(AXXX); + if(f->reg) + n |= f->reg->mode; + else + n |= AXNON; + Bputc(bout, n); + aout(f->reg); + aout(f->src); + aout(f->dst); + + if(listing) + print("%4ld %i\n", f->pc, f); + } + + for(d = dlist; d; d = d->link) { + conout(d->id); + conout(d->size); + conout(d->np); + for(n = 0; n < d->np; n++) + Bputc(bout, d->map[n]); + } + + dout(); + lout(); + ldtout(); + excout(); + srcout(); +} + +void +data(int type, int addr, List *l) +{ + List *f; + + if(inldt){ + ldtw(l->u.ival); + return; + } + + l->type = type; + l->addr = addr; + + if(mdata == nil) + mdata = l; + else { + for(f = mdata; f->link != nil; f = f->link) + ; + f->link = l; + } +} + +void +ext(int addr, int type, String *s) +{ + int i; + char *p; + List *n; + + if(inldt){ + ldte(type, s->string); + return; + } + + data(DEFW, addr, newi(type, nil)); + + n = nil; + p = s->string; + for(i = 0; i < s->len; i++) + n = newi(*p++, n); + data(DEFB, addr+IBY2WD, n); + + if(addr+s->len > dseg) + diag("ext beyond mp"); +} + +void +mklink(int desc, int addr, int type, String *s) +{ + Link *l; + + for(l = links; l; l = l->link) + if(strcmp(l->name, s->string) == 0) + diag("%s already defined", s->string); + + nlink++; + l = malloc(sizeof(Link)); + l->desc = desc; + l->addr = addr; + l->type = type; + l->name = s->string; + l->link = nil; + + if(links == nil) + links = l; + else + linkt->link = l; + linkt = l; +} + +void +dout(void) +{ + int n, i; + List *l, *e; + + e = nil; + for(l = mdata; l; l = e) { + switch(l->type) { + case DEFB: + n = 1; + for(e = l->link; e && e->addr == -1; e = e->link) + n++; + if(n < DMAX) + Bputc(bout, DBYTE(DEFB, n)); + else { + Bputc(bout, DBYTE(DEFB, 0)); + conout(n); + } + conout(l->addr); + while(l != e) { + Bputc(bout, l->u.ival); + l = l->link; + } + break; + case DEFW: + n = 1; + for(e = l->link; e && e->addr == -1; e = e->link) + n++; + if(n < DMAX) + Bputc(bout, DBYTE(DEFW, n)); + else { + Bputc(bout, DBYTE(DEFW, 0)); + conout(n); + } + conout(l->addr); + while(l != e) { + n = (int)l->u.ival; + Bputc(bout, n>>24); + Bputc(bout, n>>16); + Bputc(bout, n>>8); + Bputc(bout, n); + l = l->link; + } + break; + case DEFL: + n = 1; + for(e = l->link; e && e->addr == -1; e = e->link) + n++; + if(n < DMAX) + Bputc(bout, DBYTE(DEFL, n)); + else { + Bputc(bout, DBYTE(DEFL, 0)); + conout(n); + } + conout(l->addr); + while(l != e) { + Bputc(bout, l->u.ival>>56); + Bputc(bout, l->u.ival>>48); + Bputc(bout, l->u.ival>>40); + Bputc(bout, l->u.ival>>32); + Bputc(bout, l->u.ival>>24); + Bputc(bout, l->u.ival>>16); + Bputc(bout, l->u.ival>>8); + Bputc(bout, l->u.ival); + l = l->link; + } + break; + case DEFF: + n = 1; + for(e = l->link; e && e->addr == -1; e = e->link) + n++; + if(n < DMAX) + Bputc(bout, DBYTE(DEFF, n)); + else { + Bputc(bout, DBYTE(DEFF, 0)); + conout(n); + } + conout(l->addr); + while(l != e) { + Bputc(bout, l->u.ival>>56); + Bputc(bout, l->u.ival>>48); + Bputc(bout, l->u.ival>>40); + Bputc(bout, l->u.ival>>32); + Bputc(bout, l->u.ival>>24); + Bputc(bout, l->u.ival>>16); + Bputc(bout, l->u.ival>>8); + Bputc(bout, l->u.ival); + l = l->link; + } + break; + case DEFS: + n = l->u.str->len-1; + if(n < DMAX && n != 0) + Bputc(bout, DBYTE(DEFS, n)); + else { + Bputc(bout, DBYTE(DEFS, 0)); + conout(n); + } + conout(l->addr); + for(i = 0; i < n; i++) + Bputc(bout, l->u.str->string[i]); + + e = l->link; + break; + case DEFA: + Bputc(bout, DBYTE(DEFA, 1)); + conout(l->addr); + Bputc(bout, l->u.a->i>>24); + Bputc(bout, l->u.a->i>>16); + Bputc(bout, l->u.a->i>>8); + Bputc(bout, l->u.a->i); + Bputc(bout, l->u.a->size>>24); + Bputc(bout, l->u.a->size>>16); + Bputc(bout, l->u.a->size>>8); + Bputc(bout, l->u.a->size); + e = l->link; + break; + case DIND: + Bputc(bout, DBYTE(DIND, 1)); + conout(l->addr); + Bputc(bout, 0); + Bputc(bout, 0); + Bputc(bout, 0); + Bputc(bout, 0); + e = l->link; + break; + case DAPOP: + Bputc(bout, DBYTE(DAPOP, 1)); + conout(0); + e = l->link; + break; + } + } + + Bputc(bout, DBYTE(DEFZ, 0)); +} + +void +ldts(int n) +{ + nldts = n; + inldt = 1; +} + +static void +ldtw(int n) +{ + Ldts *ls, *p; + + ls = malloc(sizeof(Ldts)); + ls->n = n; + ls->ldt = nil; + ls->next = nil; + if(aldts == nil) + aldts = ls; + else{ + for(p = aldts; p->next != nil; p = p->next) + ; + p->next = ls; + } + curl = ls; +} + +static void +ldte(int n, char *s) +{ + Ldt *l, *p; + + l = malloc(sizeof(Ldt)); + l->sign = n; + l->name = s; + l->next = nil; + if(curl->ldt == nil) + curl->ldt = l; + else{ + for(p = curl->ldt; p->next != nil; p = p->next) + ; + p->next = l; + } +} + +void +excs(int n) +{ + nexcs = n; +} + +void +exc(int n1, int n2, int n3, int n4, int n5, int n6) +{ + Exc *e, *es; + + e = malloc(sizeof(Exc)); + e->n1 = n1; + e->n2 = n2; + e->n3 = n3; + e->n4 = n4; + e->n5 = n5; + e->n6 = n6; + e->etab = nil; + e->next = nil; + if(aexcs == nil) + aexcs = e; + else{ + for(es = aexcs; es->next != nil; es = es->next) + ; + es->next = e; + } + cure = e; +} + +void +etab(String *s, int n) +{ + Etab *et, *ets; + + et = malloc(sizeof(Etab)); + et->n = n; + if(s != nil) + et->name = s->string; + else + et->name = nil; + et->next = nil; + if(cure->etab == nil) + cure->etab = et; + else{ + for(ets = cure->etab; ets->next != nil; ets = ets->next) + ; + ets->next = et; + } +} + +void +source(String *s) +{ + srcpath = s->string; +} |
