// OBJECT.C - Writing Object Files
// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
//
#include "object.h"
#include "mark.h"
#include "error.h"
#include "riscasm.h"
+#include "mark.h"
+
+/*
+ * Imports
+ */
+extern int obj_format; // object file format to write
+extern int prg_flag; // generate Atari ST direct executable
LONG symsize = 0; // Size of BSD symbol table
LONG strindx = 0x00000004; // BSD string table index
}
+/*
+ * Alcyon symbol flags
+ */
+#define AL_DEFINED 0x8000
+#define AL_EQUATED 0x4000
+#define AL_GLOBAL 0x2000
+#define AL_EQUREG 0x1000
+#define AL_EXTERN 0x0800
+#define AL_DATA 0x0400
+#define AL_TEXT 0x0200
+#define AL_BSS 0x0100
+#define AL_FILE 0x0080
+
+LONG PRGFLAGS; /* PRGFLAGS as defined in Atari Compendium Chapter 2 */
+ /* Definition Bit(s) Meaning */
+ /* PF_FASTLOAD 0 If set, clear only the BSS area on program load, */
+ /* otherwise clear the entire heap. */
+ /* PF_TTRAMLOAD 1 If set, the program may be loaded into alternative RAM, */
+ /* otherwise it must be loaded into standard RAM. */
+ /* PF_TTRAMMEM 2 If set, the program's Malloc() requests may be satisfied */
+ /* from alternative RAM, otherwise they must be satisfied */
+ /* from standard RAM. */
+ /* - 3 Currently unused. */
+ /* See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' */
+ /* entire memory space will be considered private */
+ /* (when memory protection is enabled).If these bits are */
+ /* set to 1 (PF_GLOBAL), the processes' entire memory space */
+ /* will be readable and writable by any process (i.e. global). */
+ /* If these bits are set to 2 (PF_SUPERVISOR), the processes' */
+ /* entire memory space will only be readable and writable by */
+ /* itself and any other process in supervisor mode.If these */
+ /* bits are set to 3 (PF_READABLE), the processes' entire memory */
+ /* space will be readable by any application but only */
+ /* writable by itself. */
+ /* - 6-15 Currently unused. */
+
+static WORD tdb_tab[] = {
+ 0, /* absolute */
+ AL_TEXT, /* TEXT segment based */
+ AL_DATA, 0, /* DATA segment based */
+ AL_BSS /* BSS segment based */
+};
+
+
+#define HDRSIZE 0x1C /* size of Alcyon header */
+
+
+/*
+ * Add entry to symbol table;
+ * if `globflag' is 1, make the symbol global;
+ * if in .PRG mode, adjust symbol values for fake link.
+ *
+ */
+char * constr_symtab(register char * buf, SYM * sym, int globflag)
+{
+ register int i;
+ register char * s;
+ register WORD w;
+ register LONG z;
+ register WORD w1;
+
+ /*
+ * Copy symbol name
+ */
+ s = sym->sname;
+
+ for(i=0; i<8 && *s; i++)
+ *buf++ = *s++;
+
+ while (i++ < 8)
+ *buf++ = '\0';
+
+ /*
+ * Construct and deposit flag word
+ *
+ * o all symbols are AL_DEFINED
+ * o install T/D/B/A base
+ * o install 'equated'
+ * o commons (COMMON) are AL_EXTERN, but not BSS
+ * o exports (DEFINED) are AL_GLOBAL
+ * o imports (~DEFINED) are AL_EXTERN
+ *
+ */
+ w1 = sym->sattr;
+ w = AL_DEFINED | tdb_tab[w1 & TDB];
+
+ if (w1 & EQUATED) /* equated */
+ w |= AL_EQUATED;
+
+ if (w1 & COMMON)
+ {
+ w |= AL_EXTERN | AL_GLOBAL; /* common symbol */
+ w &= ~AL_BSS; /* they're not BSS in Alcyon object files */
+ }
+ else if (w1 & DEFINED)
+ {
+ if (globflag) /* export the symbol */
+ w |= AL_GLOBAL;
+ }
+ else w |= AL_EXTERN; /* imported symbol */
+
+ *buf++ = w >> 8;
+ *buf++ = (char)w;
+
+ z = sym->svalue;
+
+ if (prg_flag) /* relocate value in .PRG segment */
+ {
+ w1 &= DATA | BSS;
+
+ if (w1)
+ z += sect[TEXT].sloc;
+
+ if (w1 & BSS)
+ z += sect[DATA].sloc;
+ }
+
+ *buf++ = z >> 24; /* deposit symbol value */
+ *buf++ = z >> 16;
+ *buf++ = z >> 8;
+ *buf++ = z;
+
+ return buf;
+}
+
+
//
// Write an object file to the passed in file descriptor
// N.B.: Return value is ignored...
LONG trsize, drsize; // Size of relocations
long unused; // For supressing 'write' warnings
- // Write requested object file...
- switch (obj_format)
+ if (verb_flag)
{
- case BSD:
+ printf("TEXT segment: %d bytes\n", sect[TEXT].sloc);
+ printf("DATA segment: %d bytes\n", sect[DATA].sloc);
+ printf("BSS segment: %d bytes\n", sect[BSS].sloc);
+ }
+
+ // Write requested object file...
+ if (obj_format==BSD || (obj_format==ALCYON && prg_flag==0))
+ {
+ if (verb_flag)
+ {
+ printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
+ }
ssize = ((LONG)sy_assign(NULL, NULL)); // Assign index numbers to the symbols
tds = sect[TEXT].sloc + sect[DATA].sloc; // Get size of TEXT and DATA segment
buf = malloc(0x600000); // Allocate 6mb object file image memory
if (buf)
free(buf); // Free allocated memory
- break;
+ }
+ else if (obj_format==ALCYON)
+ {
+ 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);
+ }
+ }
+ /*
+ * Compute size of symbol table;
+ * assign numbers to the symbols...
+ */
+ ssize = 0;
+
+ if (prg_flag != 1)
+ ssize = ((LONG)sy_assign(NULL, NULL)) * 14;
+
+ /*
+ * Alloc memory for header+text+data, symbol and
+ * relocation information construction.
+ */
+ t = tds = sect[TEXT].sloc + sect[DATA].sloc;
+
+ if (t < ssize)
+ t = ssize;
+
+ buf = (char *)((int)malloc(t + HDRSIZE) + HDRSIZE);
+
+ /*
+ * Build object file header
+ * just before the text+data image
+ */
+ chptr = buf - HDRSIZE; /* -> base of header */
+ D_word(0x601a); /* 00 - magic number */
+ t = sect[TEXT].sloc; /* 02 - TEXT size */
+ D_long(t);
+ t = sect[DATA].sloc; /* 06 - DATA size */
+ D_long(t);
+ t = sect[BSS].sloc; /* 0a - BSS size */
+ D_long(t);
+ D_long(ssize); /* 0e - symbol table size */
+ 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;
+
+ for(i=TEXT; i<=DATA; i++)
+ {
+ for (cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
+ {
+ memcpy(p, cp->chptr, cp->ch_size);
+ p += cp->ch_size;
+ }
+ }
+
+ if (prg_flag)
+ markimg(buf, tds, sect[TEXT].sloc, 0);
+
+ write(fd, buf - HDRSIZE, tds + HDRSIZE);
+
+ /*
+ * Construct and write symbol table
+ */
+ if (prg_flag != 1)
+ {
+ sy_assign(buf, constr_symtab);
+ write(fd, buf, ssize);
+ }
+
+ /*
+ * Construct and write relocation information;
+ * the size of it changes if we're writing a RELMODed executable.
+ */
+ tds = markimg(buf, tds, sect[TEXT].sloc, 1);
+ write(fd, buf, tds);
}
return 0;