From b0ceece52a07383f3ab3d204c3ba3df340977be8 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 18 May 2002 21:39:35 +0000 Subject: [PATCH] Fixed a bug (offset was not correct if more than one module was used). Added support for the new simple o65 addressing format. git-svn-id: svn://svn.cc65.org/cc65/trunk@1280 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ld65/o65.c | 109 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/src/ld65/o65.c b/src/ld65/o65.c index d14322880..0458207ed 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -66,10 +66,22 @@ #define MF_CPU_6502 0x0000 /* Executable is for the 6502 */ #define MF_CPU_MASK 0x8000 /* Mask to extract CPU type */ +#define MF_RELOC_PAGE 0x4000 /* Page wise relocation */ +#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_16BIT 0x0000 /* All size words are 16bit */ #define MF_SIZE_MASK 0x2000 /* Mask to extract size */ +#define MF_FTYPE_OBJ 0x1000 /* Object file */ +#define MF_FTYPE_EXE 0x0000 /* Executable file */ +#define MF_FTYPE_MASK 0x1000 /* Mask to extract type */ + +#define MF_ADDR_SIMPLE 0x0800 /* Simple addressing */ +#define MF_ADDR_DEFAULT 0x0000 /* Default addressing */ +#define MF_ADDR_MASK 0x0800 /* Mask to extract addressing */ + #define MF_ALIGN_1 0x0000 /* Bytewise alignment */ #define MF_ALIGN_2 0x0001 /* Align words */ #define MF_ALIGN_4 0x0002 /* Align longwords */ @@ -114,40 +126,40 @@ struct O65Header { 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 */ + unsigned char Type; /* Type of option */ + unsigned char Len; /* Data length */ + unsigned char Data [1]; /* Data, dynamically allocated */ }; /* A o65 relocation table */ #define RELOC_BLOCKSIZE 4096 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 */ - 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 */ + 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; @@ -265,7 +277,7 @@ static const SegDesc* O65FindSeg (const O65Desc* D, const Segment* S) /*****************************************************************************/ -/* Expression handling */ +/* Expression handling */ /*****************************************************************************/ @@ -277,6 +289,7 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) */ { Export* E; + unsigned long Val; switch (Expr->Op) { @@ -322,6 +335,13 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) } else { /* Remember the segment reference */ D->SegRef = GetExprSection (Expr); + /* Add the offset of the section to the constant value */ + Val = D->SegRef->Offs + D->SegRef->Seg->PC; + if (Sign < 0) { + D->Val -= Val; + } else { + D->Val += Val; + } } break; @@ -464,7 +484,6 @@ static void O65WriteHeader (O65Desc* D) O65Option* O; - /* Write the fixed header */ WriteData (D->F, Trailer, sizeof (Trailer)); Write8 (D->F, D->Header.Version); @@ -633,7 +652,7 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, case O65RELOC_SEG: O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF); break; - } + } } /* Success */ @@ -1141,6 +1160,7 @@ static void O65SetupSegments (O65Desc* D, Memory* M) /* Next segment node */ N = N->Next; } + } @@ -1161,6 +1181,38 @@ static int O65Unresolved (const char* Name, void* D) +static void O65SetupHeader (O65Desc* D) +/* Set additional stuff in the header */ +{ + /* Set the base addresses of the segments */ + if (D->TextCount > 0) { + SegDesc* FirstSeg = D->TextSeg [0]; + D->Header.TextBase = FirstSeg->Seg->PC; + } + if (D->DataCount > 0) { + SegDesc* FirstSeg = D->DataSeg [0]; + D->Header.DataBase = FirstSeg->Seg->PC; + } + if (D->BssCount > 0) { + SegDesc* FirstSeg = D->BssSeg [0]; + D->Header.BssBase = FirstSeg->Seg->PC; + } + if (D->ZPCount > 0) { + SegDesc* FirstSeg = D->ZPSeg [0]; + D->Header.ZPBase = FirstSeg->Seg->PC; + } + + /* If we have byte wise relocation and an alignment of 1, we can set + * the "simple addressing" bit in the header. + */ + if ((D->Header.Mode & MF_RELOC_MASK) == MF_RELOC_BYTE && + (D->Header.Mode & MF_ALIGN_MASK) == MF_ALIGN_1) { + D->Header.Mode = (D->Header.Mode & ~MF_ADDR_MASK) | MF_ADDR_SIMPLE; + } +} + + + void O65WriteTarget (O65Desc* D, File* F) /* Write an o65 output file */ { @@ -1190,6 +1242,9 @@ void O65WriteTarget (O65Desc* D, File* F) /* Setup the segment arrays */ O65SetupSegments (D, M); + /* Setup additional stuff in the header */ + O65SetupHeader (D); + /* Open the file */ D->F = fopen (F->Name, "wb"); if (D->F == 0) { -- 2.39.5