X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=object.c;h=395526e0ff1259c18753d2268255ab941571634d;hp=205c0a0ebd3b1387896b6da68ad34c09a92fa287;hb=c59f7a33730dacf753e066a4002e2f749051a137;hpb=76299dcc588e5f5ba7270fd4bacc5872152f088e diff --git a/object.c b/object.c index 205c0a0..395526e 100644 --- a/object.c +++ b/object.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for all Atari computers // OBJECT.C - Writing Object Files -// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2019 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -9,11 +9,13 @@ #include "object.h" #include "6502.h" #include "direct.h" +#include "dsp56k.h" #include "error.h" #include "mark.h" #include "riscasm.h" #include "sect.h" #include "symbol.h" +#include "version.h" //#define DEBUG_ELF @@ -56,6 +58,10 @@ See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' - 6-15 Currently unused */ +// Internal function prototypes +static void WriteLOD(void); +static void WriteP56(void); + // // Add entry to symbol table (in ALCYON mode) @@ -100,7 +106,6 @@ uint8_t * AddSymEntry(register uint8_t * buf, SYM * sym, int globflag) } } - // // Construct and deposit flag word // @@ -309,14 +314,13 @@ uint32_t DepositELFSymbol(uint8_t * ptr, uint32_t name, uint32_t addr, uint32_t // int WriteObject(int fd) { - LONG t; // Scratch long LONG tds; // TEXT & DATA segment size int i; // Temporary int CHUNK * cp; // Chunk (for gather) uint8_t * buf; // Scratch area uint8_t * p; // Temporary ptr LONG trsize, drsize; // Size of relocations - long unused; // For supressing 'write' warnings + uint32_t unused; // For supressing 'write' warnings if (verb_flag) { @@ -352,6 +356,7 @@ int WriteObject(int fd) if (strtable == NULL) { + free(buf); error("cannot allocate string table memory (in BSD mode)"); return ERROR; } @@ -360,6 +365,8 @@ int WriteObject(int fd) // Build object file header chptr = buf; // Base of header (for D_foo macros) + ch_size = 0; + challoc = 0x800000; D_long(0x00000107); // Magic number D_long(sect[TEXT].sloc); // TEXT size D_long(sect[DATA].sloc); // DATA size @@ -422,49 +429,39 @@ int WriteObject(int fd) } else if (obj_format == ALCYON) { - uint32_t symbolmaxsize = 0; - if (verb_flag) { if (prg_flag) - { printf("TOS header : 28 bytes\n"); - printf("Total : %d bytes\n", 28 + sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc); - } - else - { - printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc); - } + + printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc + (prg_flag ? 28 : 0)); } - if (prg_flag != 1) - symbolmaxsize = sy_assign(NULL, NULL) * 28; // Assign index numbers to the symbols + // Assign index numbers to the symbols, get # of symbols (we assume + // that all symbols can potentially be extended, hence the x28) + uint32_t symbolMaxSize = sy_assign(NULL, NULL) * 28; // Alloc memory for header + text + data, symbol and relocation // information construction. - t = tds = sect[TEXT].sloc + sect[DATA].sloc; - - if (t < symbolmaxsize) - t = symbolmaxsize; - - // Is there any reason to do this this way??? - buf = malloc(t + HDRSIZE); - buf += HDRSIZE; + tds = sect[TEXT].sloc + sect[DATA].sloc; + buf = malloc(HDRSIZE + tds + symbolMaxSize); // Build object file header just before the text+data image - chptr = buf - HDRSIZE; // -> base of header + chptr = buf; // -> base of header + ch_size = 0; + challoc = HDRSIZE + tds + symbolMaxSize; D_word(0x601A); // 00 - magic number D_long(sect[TEXT].sloc); // 02 - TEXT size D_long(sect[DATA].sloc); // 06 - DATA size D_long(sect[BSS].sloc); // 0A - BSS size - D_long(0); // 0E - symbol table size (will be filled later if non zero) + D_long(0); // 0E - symbol table size (filled later) D_long(0); // 12 - stack size (unused) D_long(PRGFLAGS); // 16 - PRGFLAGS D_word(0); // 1A - relocation information exists // Construct text and data segments; fixup relocatable longs in .PRG // mode; finally write the header + text + data - p = buf; + p = buf + HDRSIZE; for(i=TEXT; i<=DATA; i++) { @@ -477,28 +474,27 @@ int WriteObject(int fd) // Do a first pass on the Alcyon image, if in PRG mode if (prg_flag) - MarkImage(buf, tds, sect[TEXT].sloc, 0); - - unused = write(fd, buf - HDRSIZE, tds + HDRSIZE); + MarkImage(buf + HDRSIZE, tds, sect[TEXT].sloc, 0); - // Construct and write symbol table - if (prg_flag != 1) + // Construct symbol table and update the header entry, if necessary + if (prg_flag > 1) { - sy_assign(buf, AddSymEntry); - unused = write(fd, buf, symsize); + // sy_assign with AddSymEntry updates symsize (stays 0 otherwise) + sy_assign(buf + HDRSIZE + tds, AddSymEntry); + chptr = buf + 0x0E; // Point to symbol table size entry + D_long(symsize); + + if (verb_flag) + printf("Symbol table: %d bytes\n", symsize); } + // Write out the header + text & data + symbol table (if any) + unused = write(fd, buf, HDRSIZE + tds + symsize); + // Construct and write relocation information; the size of it changes if - // we're writing a RELMODed executable. + // we're writing a RELMODed executable. N.B.: Destroys buffer! tds = MarkImage(buf, tds, sect[TEXT].sloc, 1); unused = write(fd, buf, tds); - - // If we generated a symbol table we need to update the placeholder value - // we wrote above in the header - lseek(fd, 0xE, 0); - symsize = BYTESWAP32(symsize); - unused = write(fd, &symsize, 4); - } else if (obj_format == ELF) { @@ -609,6 +605,8 @@ for(int j=0; jELF" Magic Number D_byte(0x01); // 04 - 32 vs 64 (1 = 32, 2 = 64) D_byte(0x02); // 05 - Endianness (1 = LE, 2 = BE) @@ -791,7 +789,174 @@ for(int j=0; j base of header + ch_size = 0; + challoc = 0x600000; + + if (obj_format == LOD) + WriteLOD(); + else + WriteP56(); + + // Write all the things |o/ + unused = write(fd, buf, chptr - buf); + + if (buf) + free(buf); + } return 0; } + +static void WriteLOD(void) +{ + D_printf("_START %s 0000 0000 0000 RMAC %01i.%01i.%01i\n\n", firstfname, MAJOR, MINOR, PATCH); + + for(DSP_ORG * l=&dsp_orgmap[0]; lend != l->start) + { + switch (l->memtype) + { + case ORG_P: D_printf("_DATA P %.4X\n", l->orgadr); break; + case ORG_X: D_printf("_DATA X %.4X\n", l->orgadr); break; + case ORG_Y: D_printf("_DATA Y %.4X\n", l->orgadr); break; + case ORG_L: D_printf("_DATA L %.4X\n", l->orgadr); break; + default: + error("Internal error: unknown DSP56001 org'd section"); + return; + } + + CHUNK * cp = l->chunk; + uint8_t * p_chunk = l->start; + uint8_t * p_chunk_end = p_chunk; + uint32_t j = 0; + + while (p_chunk_end != l->end) + { + if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr) + { + // If the end of the section is inside the current chunk, just dump everything and stop + p_chunk_end = l->end; + } + else + { + // If the end of the section is not inside the current chunk, just dump everything from the current chunk and move on to the next + p_chunk_end = cp->chptr + cp->ch_size; + } + + uint32_t count = (uint32_t)(p_chunk_end - p_chunk); + + for(uint32_t i=0; ichnext; // Advance chunk + + if (cp != NULL) + p_chunk = cp->chptr; // Set dump pointer to start of this chunk + } + + if ((j & 7) != 0) + D_printf("\n"); + } + } + + // Dump the symbol table into the buf + DumpLODSymbols(); + + D_printf("\n_END %.4X\n", dsp_orgmap[0].orgadr); +} + + +static void WriteP56(void) +{ + for(DSP_ORG * l=&dsp_orgmap[0]; lend == l->start) + continue; + + if ((l->memtype < ORG_P) || (l->memtype > ORG_L)) + { + error("Internal error: unknown DSP56001 org'd section"); + return; + } + + CHUNK * cp = l->chunk; + uint8_t * p_chunk = l->start; + uint8_t * p_chunk_end = p_chunk; + + // Memory type (P, X, Y or L) + D_dsp(l->memtype); + + // Chunk start address (in DSP words) + D_dsp(l->orgadr); + + // Chunk length (in DSP words) + // We'll fill this field after we write the chunk so we can calculate + // how long it is (so if the chunk is split into different CHUNKs we + // can deal with this during copy) + uint8_t * p_buf_len = chptr; + chptr += 3; + + // The chunk itself + uint32_t chunk_size = 0; + + while (p_chunk_end != l->end) + { + if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr) + { + // If the end of the section is inside the current chunk, just + // dump everything and stop + p_chunk_end = l->end; + } + else + { + // If the end of the section is not inside the current chunk, + // just dump everything from the current chunk and move on to + // the next + p_chunk_end = cp->chptr + cp->ch_size; + } + + uint32_t current_chunk_size = p_chunk_end - p_chunk; + chunk_size += current_chunk_size; + memcpy(chptr, p_chunk, current_chunk_size); + chptr += current_chunk_size; + + cp = cp->chnext; // Advance chunk + + if (cp != NULL) + p_chunk = cp->chptr; // Set dump pointer to start of this chunk + } + + // Now we can mark the chunk's length (DSP word size is 24-bits, so + // the byte count needs to be divided by 3) + SETBE24(p_buf_len, chunk_size / 3); + } +} +