commit c04db5e82d82088e3cfc98c3c58622cc8241d94a
parent 6fa227852ba779950f62c092c1a5bb6d20216afb
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 23 Nov 2017 13:47:49 +0000
[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.
Diffstat:
M | as/as.h | | | 20 | +++++++++++++++++++- |
M | as/ins.c | | | 9 | +++++++-- |
M | as/myro.c | | | 255 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
3 files changed, 276 insertions(+), 8 deletions(-)
diff --git a/as/as.h b/as/as.h
@@ -49,6 +49,7 @@ enum common_args {
#define MAXSYM 63
+typedef struct reloc Reloc;
typedef struct ins Ins;
typedef struct op Op;
typedef struct section Section;
@@ -73,6 +74,15 @@ struct ins {
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 @@ struct node {
/* 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);
@@ -144,6 +153,15 @@ extern int match(Op *op, Node **args);
/* 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
*/
diff --git a/as/ins.c b/as/ins.c
@@ -32,8 +32,13 @@ def(Node **args, int siz)
{
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
diff --git 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, §);
+ }
+
+ 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;
+}