165 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "mcg.h"
 | |
| #include <ctype.h>
 | |
| 
 | |
| #define IEEEFLOAT
 | |
| #define FL_MSL_AT_LOW_ADDRESS 1
 | |
| #define FL_MSW_AT_LOW_ADDRESS 1
 | |
| #define FL_MSB_AT_LOW_ADDRESS 1
 | |
| 
 | |
| #include "con_float"
 | |
| 
 | |
| 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));
 | |
| 
 | |
|     i = float_cst(data, size, (char*) buffer);
 | |
|     if ((i != 0) && (i != 2)) /* 2 == overflow */
 | |
|         fatal("cannot parse floating point constant %s sz %d", data, size);
 | |
| 
 | |
|     fprintf(outputfile, "\t!float %s sz %d\n", data, size);
 | |
|     fprintf(outputfile, "\t.data1 ");
 | |
|     writehex(buffer[0], 1);
 | |
|     for (i=1; i<size; i++)
 | |
|     {
 | |
|         fprintf(outputfile, ", ");
 | |
|         writehex(buffer[i], 1);
 | |
|     }
 | |
|     fprintf(outputfile, "\n");
 | |
| }
 | |
| 
 | |
| 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 : */
 |