ack/mach/proto/mcg/data.c
David Given 642956fa2f mcg now uses dataf4 and dataf8 to emit floating point constants, and so doesn't
need flt_arith any more. (And also generates them correctly on little-endian
systems.) as now parses numbers properly, doesn't trash memory all over the
place, and can handle negative numbers.
2018-09-12 23:19:32 +02:00

147 lines
3.4 KiB
C

#include "mcg.h"
#include <ctype.h>
static struct symbol* pending;
void data_label(const char* label)
{
struct symbol* sym = symbol_get(label);
if (sym->is_defined)
fatal("label '%s' defined twice", sym->name);
if (pending)
fprintf(outputfile, "%s = %s\n",
platform_label(label), platform_label(pending->name));
else
{
pending = sym;
pending = symbol_get(label);
pending->is_defined = true;
}
}
static const char* section_to_str(int section)
{
switch (section)
{
case SECTION_ROM: return ".rom";
case SECTION_DATA: return ".data";
case SECTION_BSS: return ".bss";
case SECTION_TEXT: return ".text";
default: return "unknown";
}
}
static void emit_header(int desired_section)
{
if (pending)
{
if (pending->section == SECTION_UNKNOWN)
pending->section = desired_section;
else if (pending->section != desired_section)
fatal("label '%s' can't change sections", pending->name);
fprintf(outputfile, "\n.sect %s\n", section_to_str(pending->section));
fprintf(outputfile, "%s:\n", platform_label(pending->name));
pending = NULL;
}
}
static void writehex(arith data, int size)
{
if (data < 0)
fprintf(outputfile, "-0x%0*lx", size*2, -data);
else
fprintf(outputfile, "0x%0*lx", size*2, data);
}
void data_int(arith data, size_t size, bool is_ro)
{
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
assert((size == 1) || (size == 2) || (size == 4) || (size == 8));
fprintf(outputfile, "\t.data%d ", size);
writehex(data, size);
fprintf(outputfile, "\n");
}
void data_float(const char* data, size_t size, bool is_ro)
{
unsigned char buffer[8];
int i;
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
assert((size == 4) || (size == 8));
fprintf(outputfile, "\t.dataf%d %s\n", size, data);
}
static bool istext(c)
{
return isprint(c) && (c != '"');
}
void data_block(const uint8_t* data, size_t size, bool is_ro)
{
const uint8_t* start = data;
const uint8_t* end = data + size;
const uint8_t* p = data;
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
start = p = data;
while (p < end)
{
while ((p < end) && istext(*p))
p++;
if (start < p)
{
fprintf(outputfile, "\t.ascii \"");
while (start < p)
{
fprintf(outputfile, "%c", *start);
start++;
}
fprintf(outputfile, "\"\n");
}
while ((p < end) && !istext(*p))
p++;
if (start < p)
{
bool first = true;
fprintf(outputfile, "\t.data1 ");
while (start < p)
{
if (!first)
fprintf(outputfile, ", ");
writehex(*start, 1);
start++;
first = false;
}
fprintf(outputfile, "\n");
}
}
}
void data_offset(const char* label, arith offset, bool is_ro)
{
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
fprintf(outputfile, "\t.data%d %s+%lld\n",
EM_pointersize, platform_label(label), offset);
}
void data_bss(arith size, int init)
{
if (init != 0)
fatal("non-zero-initialised bss not supported");
emit_header(SECTION_BSS);
fprintf(outputfile, "\t.space %lld\n", size);
}
/* vim: set sw=4 ts=4 expandtab : */