summaryrefslogtreecommitdiff
path: root/asm/assem.c
diff options
context:
space:
mode:
Diffstat (limited to 'asm/assem.c')
-rw-r--r--asm/assem.c672
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;
+}