/*****************************************************************************/
/* */
-/* o65.c */
+/* o65.c */
/* */
-/* Module to handle the o65 binary format */
+/* Module to handle the o65 binary format */
/* */
/* */
/* */
-/* (C) 1999-2010, Ullrich von Bassewitz */
+/* (C) 1999-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* common */
#include "chartype.h"
#include "check.h"
+#include "fname.h"
#include "print.h"
#include "version.h"
#include "xmalloc.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Header mode bits */
-#define MF_CPU_65816 0x8000 /* Executable is for 65816 */
+#define MF_CPU_65816 0x8000 /* Executable is for 65816 */
#define MF_CPU_6502 0x0000 /* Executable is for the 6502 */
#define MF_CPU_MASK 0x8000 /* Mask to extract CPU type */
#define MF_RELOC_BYTE 0x0000 /* Byte wise relocation */
#define MF_RELOC_MASK 0x4000 /* Mask to extract relocation type */
-#define MF_SIZE_32BIT 0x2000 /* All size words are 32bit */
+#define MF_SIZE_32BIT 0x2000 /* All size words are 32bit */
#define MF_SIZE_16BIT 0x0000 /* All size words are 16bit */
#define MF_SIZE_MASK 0x2000 /* Mask to extract size */
#define MF_ALIGN_2 0x0001 /* Align words */
#define MF_ALIGN_4 0x0002 /* Align longwords */
#define MF_ALIGN_256 0x0003 /* Align pages (256 bytes) */
-#define MF_ALIGN_MASK 0x0003 /* Mask to extract alignment */
+#define MF_ALIGN_MASK 0x0003 /* Mask to extract alignment */
/* The four o65 segment types. Note: These values are identical to the values
* needed for the segmentID in the o65 spec.
*/
-#define O65SEG_UNDEF 0x00
-#define O65SEG_ABS 0x01
-#define O65SEG_TEXT 0x02
-#define O65SEG_DATA 0x03
-#define O65SEG_BSS 0x04
-#define O65SEG_ZP 0x05
+#define O65SEG_UNDEF 0x00
+#define O65SEG_ABS 0x01
+#define O65SEG_TEXT 0x02
+#define O65SEG_DATA 0x03
+#define O65SEG_BSS 0x04
+#define O65SEG_ZP 0x05
/* Relocation type codes for the o65 format */
-#define O65RELOC_WORD 0x80
-#define O65RELOC_HIGH 0x40
-#define O65RELOC_LOW 0x20
-#define O65RELOC_SEGADR 0xC0
-#define O65RELOC_SEG 0xA0
+#define O65RELOC_WORD 0x80
+#define O65RELOC_HIGH 0x40
+#define O65RELOC_LOW 0x20
+#define O65RELOC_SEGADR 0xC0
+#define O65RELOC_SEG 0xA0
#define O65RELOC_MASK 0xE0
/* O65 executable file header */
typedef struct O65Header O65Header;
struct O65Header {
- unsigned Version; /* Version number for o65 format */
- unsigned Mode; /* Mode word */
- unsigned long TextBase; /* Base address of text segment */
- unsigned long TextSize; /* Size of text segment */
- unsigned long DataBase; /* Base of data segment */
- unsigned long DataSize; /* Size of data segment */
- unsigned long BssBase; /* Base of bss segment */
- unsigned long BssSize; /* Size of bss segment */
- unsigned long ZPBase; /* Base of zeropage segment */
- unsigned long ZPSize; /* Size of zeropage segment */
- unsigned long StackSize; /* Requested stack size */
+ unsigned Version; /* Version number for o65 format */
+ unsigned Mode; /* Mode word */
+ unsigned long TextBase; /* Base address of text segment */
+ unsigned long TextSize; /* Size of text segment */
+ unsigned long DataBase; /* Base of data segment */
+ unsigned long DataSize; /* Size of data segment */
+ unsigned long BssBase; /* Base of bss segment */
+ unsigned long BssSize; /* Size of bss segment */
+ unsigned long ZPBase; /* Base of zeropage segment */
+ unsigned long ZPSize; /* Size of zeropage segment */
+ unsigned long StackSize; /* Requested stack size */
};
/* An o65 option */
typedef struct O65Option O65Option;
struct O65Option {
- O65Option* Next; /* Next in option list */
- unsigned char Type; /* Type of option */
- unsigned char Len; /* Data length */
- unsigned char Data [1]; /* Data, dynamically allocated */
+ O65Option* Next; /* Next in option list */
+ unsigned char Type; /* Type of option */
+ unsigned char Len; /* Data length */
+ unsigned char Data [1]; /* Data, dynamically allocated */
};
/* A o65 relocation table */
typedef struct O65RelocTab O65RelocTab;
struct O65RelocTab {
- unsigned Size; /* Size of the table */
- unsigned Fill; /* Amount used */
- unsigned char* Buf; /* Buffer, dynamically allocated */
+ unsigned Size; /* Size of the table */
+ unsigned Fill; /* Amount used */
+ unsigned char* Buf; /* Buffer, dynamically allocated */
};
/* Structure describing the format */
struct O65Desc {
- O65Header Header; /* File header */
- O65Option* Options; /* List of file options */
- ExtSymTab* Exports; /* Table with exported symbols */
- ExtSymTab* Imports; /* Table with imported symbols */
- unsigned Undef; /* Count of undefined symbols */
- FILE* F; /* The file we're writing to */
- const char* Filename; /* Name of the output file */
- O65RelocTab* TextReloc; /* Relocation table for text segment */
- O65RelocTab* DataReloc; /* Relocation table for data segment */
-
- unsigned TextCount; /* Number of segments assigned to .text */
- SegDesc** TextSeg; /* Array of text segments */
- unsigned DataCount; /* Number of segments assigned to .data */
- SegDesc** DataSeg; /* Array of data segments */
- unsigned BssCount; /* Number of segments assigned to .bss */
- SegDesc** BssSeg; /* Array of bss segments */
- unsigned ZPCount; /* Number of segments assigned to .zp */
- SegDesc** ZPSeg; /* Array of zp segments */
+ O65Header Header; /* File header */
+ O65Option* Options; /* List of file options */
+ ExtSymTab* Exports; /* Table with exported symbols */
+ ExtSymTab* Imports; /* Table with imported symbols */
+ unsigned Undef; /* Count of undefined symbols */
+ FILE* F; /* The file we're writing to */
+ const char* Filename; /* Name of the output file */
+ O65RelocTab* TextReloc; /* Relocation table for text segment */
+ O65RelocTab* DataReloc; /* Relocation table for data segment */
+
+ unsigned TextCount; /* Number of segments assigned to .text */
+ SegDesc** TextSeg; /* Array of text segments */
+ unsigned DataCount; /* Number of segments assigned to .data */
+ SegDesc** DataSeg; /* Array of data segments */
+ unsigned BssCount; /* Number of segments assigned to .bss */
+ SegDesc** BssSeg; /* Array of bss segments */
+ unsigned ZPCount; /* Number of segments assigned to .zp */
+ SegDesc** ZPSeg; /* Array of zp segments */
/* Temporary data for writing segments */
unsigned long SegSize;
O65RelocTab* CurReloc;
- long LastOffs;
+ long LastOffs;
};
/* Structure for parsing expression trees */
typedef struct ExprDesc ExprDesc;
struct ExprDesc {
- O65Desc* D; /* File format descriptor */
- long Val; /* The offset value */
- int TooComplex; /* Expression too complex */
+ O65Desc* D; /* File format descriptor */
+ long Val; /* The offset value */
+ int TooComplex; /* Expression too complex */
MemoryArea* MemRef; /* Memory reference if any */
Segment* SegRef; /* Segment reference if any */
- Section* SecRef; /* Section reference if any */
- ExtSym* ExtRef; /* External reference if any */
+ Section* SecRef; /* Section reference if any */
+ ExtSym* ExtRef; /* External reference if any */
};
/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D)
/* Initialize an ExprDesc structure for use with O65ParseExpr */
{
- ED->D = D;
- ED->Val = 0;
+ ED->D = D;
+ ED->Val = 0;
ED->TooComplex = 0;
ED->MemRef = 0;
ED->SegRef = 0;
/* Write a "size" word to the file */
{
switch (D->Header.Mode & MF_SIZE_MASK) {
- case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break;
- case MF_SIZE_32BIT: Write32 (D->F, Val); break;
- default: Internal ("Invalid size in header: %04X", D->Header.Mode);
+ case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break;
+ case MF_SIZE_32BIT: Write32 (D->F, Val); break;
+ default: Internal ("Invalid size in header: %04X", D->Header.Mode);
}
}
* to check SF_ZP first.
*/
if (S->Flags & SF_RO) {
- return O65SEG_TEXT;
+ return O65SEG_TEXT;
} else if (S->Flags & SF_ZP) {
- return O65SEG_ZP;
+ return O65SEG_ZP;
} else if (S->Flags & SF_BSS) {
- return O65SEG_BSS;
+ return O65SEG_BSS;
} else {
- return O65SEG_DATA;
+ return O65SEG_DATA;
}
}
for (I = 0; I < CollCount (&M->SegList); ++I) {
/* Get the segment and check if it's a run segment */
- SegDesc* S = CollAtUnchecked (&M->SegList, I);
+ SegDesc* S = CollAtUnchecked (&M->SegList, I);
if (S->Run == M) {
unsigned long O;
unsigned I;
for (I = 0; I < Count; ++I) {
- if (List[I]->Seg == S) {
- /* Found */
- return List[I];
- }
+ if (List[I]->Seg == S) {
+ /* Found */
+ return List[I];
+ }
}
/* Not found */
const SegDesc* SD;
if ((SD = FindSeg (D->TextSeg, D->TextCount, S)) != 0) {
- return SD;
+ return SD;
}
if ((SD = FindSeg (D->DataSeg, D->DataCount, S)) != 0) {
- return SD;
+ return SD;
}
if ((SD = FindSeg (D->BssSeg, D->BssCount, S)) != 0) {
- return SD;
+ return SD;
}
if ((SD = FindSeg (D->ZPSeg, D->ZPCount, S)) != 0) {
- return SD;
+ return SD;
}
/* Not found */
/*****************************************************************************/
-/* Expression handling */
+/* Expression handling */
/*****************************************************************************/
switch (Expr->Op) {
- case EXPR_LITERAL:
+ case EXPR_LITERAL:
D->Val += (Sign * Expr->V.IVal);
- break;
-
- case EXPR_SYMBOL:
- /* Get the referenced Export */
- E = GetExprExport (Expr);
- /* If this export has a mark set, we've already encountered it.
- * This means that the export is used to define it's own value,
- * which in turn means, that we have a circular reference.
- */
- if (ExportHasMark (E)) {
- CircularRefError (E);
- } else if (E->Expr == 0) {
- /* Dummy export, must be an o65 imported symbol */
- ExtSym* S = O65GetImport (D->D, E->Name);
- CHECK (S != 0);
- if (D->ExtRef) {
- /* We cannot have more than one external reference in o65 */
- D->TooComplex = 1;
- } else {
- /* Remember the external reference */
- D->ExtRef = S;
- }
- } else {
- MarkExport (E);
- O65ParseExpr (E->Expr, D, Sign);
- UnmarkExport (E);
- }
- break;
-
- case EXPR_SECTION:
- if (D->SecRef) {
- /* We cannot handle more than one segment reference in o65 */
- D->TooComplex = 1;
- } else {
- /* Remember the segment reference */
- D->SecRef = GetExprSection (Expr);
+ break;
+
+ case EXPR_SYMBOL:
+ /* Get the referenced Export */
+ E = GetExprExport (Expr);
+ /* If this export has a mark set, we've already encountered it.
+ * This means that the export is used to define it's own value,
+ * which in turn means, that we have a circular reference.
+ */
+ if (ExportHasMark (E)) {
+ CircularRefError (E);
+ } else if (E->Expr == 0) {
+ /* Dummy export, must be an o65 imported symbol */
+ ExtSym* S = O65GetImport (D->D, E->Name);
+ CHECK (S != 0);
+ if (D->ExtRef) {
+ /* We cannot have more than one external reference in o65 */
+ D->TooComplex = 1;
+ } else {
+ /* Remember the external reference */
+ D->ExtRef = S;
+ }
+ } else {
+ MarkExport (E);
+ O65ParseExpr (E->Expr, D, Sign);
+ UnmarkExport (E);
+ }
+ break;
+
+ case EXPR_SECTION:
+ if (D->SecRef) {
+ /* We cannot handle more than one segment reference in o65 */
+ D->TooComplex = 1;
+ } else {
+ /* Remember the segment reference */
+ D->SecRef = GetExprSection (Expr);
/* Add the offset of the section to the constant value */
D->Val += Sign * (D->SecRef->Offs + D->SecRef->Seg->PC);
- }
- break;
+ }
+ break;
case EXPR_SEGMENT:
- if (D->SegRef) {
- /* We cannot handle more than one segment reference in o65 */
- D->TooComplex = 1;
- } else {
- /* Remember the segment reference */
- D->SegRef = Expr->V.Seg;
+ if (D->SegRef) {
+ /* We cannot handle more than one segment reference in o65 */
+ D->TooComplex = 1;
+ } else {
+ /* Remember the segment reference */
+ D->SegRef = Expr->V.Seg;
/* Add the offset of the segment to the constant value */
D->Val += (Sign * D->SegRef->PC);
- }
- break;
+ }
+ break;
case EXPR_MEMAREA:
- if (D->MemRef) {
- /* We cannot handle more than one memory reference in o65 */
- D->TooComplex = 1;
- } else {
- /* Remember the memory area reference */
- D->MemRef = Expr->V.Mem;
+ if (D->MemRef) {
+ /* We cannot handle more than one memory reference in o65 */
+ D->TooComplex = 1;
+ } else {
+ /* Remember the memory area reference */
+ D->MemRef = Expr->V.Mem;
/* Add the start address of the memory area to the constant
* value
*/
D->Val += (Sign * D->MemRef->Start);
- }
- break;
+ }
+ break;
- case EXPR_PLUS:
- O65ParseExpr (Expr->Left, D, Sign);
- O65ParseExpr (Expr->Right, D, Sign);
- break;
+ case EXPR_PLUS:
+ O65ParseExpr (Expr->Left, D, Sign);
+ O65ParseExpr (Expr->Right, D, Sign);
+ break;
- case EXPR_MINUS:
- O65ParseExpr (Expr->Left, D, Sign);
- O65ParseExpr (Expr->Right, D, -Sign);
- break;
+ case EXPR_MINUS:
+ O65ParseExpr (Expr->Left, D, Sign);
+ O65ParseExpr (Expr->Right, D, -Sign);
+ break;
- default:
- /* Expression contains illegal operators */
- D->TooComplex = 1;
- break;
+ default:
+ /* Expression contains illegal operators */
+ D->TooComplex = 1;
+ break;
}
}
/*****************************************************************************/
-/* Relocation tables */
+/* Relocation tables */
/*****************************************************************************/
{
/* Do we have enough space in the buffer? */
if (R->Fill == R->Size) {
- /* We need to grow the buffer */
+ /* We need to grow the buffer */
if (R->Size) {
R->Size *= 2;
} else {
/*****************************************************************************/
-/* Option handling */
+/* Option handling */
/*****************************************************************************/
O = xmalloc (sizeof (O65Option) - 1 + DataLen);
/* Initialize the structure */
- O->Next = 0;
- O->Type = Type;
- O->Len = DataLen;
+ O->Next = 0;
+ O->Type = Type;
+ O->Len = DataLen;
memcpy (O->Data, Data, DataLen);
/* Return the created struct */
static void FreeO65Option (O65Option* O)
-/* Free an O65Option struct */
+/* Free an O65Option struct */
{
xfree (O);
}
/*****************************************************************************/
-/* Subroutines to write o65 sections */
+/* Subroutines to write o65 sections */
/*****************************************************************************/
/* Write the header of the executable to the given file */
{
static unsigned char Trailer [5] = {
- 0x01, 0x00, 0x6F, 0x36, 0x35
+ 0x01, 0x00, 0x6F, 0x36, 0x35
};
O65Option* O;
/* Write the options */
O = D->Options;
while (O) {
- Write8 (D->F, O->Len + 2); /* Account for len and type bytes */
- Write8 (D->F, O->Type);
- if (O->Len) {
- WriteData (D->F, O->Data, O->Len);
- }
- O = O->Next;
+ Write8 (D->F, O->Len + 2); /* Account for len and type bytes */
+ Write8 (D->F, O->Type);
+ if (O->Len) {
+ WriteData (D->F, O->Data, O->Len);
+ }
+ O = O->Next;
}
/* Write the end-of-options byte */
static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
- unsigned long Offs, void* Data)
+ unsigned long Offs, void* Data)
/* Called from SegWrite for an expression. Evaluate the expression, check the
* range and write the expression value to the file, update the relocation
* table.
/* Check for a constant expression */
if (IsConstExpr (E)) {
- /* Write out the constant expression */
- return SegWriteConstExpr (((O65Desc*)Data)->F, E, Signed, Size);
+ /* Write out the constant expression */
+ return SegWriteConstExpr (((O65Desc*)Data)->F, E, Signed, Size);
}
/* We have a relocatable expression that needs a relocation table entry.
* Calculate the number of bytes between this entry and the last one, and
* setup all necessary intermediate bytes in the relocation table.
*/
- Offs += D->SegSize; /* Calulate full offset */
+ Offs += D->SegSize; /* Calulate full offset */
Diff = ((long) Offs) - D->LastOffs;
while (Diff > 0xFE) {
- O65RelocPutByte (D->CurReloc, 0xFF);
- Diff -= 0xFE;
+ O65RelocPutByte (D->CurReloc, 0xFF);
+ Diff -= 0xFE;
}
O65RelocPutByte (D->CurReloc, (unsigned char) Diff);
/* Determine the expression to relocate */
Expr = E;
- if (E->Op == EXPR_BYTE0 || E->Op == EXPR_BYTE1 ||
- E->Op == EXPR_BYTE2 || E->Op == EXPR_BYTE3 ||
- E->Op == EXPR_WORD0 || E->Op == EXPR_WORD1) {
- /* Use the real expression */
- Expr = E->Left;
+ if (E->Op == EXPR_BYTE0 || E->Op == EXPR_BYTE1 ||
+ E->Op == EXPR_BYTE2 || E->Op == EXPR_BYTE3 ||
+ E->Op == EXPR_WORD0 || E->Op == EXPR_WORD1 ||
+ E->Op == EXPR_FARADDR || E->Op == EXPR_DWORD) {
+ /* Use the real expression */
+ Expr = E->Left;
}
/* Recursively collect information about this expression */
RefCount = (ED.MemRef != 0) + (ED.SegRef != 0) +
(ED.SecRef != 0) + (ED.ExtRef != 0);
if (RefCount > 1) {
- ED.TooComplex = 1;
+ ED.TooComplex = 1;
}
/* If we have a memory area reference, we need to convert it into a
/* Bail out if we cannot handle the expression */
if (ED.TooComplex) {
- return SEG_EXPR_TOO_COMPLEX;
+ return SEG_EXPR_TOO_COMPLEX;
}
/* Safety: Check that we have exactly one reference */
/* Write out the offset that goes into the segment. */
BinVal = ED.Val;
switch (E->Op) {
- case EXPR_BYTE0: BinVal &= 0xFF; break;
- case EXPR_BYTE1: BinVal = (BinVal >> 8) & 0xFF; break;
- case EXPR_BYTE2: BinVal = (BinVal >> 16) & 0xFF; break;
- case EXPR_BYTE3: BinVal = (BinVal >> 24) & 0xFF; break;
- case EXPR_WORD0: BinVal &= 0xFFFF; break;
- case EXPR_WORD1: BinVal = (BinVal >> 16) & 0xFFFF; break;
+ case EXPR_BYTE0: BinVal &= 0xFF; break;
+ case EXPR_BYTE1: BinVal = (BinVal >> 8) & 0xFF; break;
+ case EXPR_BYTE2: BinVal = (BinVal >> 16) & 0xFF; break;
+ case EXPR_BYTE3: BinVal = (BinVal >> 24) & 0xFF; break;
+ case EXPR_WORD0: BinVal &= 0xFFFF; break;
+ case EXPR_WORD1: BinVal = (BinVal >> 16) & 0xFFFF; break;
+ case EXPR_FARADDR: BinVal &= 0xFFFFFFUL; break;
+ case EXPR_DWORD: BinVal &= 0xFFFFFFFFUL; break;
}
WriteVal (D->F, BinVal, Size);
* information gathered about the expression.
*/
if (E->Op == EXPR_BYTE0) {
- RelocType = O65RELOC_LOW;
+ RelocType = O65RELOC_LOW;
} else if (E->Op == EXPR_BYTE1) {
- RelocType = O65RELOC_HIGH;
+ RelocType = O65RELOC_HIGH;
} else if (E->Op == EXPR_BYTE2) {
- RelocType = O65RELOC_SEG;
+ RelocType = O65RELOC_SEG;
} else {
- switch (Size) {
+ switch (Size) {
- case 1:
- RelocType = O65RELOC_LOW;
- break;
+ case 1:
+ RelocType = O65RELOC_LOW;
+ break;
- case 2:
- RelocType = O65RELOC_WORD;
- break;
+ case 2:
+ RelocType = O65RELOC_WORD;
+ break;
- case 3:
- RelocType = O65RELOC_SEGADR;
- break;
+ case 3:
+ RelocType = O65RELOC_SEGADR;
+ break;
- case 4:
- /* 4 byte expression not supported by o65 */
- return SEG_EXPR_TOO_COMPLEX;
+ case 4:
+ /* 4 byte expression not supported by o65 */
+ return SEG_EXPR_TOO_COMPLEX;
- default:
- Internal ("O65WriteExpr: Invalid expression size: %u", Size);
- RelocType = 0; /* Avoid gcc warnings */
- }
+ default:
+ Internal ("O65WriteExpr: Invalid expression size: %u", Size);
+ RelocType = 0; /* Avoid gcc warnings */
+ }
}
/* Determine which segment we're referencing */
ED.SegRef = ED.SecRef->Seg;
}
- /* Search for the segment and map it to it's o65 segmentID */
- Seg = O65FindSeg (D, ED.SegRef);
- if (Seg == 0) {
- /* For some reason, we didn't find this segment in the list of
- * segments written to the o65 file.
- */
- return SEG_EXPR_INVALID;
- }
- RelocType |= O65SegType (Seg);
- O65RelocPutByte (D->CurReloc, RelocType);
-
- /* Output additional data if needed */
- switch (RelocType & O65RELOC_MASK) {
- case O65RELOC_HIGH:
- O65RelocPutByte (D->CurReloc, ED.Val & 0xFF);
- break;
- case O65RELOC_SEG:
- O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
- break;
- }
+ /* Search for the segment and map it to it's o65 segmentID */
+ Seg = O65FindSeg (D, ED.SegRef);
+ if (Seg == 0) {
+ /* For some reason, we didn't find this segment in the list of
+ * segments written to the o65 file.
+ */
+ return SEG_EXPR_INVALID;
+ }
+ RelocType |= O65SegType (Seg);
+ O65RelocPutByte (D->CurReloc, RelocType);
+
+ /* Output additional data if needed */
+ switch (RelocType & O65RELOC_MASK) {
+ case O65RELOC_HIGH:
+ O65RelocPutByte (D->CurReloc, ED.Val & 0xFF);
+ break;
+ case O65RELOC_SEG:
+ O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF);
+ break;
+ }
} else if (ED.ExtRef) {
- /* Imported symbol */
- RelocType |= O65SEG_UNDEF;
- O65RelocPutByte (D->CurReloc, RelocType);
- /* Put the number of the imported symbol into the table */
- O65RelocPutWord (D->CurReloc, ExtSymNum (ED.ExtRef));
+ /* Imported symbol */
+ RelocType |= O65SEG_UNDEF;
+ O65RelocPutByte (D->CurReloc, RelocType);
+ /* Put the number of the imported symbol into the table */
+ O65RelocPutWord (D->CurReloc, ExtSymNum (ED.ExtRef));
} else {
/* Write out all segments */
for (I = 0; I < Count; ++I) {
- /* Get the segment from the list node */
- S = Seg [I];
+ /* Get the segment from the list node */
+ S = Seg [I];
- /* Relocate line info for this segment */
- RelocLineInfo (S->Seg);
+ /* Keep the user happy */
+ Print (stdout, 1, " Writing `%s'\n", GetString (S->Name));
- /* Keep the user happy */
- Print (stdout, 1, " Writing `%s'\n", GetString (S->Name));
-
- /* Write this segment */
- if (DoWrite) {
- SegWrite (D->Filename, D->F, S->Seg, O65WriteExpr, D);
- }
+ /* Write this segment */
+ if (DoWrite) {
+ SegWrite (D->Filename, D->F, S->Seg, O65WriteExpr, D);
+ }
- /* Mark the segment as dumped */
- S->Seg->Dumped = 1;
+ /* Mark the segment as dumped */
+ S->Seg->Dumped = 1;
- /* Calculate the total size */
- D->SegSize += S->Seg->Size;
+ /* Calculate the total size */
+ D->SegSize += S->Seg->Size;
}
/* Terminate the relocation table for this segment */
/* Check the size of the segment for overflow */
if ((D->Header.Mode & MF_SIZE_MASK) == MF_SIZE_16BIT && D->SegSize > 0xFFFF) {
- Error ("Segment overflow in file `%s'", D->Filename);
+ Error ("Segment overflow in file `%s'", D->Filename);
}
}
/* Write the code segment to the o65 output file */
{
/* Initialize variables */
- D->CurReloc = D->TextReloc;
+ D->CurReloc = D->TextReloc;
/* Dump all text segments */
O65WriteSeg (D, D->TextSeg, D->TextCount, 1);
/* Write the data segment to the o65 output file */
{
/* Initialize variables */
- D->CurReloc = D->DataReloc;
+ D->CurReloc = D->DataReloc;
/* Dump all data segments */
O65WriteSeg (D, D->DataSeg, D->DataCount, 1);
*/
{
/* Initialize variables */
- D->CurReloc = 0;
+ D->CurReloc = 0;
- /* Dump all data segments */
+ /* Dump all bss segments */
O65WriteSeg (D, D->BssSeg, D->BssCount, 0);
/* Set the size of the segment */
*/
{
/* Initialize variables */
- D->CurReloc = 0;
+ D->CurReloc = 0;
- /* Dump all data segments */
+ /* Dump all zp segments */
O65WriteSeg (D, D->ZPSeg, D->ZPCount, 0);
/* Set the size of the segment */
/* Write out the symbol names, zero terminated */
S = ExtSymList (D->Imports);
while (S) {
- /* Get the name */
- const char* Name = GetString (ExtSymName (S));
- /* And write it to the output file */
- WriteData (D->F, Name, strlen (Name) + 1);
- /* Next symbol */
- S = ExtSymNext (S);
+ /* Get the name */
+ const char* Name = GetString (ExtSymName (S));
+ /* And write it to the output file */
+ WriteData (D->F, Name, strlen (Name) + 1);
+ /* Next symbol */
+ S = ExtSymNext (S);
}
}
S = ExtSymList (D->Exports);
while (S) {
- ExprNode* Expr;
- unsigned char SegmentID;
- ExprDesc ED;
+ ExprNode* Expr;
+ unsigned char SegmentID;
+ ExprDesc ED;
- /* Get the name */
- unsigned NameIdx = ExtSymName (S);
+ /* Get the name */
+ unsigned NameIdx = ExtSymName (S);
const char* Name = GetString (NameIdx);
- /* Get the export for this symbol. We've checked before that this
- * export does really exist, so if it is unresolved, or if we don't
- * find it, there is an error in the linker code.
- */
- Export* E = FindExport (NameIdx);
- if (E == 0 || IsUnresolvedExport (E)) {
- Internal ("Unresolved export `%s' found in O65WriteExports", Name);
- }
+ /* Get the export for this symbol. We've checked before that this
+ * export does really exist, so if it is unresolved, or if we don't
+ * find it, there is an error in the linker code.
+ */
+ Export* E = FindExport (NameIdx);
+ if (E == 0 || IsUnresolvedExport (E)) {
+ Internal ("Unresolved export `%s' found in O65WriteExports", Name);
+ }
- /* Get the expression for the symbol */
- Expr = E->Expr;
+ /* Get the expression for the symbol */
+ Expr = E->Expr;
- /* Recursively collect information about this expression */
- O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
+ /* Recursively collect information about this expression */
+ O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
- /* We cannot handle expressions with imported symbols, or expressions
+ /* We cannot handle expressions with imported symbols, or expressions
* with more than one segment reference here
*/
- if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) {
- ED.TooComplex = 1;
- }
+ if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) {
+ ED.TooComplex = 1;
+ }
- /* Bail out if we cannot handle the expression */
- if (ED.TooComplex) {
- Error ("Expression for symbol `%s' is too complex", Name);
- }
+ /* Bail out if we cannot handle the expression */
+ if (ED.TooComplex) {
+ Error ("Expression for symbol `%s' is too complex", Name);
+ }
- /* Determine the segment id for the expression */
+ /* Determine the segment id for the expression */
if (ED.SegRef != 0 || ED.SecRef != 0) {
const SegDesc* Seg;
ED.SegRef = ED.SecRef->Seg; /* Get segment from section */
}
- /* Search for the segment and map it to it's o65 segmentID */
- Seg = O65FindSeg (D, ED.SegRef);
- if (Seg == 0) {
- /* For some reason, we didn't find this segment in the list of
- * segments written to the o65 file.
- */
- Error ("Segment for symbol `%s' is undefined", Name);
- }
- SegmentID = O65SegType (Seg);
+ /* Search for the segment and map it to it's o65 segmentID */
+ Seg = O65FindSeg (D, ED.SegRef);
+ if (Seg == 0) {
+ /* For some reason, we didn't find this segment in the list of
+ * segments written to the o65 file.
+ */
+ Error ("Segment for symbol `%s' is undefined", Name);
+ }
+ SegmentID = O65SegType (Seg);
} else {
- /* Absolute value */
- SegmentID = O65SEG_ABS;
+ /* Absolute value */
+ SegmentID = O65SEG_ABS;
- }
+ }
- /* Write the name to the output file */
- WriteData (D->F, Name, strlen (Name) + 1);
+ /* Write the name to the output file */
+ WriteData (D->F, Name, strlen (Name) + 1);
- /* Output the segment id followed by the literal value */
- Write8 (D->F, SegmentID);
- WriteSize (D, ED.Val);
+ /* Output the segment id followed by the literal value */
+ Write8 (D->F, SegmentID);
+ WriteSize (D, ED.Val);
- /* Next symbol */
- S = ExtSymNext (S);
+ /* Next symbol */
+ S = ExtSymNext (S);
}
}
/*****************************************************************************/
-/* Public code */
+/* Public code */
/*****************************************************************************/
O65Desc* D = xmalloc (sizeof (O65Desc));
/* Initialize the header */
- D->Header.Version = 0;
+ D->Header.Version = 0;
D->Header.Mode = 0;
- D->Header.TextBase = 0;
+ D->Header.TextBase = 0;
D->Header.TextSize = 0;
D->Header.DataBase = 0;
D->Header.DataSize = 0;
D->Header.BssSize = 0;
D->Header.ZPBase = 0;
D->Header.ZPSize = 0;
- D->Header.StackSize = 0; /* Let OS choose a good value */
+ D->Header.StackSize = 0; /* Let OS choose a good value */
/* Initialize other data */
- D->Options = 0;
- D->Exports = NewExtSymTab ();
- D->Imports = NewExtSymTab ();
- D->Undef = 0;
- D->F = 0;
- D->Filename = 0;
- D->TextReloc = NewO65RelocTab ();
- D->DataReloc = NewO65RelocTab ();
- D->TextCount = 0;
- D->TextSeg = 0;
- D->DataCount = 0;
- D->DataSeg = 0;
- D->BssCount = 0;
- D->BssSeg = 0;
- D->ZPCount = 0;
- D->ZPSeg = 0;
+ D->Options = 0;
+ D->Exports = NewExtSymTab ();
+ D->Imports = NewExtSymTab ();
+ D->Undef = 0;
+ D->F = 0;
+ D->Filename = 0;
+ D->TextReloc = NewO65RelocTab ();
+ D->DataReloc = NewO65RelocTab ();
+ D->TextCount = 0;
+ D->TextSeg = 0;
+ D->DataCount = 0;
+ D->DataSeg = 0;
+ D->BssCount = 0;
+ D->BssSeg = 0;
+ D->ZPCount = 0;
+ D->ZPSeg = 0;
/* Return the created struct */
return D;
/* Free the option list */
while (D->Options) {
O65Option* O = D->Options;
- D->Options = D->Options->Next;
- FreeO65Option (O);
+ D->Options = D->Options->Next;
+ FreeO65Option (O);
}
/* Free the external symbol tables */
-void O65SetAlignment (O65Desc* D, unsigned Align)
+void O65SetAlignment (O65Desc* D, unsigned Alignment)
/* Set the executable alignment */
{
/* Remove all alignment bits from the mode word */
D->Header.Mode &= ~MF_ALIGN_MASK;
/* Set the alignment bits */
- switch (Align) {
- case 1: D->Header.Mode |= MF_ALIGN_1; break;
- case 2: D->Header.Mode |= MF_ALIGN_2; break;
- case 4: D->Header.Mode |= MF_ALIGN_4; break;
+ switch (Alignment) {
+ case 1: D->Header.Mode |= MF_ALIGN_1; break;
+ case 2: D->Header.Mode |= MF_ALIGN_2; break;
+ case 4: D->Header.Mode |= MF_ALIGN_4; break;
case 256: D->Header.Mode |= MF_ALIGN_256; break;
- default: Error ("Invalid alignment for O65 format: %u", Align);
+ default: Error ("Invalid alignment for O65 format: %u", Alignment);
}
}
/* Write the correct option length */
switch (OS) {
- case O65OS_CC65:
+ case O65OS_CC65:
/* Set the 16 bit id */
Opt[2] = (unsigned char) Id;
Opt[3] = (unsigned char) (Id >> 8);
- O65SetOption (D, O65OPT_OS, Opt, 4);
- break;
+ O65SetOption (D, O65OPT_OS, Opt, 4);
+ break;
- default:
+ default:
/* No id for OS/A65, Lunix, and unknown OSes */
- O65SetOption (D, O65OPT_OS, Opt, 2);
- break;
+ O65SetOption (D, O65OPT_OS, Opt, 2);
+ break;
}
}
*/
Export* E = FindExport (Ident);
if (E == 0 || IsUnresolvedExport (E)) {
- Error ("Unresolved export: `%s'", GetString (Ident));
+ Error ("Unresolved export: `%s'", GetString (Ident));
}
/* Insert the entry into the table */
case O65SEG_TEXT: D->TextCount++; break;
case O65SEG_DATA: D->DataCount++; break;
case O65SEG_BSS: D->BssCount++; break;
- case O65SEG_ZP: D->ZPCount++; break;
- default: Internal ("Invalid return from O65SegType");
+ case O65SEG_ZP: D->ZPCount++; break;
+ default: Internal ("Invalid return from O65SegType");
}
}
}
/* Check the segment type. */
switch (O65SegType (S)) {
- case O65SEG_TEXT: D->TextSeg [TextIdx++] = S; break;
- case O65SEG_DATA: D->DataSeg [DataIdx++] = S; break;
+ case O65SEG_TEXT: D->TextSeg [TextIdx++] = S; break;
+ case O65SEG_DATA: D->DataSeg [DataIdx++] = S; break;
case O65SEG_BSS: D->BssSeg [BssIdx++] = S; break;
- case O65SEG_ZP: D->ZPSeg [ZPIdx++] = S; break;
- default: Internal ("Invalid return from O65SegType");
+ case O65SEG_ZP: D->ZPSeg [ZPIdx++] = S; break;
+ default: Internal ("Invalid return from O65SegType");
}
}
}
{
/* Check if the symbol is an imported o65 symbol */
if (O65GetImport (D, Name) != 0) {
- /* This is an external symbol, relax... */
- return 1;
+ /* This is an external symbol, relax... */
+ return 1;
} else {
- /* This is actually an unresolved external. Bump the counter */
- ((O65Desc*) D)->Undef++;
- return 0;
+ /* This is actually an unresolved external. Bump the counter */
+ ((O65Desc*) D)->Undef++;
+ return 0;
}
}
void O65WriteTarget (O65Desc* D, File* F)
/* Write an o65 output file */
{
- char OptBuf [256]; /* Buffer for option strings */
+ char OptBuf [256]; /* Buffer for option strings */
unsigned OptLen;
time_t T;
+ const char* Name;
/* Place the filename in the control structure */
D->Filename = GetString (F->Name);
/* Check for unresolved symbols. The function O65Unresolved is called
* if we get an unresolved symbol.
*/
- D->Undef = 0; /* Reset the counter */
+ D->Undef = 0; /* Reset the counter */
CheckUnresolvedImports (O65Unresolved, D);
if (D->Undef > 0) {
- /* We had unresolved symbols, cannot create output file */
- Error ("%u unresolved external(s) found - cannot create output file", D->Undef);
+ /* We had unresolved symbols, cannot create output file */
+ Error ("%u unresolved external(s) found - cannot create output file", D->Undef);
}
/* Setup the segment arrays */
/* Open the file */
D->F = fopen (D->Filename, "wb");
if (D->F == 0) {
- Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
+ Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
}
/* Keep the user happy */
Print (stdout, 1, "Opened `%s'...\n", D->Filename);
- /* Define some more options: A timestamp and the linker version */
+ /* Define some more options: A timestamp, the linker version and the
+ * filename
+ */
T = time (0);
strcpy (OptBuf, ctime (&T));
OptLen = strlen (OptBuf);
O65SetOption (D, O65OPT_TIMESTAMP, OptBuf, OptLen + 1);
sprintf (OptBuf, "ld65 V%s", GetVersionAsString ());
O65SetOption (D, O65OPT_ASM, OptBuf, strlen (OptBuf) + 1);
+ Name = FindName (D->Filename);
+ O65SetOption (D, O65OPT_FILENAME, Name, strlen (Name) + 1);
/* Write the header */
O65WriteHeader (D);
/* Close the file */
if (fclose (D->F) != 0) {
- Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
+ Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
}
/* Reset the file and filename */
D->F = 0;
D->Filename = 0;
}
-
-
-
-