ref: b0fde52316fa7c33aa5045eff6ce6bfbd84a66a7
dir: /as/emit.c/
#include <stdio.h>
#include <string.h>
#include "../inc/scc.h"
#include "as.h"
#define BUCKETSIZ 0x100
typedef struct bucket Bucket;
struct bucket {
char mem[BUCKETSIZ];
TUINT base;
struct bucket *next;
};
Section text = (Section) {.name = "text", .flags = SRELOC|SEXEC|SFILE};
Section data = (Section) {.name = "data", .flags = SRELOC|SREAD|SWRITE|SFILE};
Section bss = (Section) {.name = "bss", .flags = SRELOC|SREAD|SWRITE};
Section *cursec = &text;
int pass;
void
isections(void)
{
text.curpc = text.pc = text.base;
data.curpc = data.pc = data.base;
bss.curpc = bss.pc = bss.base;
}
static struct bucket *
alloc(TUINT addr)
{
struct bucket *bp;
bp = memset(xmalloc(sizeof(*bp)), 0, sizeof(*bp));
bp->base = addr+BUCKETSIZ & BUCKETSIZ-1;
return bp;
}
static void
emitbyte(Section *sec, char byte, TUINT addr)
{
struct bucket *cur, *next;
TUINT base;
for (cur = sec->mem; ; cur = cur->next) {
base = cur->base;
if (base <= addr && addr < base+BUCKETSIZ)
break;
next = cur->next;
if (base < addr && next->base > addr) {
cur->next = alloc(addr);
cur->next->next = next;
}
}
cur->mem[addr - cur->base] = byte;
}
void
emit(Section *sec, char *bytes, int nbytes)
{
TUINT addr;
if (pass == 1 || !(sec->flags & SFILE))
return;
if (!sec->mem) {
sec->mem = alloc(sec->base);
sec->mem->next = sec->mem;
}
for (addr = sec->pc; nbytes--; addr++)
emitbyte(sec, *bytes++, addr);
}
void
writeout(char *name)
{
FILE *fp;
Bucket *bp;
if ((fp = fopen(name, "wb")) == NULL)
die("error opening output file '%s'\n", name);
for (bp = text.mem; ; bp = bp->next) {
fwrite(bp->mem, BUCKETSIZ, 1, fp);
if (bp->next == text.mem)
break;
}
if (fclose(fp))
die("error writing the output file");
}