shithub: scc

Download patch

ref: 91969afe96ea1d251bb1bf3f4afd58049350f890
parent: 03364b67869bdfc077933d481624896c87986bb9
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Nov 23 08:47:49 EST 2017

[as] Add first version of myro code generator

This is not a functional version of the code generator
but it can generate a file and it matches the draft
definition of the file.

--- a/as/as.h
+++ b/as/as.h
@@ -49,6 +49,7 @@
 
 #define MAXSYM 63
 
+typedef struct reloc Reloc;
 typedef struct ins Ins;
 typedef struct op Op;
 typedef struct section Section;
@@ -73,6 +74,15 @@
 	char *str;
 };
 
+struct reloc {
+	size_t offset;
+	Symbol *sym;
+	unsigned char flags;
+	unsigned char size;
+	unsigned char nbits;
+	unsigned char shift;
+};
+
 struct op {
 	unsigned char flags;
 	char size;
@@ -112,7 +122,6 @@
 
 /* symbol.c */
 extern void isections(void);
-extern void writeout(char *name);
 extern void emit(Section *sec, char *bytes, int nbytes);
 extern Section *section(char *name);
 extern Symbol *tmpsym(TUINT val);
@@ -143,6 +152,15 @@
 
 /* ins.c */
 extern char *tobytes(TUINT v, int n, int inc);
+
+/* format.c */
+extern void writeout(char *name);
+extern void reloc(Symbol *sym,
+                  unsigned flags,
+                  unsigned size,
+                  unsigned nbits,
+                  unsigned shift);
+
 
 /*
  * Definition of global variables
--- a/as/ins.c
+++ b/as/ins.c
@@ -32,8 +32,13 @@
 {
 	Node *np;
 
-	for ( ; np = *args; ++args)
-		emit(cursec, tobytes(np->sym->value, siz, endian), siz);
+	for ( ; np = *args; ++args) {
+		Symbol *sym = np->sym;
+
+		if (sym->flags & FUNDEF)
+			reloc(sym, 0, siz, siz * 8, 0);
+		emit(cursec, tobytes(sym->value, siz, endian), siz);
+	}
 }
 
 void
--- a/as/myro.c
+++ b/as/myro.c
@@ -1,25 +1,270 @@
 static char sccsid[] = "@(#) ./as/myro.c";
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include "../inc/scc.h"
 #include "as.h"
 
-void
-writeout(char *name)
+struct myrohdr {
+	unsigned long format;
+	unsigned long long entry;
+	unsigned long long strsize;
+	unsigned long long secsize;
+	unsigned long long symsize;
+	unsigned long long relsize;
+};
+
+struct myrosect {
+	unsigned long name;
+	unsigned short flags;
+	unsigned char fill;
+	unsigned char aligment;
+	unsigned long long offset;
+	unsigned long long len;
+};
+
+struct myrosym {
+	unsigned long name;
+	unsigned long type;
+	unsigned char section;
+	unsigned char flags;
+	unsigned long long offset;
+	unsigned long long len;
+};
+
+struct myrorel {
+	unsigned long id;
+	unsigned char flags;
+	unsigned char size;
+	unsigned char nbits;
+	unsigned char shift;
+	unsigned long long offset;
+};
+
+static Reloc *relocs;
+static size_t relcap, relsiz;
+
+static void
+writehdr(FILE *fp, struct myrohdr *hdr)
 {
-	FILE *fp;
+	unsigned char buf[sizeof(*hdr)];
+	size_t len;
+
+	len = lpack(buf, "lqqqqq",
+	            hdr->format,
+	            hdr->entry,
+	            hdr->strsize,
+	            hdr->secsize,
+	            hdr->symsize,
+	            hdr->relsize);
+	fwrite(buf, len, 1, fp);
+}
+
+static size_t
+writesec(FILE *fp, struct myrosect *sect)
+{
+	unsigned char buf[sizeof(*sect)];
+	size_t len;
+
+	len = lpack(buf, "lsccqq",
+	            sect->name,
+	            sect->flags,
+	            sect->fill,
+	            sect->aligment,
+	            sect->offset,
+	            sect->len);
+	fwrite(buf, len, 1, fp);
+
+	return len;
+}
+
+static size_t
+writestrings(FILE *fp)
+{
+	size_t off = 0;
+	size_t len;
+	Symbol *sym;
 	Section *sp;
+	String str;
 
-	if ((fp = fopen(name, "wb")) == NULL)
-		die("error opening output file '%s'\n", name);
+	fputs("z80-scc", fp);
+	off = 7;
 
+	for (sym = symlist; sym; sym = sym->next) {
+		str = sym->name;
+		len = strlen(str.buf) + 1;
+		fwrite(str.buf, len, 1, fp);
+		str.offset = off;
+		off += len;
+	}
+
 	for (sp = seclist; sp; sp = sp->next) {
+		str = sp->name;
+		len = strlen(str.buf) + 1;
+		fwrite(str.buf, len, 1, fp);
+		str.offset = off;
+		off += len;
+	}
+
+	return off;
+}
+
+static size_t
+writesections(FILE *fp)
+{
+	Section *sp;
+	size_t off = 0;
+	struct myrosect sect;
+
+	for (sp = seclist; sp; sp = sp->next) {
+		sect.name = sp->name.offset;
+		sect.flags = 0;
+		sect.fill = 0;
+		sect.aligment = 0;
+		sect.offset = off;
+		sect.len = 0;
+		off += writesec(fp, &sect);
+	}
+
+	return off;
+}
+
+static size_t
+writesym(FILE *fp, struct myrosym *sym)
+{
+	unsigned char buf[sizeof(*sym)];
+	size_t len;
+
+	len = lpack(buf, "llccqq",
+	            sym->name,
+	            sym->type,
+	            sym->section,
+	            sym->flags,
+	            sym->offset,
+	            sym->len);
+	fwrite(buf, len, 1, fp);
+
+	return len;
+}
+
+static size_t
+writesymbols(FILE *fp)
+{
+	Symbol *sym;
+	size_t off = 0;
+	struct myrosym symbol;
+
+	for (sym = symlist; sym; sym = sym->next) {
+		symbol.name = sym->name.offset;
+		symbol.type = -1;
+		symbol.section = -1;
+		symbol.flags = 0;
+		symbol.offset = off;
+		symbol.len = 0;
+		off += writesym(fp, &symbol);
+	}
+
+	return off;
+}
+
+static size_t
+writerel(FILE *fp, struct myrorel *rel)
+{
+	unsigned char buf[sizeof(*rel)];
+	size_t len;
+
+	len = lpack(buf, "lccccq",
+	            rel->id,
+	            rel->flags,
+	            rel->size,
+	            rel->nbits,
+	            rel->shift,
+	            rel->offset);
+	return len;
+}
+
+static size_t
+writerelocs(FILE *fp)
+{
+	Reloc *bp, *lim;
+	size_t off = 0;
+	struct myrorel reloc;
+
+	lim = &relocs[relsiz];
+	for (bp = relocs; bp < lim; ++bp) {
+		reloc.id = 0;
+		reloc.flags = bp->flags;
+		reloc.size = bp->size;
+		reloc.nbits = bp->nbits;
+		reloc.shift = bp->shift;
+		reloc.offset = bp->offset;
+		off += writerel(fp, &reloc);
+	}
+	return off;
+}
+
+static void
+writedata(FILE *fp)
+{
+	Section *sp;
+
+	for (sp = seclist; sp; sp = sp->next) {
 		if (!sp->mem)
 			continue;
 		fwrite(sp->mem, sp->max - sp->base, 1, fp);
 	}
+}
 
+void
+writeout(char *name)
+{
+	FILE *fp;
+	long hdrpos;
+	struct myrohdr hdr = {0};
+
+	if ((fp = fopen(name, "wb")) == NULL)
+		die("error opening output file '%s'\n", name);
+
+	fputs("uobj", fp);
+	hdrpos = ftell(fp);
+	writehdr(fp, &hdr);
+	hdr.strsize = writestrings(fp);
+	hdr.secsize = writesections(fp);
+	hdr.symsize = writesymbols(fp);
+	hdr.relsize = writerelocs(fp);
+	writedata(fp);
+
+	fseek(fp, hdrpos, SEEK_SET);
+	writehdr(fp, &hdr);
+
 	if (fclose(fp))
 		die("error writing the output file");
+}
+
+void
+reloc(Symbol *sym,
+      unsigned flags, unsigned size, unsigned nbits, unsigned shift)
+{
+	size_t tmp;
+	Reloc *p;
+
+	if (relcap == relsiz) {
+		tmp = ((relcap + 1) * 3) / 2;
+		if ((p = realloc(relocs, tmp * sizeof(Reloc))) == NULL) {
+			tmp = relcap + 1;
+			p = xrealloc(relocs, tmp * sizeof(Reloc));
+		}
+		relcap = tmp;
+		relocs = p;
+	}
+
+	p = &relocs[relsiz++];
+	p->sym = sym;
+	p->flags = flags;
+	p->size = size;
+	p->nbits = nbits;
+	p->shift = shift;
+	p->offset = cursec->pc - cursec->base;
 }