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, §); 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 }