kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
260 wiersze
5.6 KiB
C
260 wiersze
5.6 KiB
C
#include "vasm.h"
|
|
|
|
#ifdef OUTIHEX
|
|
|
|
/* ihex formats */
|
|
#define I8HEX 0 /* supports 16-bit address space */
|
|
#define I16HEX 1 /* supports 20-bit address space */
|
|
#define I32HEX 2 /* supports 32-bit address space */
|
|
|
|
/* maximum address for I16HEX */
|
|
#define MEBIBYTE (1 << 20) - 1
|
|
|
|
/* ihex record types */
|
|
#define REC_DAT 0 /* data */
|
|
#define REC_EOF 1 /* end of file */
|
|
#define REC_ESA 2 /* extended segment address */
|
|
#define REC_SSA 3 /* start segment address */
|
|
#define REC_ELA 4 /* extended linear address */
|
|
#define REC_SLA 5 /* start linear address */
|
|
|
|
static char *copyright = "vasm Intel HEX output module 0.2 (c) 2020 Rida Dzhaafar";
|
|
|
|
static int ihex_fmt = I8HEX; /* default ihex format */
|
|
|
|
static uint8_t *buffer; /* output buffer for data records */
|
|
static uint8_t buffer_s = 32; /* maximum buffer size */
|
|
static uint8_t buffer_i = 0; /* current index in buffer */
|
|
|
|
static uint32_t addr = 0; /* current output address */
|
|
static uint16_t ext_addr = 0; /* last written extended segment/linear address */
|
|
|
|
static void write_newline(FILE *f) /* gbm 06'21 */
|
|
{
|
|
if (!asciiout)
|
|
fw8(f, '\r');
|
|
fw8(f, '\n');
|
|
}
|
|
|
|
static void write_eof_record(FILE *f)
|
|
{
|
|
fprintf(f, ":00000001FF");
|
|
write_newline(f);
|
|
}
|
|
|
|
static void write_extended_record(FILE *f)
|
|
{
|
|
uint8_t csum;
|
|
uint16_t ext;
|
|
uint8_t type;
|
|
|
|
if (ihex_fmt == I16HEX) {
|
|
ext = ext_addr << 4;
|
|
type = REC_ESA;
|
|
}
|
|
else if (ihex_fmt == I32HEX) {
|
|
ext = ext_addr;
|
|
type = REC_ELA;
|
|
}
|
|
|
|
csum = type + 2 + (ext >> 8) + ext;
|
|
csum = (~csum) + 1;
|
|
|
|
fprintf(f, ":020000%02X%04X%02X", type, ext, csum);
|
|
write_newline(f);
|
|
}
|
|
|
|
static void write_data_record(FILE *f)
|
|
{
|
|
uint8_t csum;
|
|
uint8_t i;
|
|
uint16_t ext;
|
|
uint32_t start;
|
|
|
|
/* pre-flight checks */
|
|
if (buffer_i == 0)
|
|
return;
|
|
if (ihex_fmt == I8HEX && addr > UINT16_MAX)
|
|
output_error(11, addr);
|
|
if (ihex_fmt == I16HEX && addr > MEBIBYTE)
|
|
output_error(11, addr);
|
|
|
|
start = addr - buffer_i;
|
|
ext = start >> 16;
|
|
start &= 0xFFFF;
|
|
/* set/reset extended address if needed */
|
|
if (ext != ext_addr) {
|
|
ext_addr = ext;
|
|
write_extended_record(f);
|
|
}
|
|
|
|
/* write data record */
|
|
fprintf(f, ":%02X%04X00", buffer_i, start);
|
|
csum = start;
|
|
csum += start >> 8;
|
|
csum += buffer_i;
|
|
for (i = 0; i < buffer_i; i++) {
|
|
csum += buffer[i];
|
|
fprintf(f, "%02X", buffer[i]);
|
|
}
|
|
csum = (~csum) + 1;
|
|
fprintf(f, "%02X", csum);
|
|
write_newline(f);
|
|
|
|
/* reset the buffer index */
|
|
buffer_i = 0;
|
|
}
|
|
|
|
static void buffer_data(FILE *f, uint8_t b)
|
|
{
|
|
buffer[buffer_i] = b;
|
|
buffer_i++;
|
|
addr++;
|
|
|
|
if (buffer_i == buffer_s)
|
|
write_data_record(f);
|
|
}
|
|
|
|
/* align the atom if necessary
|
|
adapted from output_srec.c */
|
|
static void align(FILE *f, section *sec, atom *a)
|
|
{
|
|
uint32_t align = balign(addr, a->align);
|
|
uint32_t i;
|
|
uint32_t len;
|
|
uint8_t *fill;
|
|
|
|
if (!align)
|
|
return;
|
|
|
|
if (a->type == SPACE && a->content.sb->space == 0) {
|
|
if (a->content.sb->maxalignbytes != 0 &&
|
|
align > a->content.sb->maxalignbytes)
|
|
return;
|
|
fill = a->content.sb->fill;
|
|
len = a->content.sb->size;
|
|
} else {
|
|
fill = sec->pad;
|
|
len = sec->padbytes;
|
|
}
|
|
|
|
while (align % len) {
|
|
buffer_data(f, 0);
|
|
align--;
|
|
}
|
|
|
|
while (align >= len) {
|
|
for(i = 0; i < len; i++) {
|
|
buffer_data(f, fill[i]);
|
|
align--;
|
|
}
|
|
}
|
|
|
|
while (len--) {
|
|
buffer_data(f, 0);
|
|
}
|
|
}
|
|
|
|
static void write_output(FILE *f, section *sec, symbol *sym)
|
|
{
|
|
uint32_t i, j;
|
|
atom *a;
|
|
section *s, *s2;
|
|
|
|
if (!sec)
|
|
return;
|
|
|
|
for (; sym; sym = sym->next)
|
|
if (sym->type == IMPORT)
|
|
output_error(6, sym->name); /* undefined symbol (sym->name) */
|
|
|
|
/* fail on overlapping sections
|
|
adapted from output_bin.c */
|
|
for (s = sec; s != NULL; s = s->next) {
|
|
for (s2 = s->next; s2; s2 = s2->next) {
|
|
if (((ULLTADDR(s2->org) >= ULLTADDR(s->org) &&
|
|
ULLTADDR(s2->org) < ULLTADDR(s->pc)) ||
|
|
(ULLTADDR(s2->pc) > ULLTADDR(s->org) &&
|
|
ULLTADDR(s2->pc) <= ULLTADDR(s->pc))))
|
|
output_error(0);
|
|
}
|
|
}
|
|
|
|
buffer = mymalloc(sizeof(uint8_t) * buffer_s);
|
|
|
|
for (s = sec; s; s = s->next) {
|
|
addr = ULLTADDR(s->org);
|
|
for (a = s->first; a; a = a->next) {
|
|
align(f, s, a);
|
|
if (a->type == DATA) {
|
|
for (i = 0; i < a->content.db->size; i++) {
|
|
buffer_data(f, a->content.db->data[i]);
|
|
}
|
|
} else if (a->type == SPACE) {
|
|
for (i = 0; i < a->content.sb->space; i++) {
|
|
for (j = 0; j < a->content.sb->size; j++) {
|
|
buffer_data(f, a->content.sb->fill[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* flush buffer before moving on to next section */
|
|
write_data_record(f);
|
|
}
|
|
|
|
write_eof_record(f);
|
|
myfree(buffer);
|
|
}
|
|
|
|
static int parse_args(char *arg)
|
|
{
|
|
uint8_t size;
|
|
|
|
if (!strcmp(arg, "-i8hex")) {
|
|
ihex_fmt = I8HEX;
|
|
return 1;
|
|
}
|
|
else if (!strcmp(arg, "-i16hex")) {
|
|
ihex_fmt = I16HEX;
|
|
return 1;
|
|
}
|
|
else if (!strcmp(arg, "-i32hex")) {
|
|
ihex_fmt = I32HEX;
|
|
return 1;
|
|
}
|
|
else if (!strncmp(arg, "-record-size=", 13)) {
|
|
size = atoi(arg + 13);
|
|
/* an IHEX record cannot be longer than FF bytes */
|
|
if (size < 1 || size > 255)
|
|
return 0;
|
|
buffer_s = size;
|
|
return 1;
|
|
}
|
|
else if (!strcmp(arg, "-crlf")) { /* gbm */
|
|
asciiout = 0;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int init_output_ihex(char **cp, void (**wo)(FILE *, section *, symbol *), int (**oa)(char *))
|
|
{
|
|
if (sizeof(utaddr) > sizeof(uint32_t) || bitsperbyte != 8) {
|
|
output_error(1, cpuname); /* output module doesn't support (cpuname) */
|
|
return 0;
|
|
}
|
|
|
|
*cp = copyright;
|
|
*wo = write_output;
|
|
*oa = parse_args;
|
|
asciiout=1;
|
|
return 1;
|
|
}
|
|
|
|
#else
|
|
int init_output_ihex(char **cp, void (**wo)(FILE *, section *, symbol *), int (**oa)(char *))
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|