scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

myro.c (3282B)


      1 static char sccsid[] = "@(#) ./as/myro.c";
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "../inc/scc.h"
      8 #include "../inc/myro.h"
      9 #include "as.h"
     10 
     11 #define FORMAT "z80-scc"
     12 
     13 static Reloc *relocs;
     14 static size_t relcap, relsiz;
     15 
     16 static size_t
     17 writestrings(FILE *fp)
     18 {
     19 	size_t off = 0;
     20 	size_t len;
     21 	Symbol *sym;
     22 	Section *sp;
     23 	String *str;
     24 
     25 	fwrite(FORMAT, sizeof(FORMAT), 1, fp);
     26 	off = sizeof(FORMAT);
     27 
     28 	for (sym = symlist; sym; sym = sym->next) {
     29 		if ((sym->flags & TMASK) == TREG)
     30 			continue;
     31 		str = &sym->name;
     32 		len = strlen(str->buf) + 1;
     33 		fwrite(str->buf, len, 1, fp);
     34 		str->offset = off;
     35 		off += len;
     36 	}
     37 
     38 	for (sp = seclist; sp; sp = sp->next) {
     39 		str = &sp->name;
     40 		len = strlen(str->buf) + 1;
     41 		fwrite(str->buf, len, 1, fp);
     42 		str->offset = off;
     43 		off += len;
     44 	}
     45 
     46 	return off;
     47 }
     48 
     49 static unsigned
     50 getsecflags(Section *sp)
     51 {
     52 	unsigned flags = MYROSEC_LOAD;
     53 
     54 	if (sp->flags & SREAD)
     55 		flags |= MYROSEC_READ;
     56 	if (sp->flags & SWRITE)
     57 		flags |= MYROSEC_WRITE;
     58 	if (sp->flags & SFILE)
     59 		flags |= MYROSEC_FILE;
     60 	return flags;
     61 }
     62 
     63 static size_t
     64 writesections(FILE *fp)
     65 {
     66 	Section *sp;
     67 	size_t off = 0;
     68 	struct myrosect sect;
     69 
     70 	for (sp = seclist; sp; sp = sp->next) {
     71 		sect.name = sp->name.offset;
     72 		sect.flags = getsecflags(sp);
     73 		sect.fill = sp->fill;
     74 		sect.aligment = sp->aligment;
     75 		sect.offset = off;
     76 		sect.len = sp->max - sp->base;
     77 		off += wrmyrosec(fp, &sect);
     78 	}
     79 
     80 	return off;
     81 }
     82 
     83 static size_t
     84 writesymbols(FILE *fp)
     85 {
     86 	Symbol *sym;
     87 	size_t off = 0;
     88 	struct myrosym symbol;
     89 
     90 	for (sym = symlist; sym; sym = sym->next) {
     91 		if ((sym->flags & TMASK) == TREG)
     92 			continue;
     93 		symbol.name = sym->name.offset;
     94 		symbol.type = -1;
     95 		symbol.section = -1;
     96 		symbol.flags = 0;
     97 		symbol.offset = off;
     98 		symbol.len = 0;
     99 		off += wrmyrosym(fp, &symbol);
    100 	}
    101 
    102 	return off;
    103 }
    104 
    105 static size_t
    106 writerelocs(FILE *fp)
    107 {
    108 	Reloc *bp, *lim;
    109 	size_t off = 0;
    110 	struct myrorel reloc;
    111 
    112 	lim = &relocs[relsiz];
    113 	for (bp = relocs; bp < lim; ++bp) {
    114 		reloc.id = 0;
    115 		reloc.flags = bp->flags;
    116 		reloc.size = bp->size;
    117 		reloc.nbits = bp->nbits;
    118 		reloc.shift = bp->shift;
    119 		reloc.offset = bp->offset;
    120 		off += wrmyrorel(fp, &reloc);
    121 	}
    122 	return off;
    123 }
    124 
    125 static void
    126 writedata(FILE *fp)
    127 {
    128 	Section *sp;
    129 
    130 	for (sp = seclist; sp; sp = sp->next) {
    131 		if (!sp->mem)
    132 			continue;
    133 		fwrite(sp->mem, sp->max - sp->base, 1, fp);
    134 	}
    135 }
    136 
    137 void
    138 writeout(char *name)
    139 {
    140 	FILE *fp;
    141 	struct myrohdr hdr = { .magic = MYROMAGIC };
    142 
    143 	if ((fp = fopen(name, "wb")) == NULL)
    144 		die("error opening output file '%s'\n", name);
    145 
    146 	wrmyrohdr(fp, &hdr);
    147 	hdr.strsize = writestrings(fp);
    148 	hdr.secsize = writesections(fp);
    149 	hdr.symsize = writesymbols(fp);
    150 	hdr.relsize = writerelocs(fp);
    151 	writedata(fp);
    152 
    153 	fseek(fp, 0, SEEK_SET);
    154 	wrmyrohdr(fp, &hdr);
    155 
    156 	if (fclose(fp))
    157 		die("error writing the output file");
    158 }
    159 
    160 void
    161 reloc(Symbol *sym,
    162       unsigned flags, unsigned size, unsigned nbits, unsigned shift)
    163 {
    164 	size_t tmp;
    165 	Reloc *p;
    166 
    167 	if (relcap == relsiz) {
    168 		tmp = ((relcap + 1) * 3) / 2;
    169 		if ((p = realloc(relocs, tmp * sizeof(Reloc))) == NULL) {
    170 			tmp = relcap + 1;
    171 			p = xrealloc(relocs, tmp * sizeof(Reloc));
    172 		}
    173 		relcap = tmp;
    174 		relocs = p;
    175 	}
    176 
    177 	p = &relocs[relsiz++];
    178 	p->sym = sym;
    179 	p->flags = flags;
    180 	p->size = size;
    181 	p->nbits = nbits;
    182 	p->shift = shift;
    183 	p->offset = cursec->pc - cursec->base;
    184 }