1
0
mirror of https://github.com/cc65/cc65.git synced 2024-09-30 08:57:49 +00:00

Started to add support for segments.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3805 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2007-08-31 20:27:53 +00:00
parent 10efd998e0
commit 8db6dcd414
8 changed files with 480 additions and 183 deletions

View File

@ -66,6 +66,19 @@ void AddrCheck (unsigned Addr)
int SegmentDefined (unsigned Start, unsigned End)
/* Return true if the atSegment bit is set somewhere in the given range */
{
while (Start <= End) {
if (AttrTab[Start++] & atSegment) {
return 1;
}
}
return 0;
}
unsigned GetGranularity (attr_t Style) unsigned GetGranularity (attr_t Style)
/* Get the granularity for the given style */ /* Get the granularity for the given style */
{ {

View File

@ -69,7 +69,10 @@ typedef enum attr_t {
atLabelDefined = 0x0100, /* True if we defined the label */ atLabelDefined = 0x0100, /* True if we defined the label */
atStyleMask = 0x000F, /* Output style */ atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0 /* Label information */ atLabelMask = 0x00F0, /* Label information */
/* Segment */
atSegment = 0x0100, /* Code is in a segment */
} attr_t; } attr_t;
@ -83,6 +86,9 @@ typedef enum attr_t {
void AddrCheck (unsigned Addr); void AddrCheck (unsigned Addr);
/* Check if the given address has a valid range */ /* Check if the given address has a valid range */
int SegmentDefined (unsigned Start, unsigned End);
/* Return true if the atSegment bit is set somewhere in the given range */
unsigned GetGranularity (attr_t Style); unsigned GetGranularity (attr_t Style);
/* Get the granularity for the given style */ /* Get the granularity for the given style */

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2005 Ullrich von Bassewitz */ /* (C) 2000-2007 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -58,6 +58,7 @@
#include "labels.h" #include "labels.h"
#include "opctable.h" #include "opctable.h"
#include "scanner.h" #include "scanner.h"
#include "segment.h"
@ -79,6 +80,99 @@ static void AddAttr (const char* Name, unsigned* Set, unsigned Attr)
static void AsmIncSection (void)
/* Parse a asminc section */
{
static const IdentTok LabelDefs[] = {
{ "COMMENTSTART", INFOTOK_COMMENTSTART },
{ "FILE", INFOTOK_FILE },
{ "IGNOREUNKNOWN", INFOTOK_IGNOREUNKNOWN },
};
/* Locals - initialize to avoid gcc warnings */
char* Name = 0;
int CommentStart = EOF;
int IgnoreUnknown = -1;
/* Skip the token */
InfoNextTok ();
/* Expect the opening curly brace */
InfoConsumeLCurly ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
/* Convert to special token */
InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
/* Look at the token */
switch (InfoTok) {
case INFOTOK_COMMENTSTART:
InfoNextTok ();
if (CommentStart != EOF) {
InfoError ("Commentstart already given");
}
InfoAssureChar ();
CommentStart = (char) InfoIVal;
InfoNextTok ();
break;
case INFOTOK_FILE:
InfoNextTok ();
if (Name) {
InfoError ("File name already given");
}
InfoAssureStr ();
if (InfoSVal[0] == '\0') {
InfoError ("File name may not be empty");
}
Name = xstrdup (InfoSVal);
InfoNextTok ();
break;
case INFOTOK_IGNOREUNKNOWN:
InfoNextTok ();
if (IgnoreUnknown != -1) {
InfoError ("Ignoreunknown already specified");
}
InfoBoolToken ();
IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
InfoNextTok ();
break;
default:
Internal ("Unexpected token: %u", InfoTok);
}
/* Directive is followed by a semicolon */
InfoConsumeSemi ();
}
/* Check for the necessary data and assume defaults */
if (Name == 0) {
InfoError ("File name is missing");
}
if (CommentStart == EOF) {
CommentStart = ';';
}
if (IgnoreUnknown == -1) {
IgnoreUnknown = 0;
}
/* Open the file and read the symbol definitions */
AsmInc (Name, CommentStart, IgnoreUnknown);
/* Delete the dynamically allocated memory for Name */
xfree (Name);
/* Consume the closing brace */
InfoConsumeRCurly ();
}
static void GlobalSection (void) static void GlobalSection (void)
/* Parse a global section */ /* Parse a global section */
{ {
@ -256,6 +350,134 @@ static void GlobalSection (void)
static void LabelSection (void)
/* Parse a label section */
{
static const IdentTok LabelDefs[] = {
{ "COMMENT", INFOTOK_COMMENT },
{ "ADDR", INFOTOK_ADDR },
{ "NAME", INFOTOK_NAME },
{ "SIZE", INFOTOK_SIZE },
};
/* Locals - initialize to avoid gcc warnings */
char* Name = 0;
char* Comment = 0;
long Value = -1;
long Size = -1;
/* Skip the token */
InfoNextTok ();
/* Expect the opening curly brace */
InfoConsumeLCurly ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
/* Convert to special token */
InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute");
/* Look at the token */
switch (InfoTok) {
case INFOTOK_ADDR:
InfoNextTok ();
if (Value >= 0) {
InfoError ("Value already given");
}
InfoAssureInt ();
InfoRangeCheck (0, 0xFFFF);
Value = InfoIVal;
InfoNextTok ();
break;
case INFOTOK_COMMENT:
InfoNextTok ();
if (Comment) {
InfoError ("Comment already given");
}
InfoAssureStr ();
if (InfoSVal[0] == '\0') {
InfoError ("Comment may not be empty");
}
Comment = xstrdup (InfoSVal);
InfoNextTok ();
break;
case INFOTOK_NAME:
InfoNextTok ();
if (Name) {
InfoError ("Name already given");
}
InfoAssureStr ();
Name = xstrdup (InfoSVal);
InfoNextTok ();
break;
case INFOTOK_SIZE:
InfoNextTok ();
if (Size >= 0) {
InfoError ("Size already given");
}
InfoAssureInt ();
InfoRangeCheck (1, 0x10000);
Size = InfoIVal;
InfoNextTok ();
break;
default:
Internal ("Unexpected token: %u", InfoTok);
}
/* Directive is followed by a semicolon */
InfoConsumeSemi ();
}
/* Did we get the necessary data */
if (Name == 0) {
InfoError ("Label name is missing");
}
if (Name[0] == '\0' && Size > 1) {
InfoError ("Unnamed labels must not have a size > 1");
}
if (Value < 0) {
InfoError ("Label value is missing");
}
if (Size < 0) {
/* Use default */
Size = 1;
}
if (Value + Size > 0x10000) {
InfoError ("Invalid size (address out of range)");
}
if (HaveLabel ((unsigned) Value)) {
InfoError ("Label for address $%04lX already defined", Value);
}
/* Define the label(s) */
if (Name[0] == '\0') {
/* Size has already beed checked */
AddUnnamedLabel (Value);
} else {
AddExtLabelRange ((unsigned) Value, Name, Size);
}
/* Define the comment */
if (Comment) {
SetComment (Value, Comment);
}
/* Delete the dynamically allocated memory for Name and Comment */
xfree (Name);
xfree (Comment);
/* Consume the closing brace */
InfoConsumeRCurly ();
}
static void RangeSection (void) static void RangeSection (void)
/* Parse a range section */ /* Parse a range section */
{ {
@ -311,7 +533,7 @@ static void RangeSection (void)
while (InfoTok != INFOTOK_RCURLY) { while (InfoTok != INFOTOK_RCURLY) {
/* Convert to special token */ /* Convert to special token */
InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive"); InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute");
/* Look at the token */ /* Look at the token */
switch (InfoTok) { switch (InfoTok) {
@ -425,21 +647,19 @@ static void RangeSection (void)
static void LabelSection (void) static void SegmentSection (void)
/* Parse a label section */ /* Parse a segment section */
{ {
static const IdentTok LabelDefs[] = { static const IdentTok LabelDefs[] = {
{ "COMMENT", INFOTOK_COMMENT }, { "END", INFOTOK_END },
{ "ADDR", INFOTOK_ADDR },
{ "NAME", INFOTOK_NAME }, { "NAME", INFOTOK_NAME },
{ "SIZE", INFOTOK_SIZE }, { "START", INFOTOK_START },
}; };
/* Locals - initialize to avoid gcc warnings */ /* Locals - initialize to avoid gcc warnings */
char* Name = 0; long End = -1;
char* Comment = 0; long Start = -1;
long Value = -1; char* Name = 0;
long Size = -1;
/* Skip the token */ /* Skip the token */
InfoNextTok (); InfoNextTok ();
@ -450,34 +670,21 @@ static void LabelSection (void)
/* Look for section tokens */ /* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) { while (InfoTok != INFOTOK_RCURLY) {
/* Convert to special token */ /* Convert to special token */
InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive"); InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute");
/* Look at the token */ /* Look at the token */
switch (InfoTok) { switch (InfoTok) {
case INFOTOK_ADDR: case INFOTOK_END:
InfoNextTok (); InfoNextTok ();
if (Value >= 0) { if (End >= 0) {
InfoError ("Value already given"); InfoError ("Value already given");
} }
InfoAssureInt (); InfoAssureInt ();
InfoRangeCheck (0, 0xFFFF); InfoRangeCheck (0, 0xFFFF);
Value = InfoIVal; End = InfoIVal;
InfoNextTok (); InfoNextTok ();
break;
case INFOTOK_COMMENT:
InfoNextTok ();
if (Comment) {
InfoError ("Comment already given");
}
InfoAssureStr ();
if (InfoSVal[0] == '\0') {
InfoError ("Comment may not be empty");
}
Comment = xstrdup (InfoSVal);
InfoNextTok ();
break; break;
case INFOTOK_NAME: case INFOTOK_NAME:
@ -490,16 +697,16 @@ static void LabelSection (void)
InfoNextTok (); InfoNextTok ();
break; break;
case INFOTOK_SIZE: case INFOTOK_START:
InfoNextTok (); InfoNextTok ();
if (Size >= 0) { if (Start >= 0) {
InfoError ("Size already given"); InfoError ("Value already given");
} }
InfoAssureInt (); InfoAssureInt ();
InfoRangeCheck (1, 0x10000); InfoRangeCheck (0, 0xFFFF);
Size = InfoIVal; Start = InfoIVal;
InfoNextTok (); InfoNextTok ();
break; break;
default: default:
Internal ("Unexpected token: %u", InfoTok); Internal ("Unexpected token: %u", InfoTok);
@ -509,133 +716,30 @@ static void LabelSection (void)
InfoConsumeSemi (); InfoConsumeSemi ();
} }
/* Did we get the necessary data */ /* Did we get the necessary data, and is it correct? */
if (Name == 0) { if (Name == 0 || Name[0] == '\0') {
InfoError ("Label name is missing"); InfoError ("Segment name is missing");
} }
if (Name[0] == '\0' && Size > 1) { if (End < 0) {
InfoError ("Unnamed labels must not have a size > 1"); InfoError ("End address is missing");
} }
if (Value < 0) { if (Start < 0) {
InfoError ("Label value is missing"); InfoError ("Start address is missing");
} }
if (Size < 0) { if (Start == End) {
/* Use default */ InfoError ("Segment is empty");
Size = 1;
} }
if (Value + Size > 0x10000) { if (Start > End) {
InfoError ("Invalid size (address out of range)"); InfoError ("Start address of segment is greater than end address");
}
if (HaveLabel ((unsigned) Value)) {
InfoError ("Label for address $%04lX already defined", Value);
} }
/* Define the label(s) */ /* Check that segments do not overlap */
if (Name[0] == '\0') { if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
/* Size has already beed checked */ InfoError ("Segments cannot overlap");
AddUnnamedLabel (Value);
} else {
AddExtLabelRange ((unsigned) Value, Name, Size);
} }
/* Define the comment */ /* Remember the segment data */
if (Comment) { AddAbsSegment ((unsigned) Start, (unsigned) End, Name);
SetComment (Value, Comment);
}
/* Delete the dynamically allocated memory for Name and Comment */
xfree (Name);
xfree (Comment);
/* Consume the closing brace */
InfoConsumeRCurly ();
}
static void AsmIncSection (void)
/* Parse a asminc section */
{
static const IdentTok LabelDefs[] = {
{ "COMMENTSTART", INFOTOK_COMMENTSTART },
{ "FILE", INFOTOK_FILE },
{ "IGNOREUNKNOWN", INFOTOK_IGNOREUNKNOWN },
};
/* Locals - initialize to avoid gcc warnings */
char* Name = 0;
int CommentStart = EOF;
int IgnoreUnknown = -1;
/* Skip the token */
InfoNextTok ();
/* Expect the opening curly brace */
InfoConsumeLCurly ();
/* Look for section tokens */
while (InfoTok != INFOTOK_RCURLY) {
/* Convert to special token */
InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
/* Look at the token */
switch (InfoTok) {
case INFOTOK_COMMENTSTART:
InfoNextTok ();
if (CommentStart != EOF) {
InfoError ("Commentstart already given");
}
InfoAssureChar ();
CommentStart = (char) InfoIVal;
InfoNextTok ();
break;
case INFOTOK_FILE:
InfoNextTok ();
if (Name) {
InfoError ("File name already given");
}
InfoAssureStr ();
if (InfoSVal[0] == '\0') {
InfoError ("File name may not be empty");
}
Name = xstrdup (InfoSVal);
InfoNextTok ();
break;
case INFOTOK_IGNOREUNKNOWN:
InfoNextTok ();
if (IgnoreUnknown != -1) {
InfoError ("Ignoreunknown already specified");
}
InfoBoolToken ();
IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
InfoNextTok ();
break;
default:
Internal ("Unexpected token: %u", InfoTok);
}
/* Directive is followed by a semicolon */
InfoConsumeSemi ();
}
/* Check for the necessary data and assume defaults */
if (Name == 0) {
InfoError ("File name is missing");
}
if (CommentStart == EOF) {
CommentStart = ';';
}
if (IgnoreUnknown == -1) {
IgnoreUnknown = 0;
}
/* Open the file and read the symbol definitions */
AsmInc (Name, CommentStart, IgnoreUnknown);
/* Delete the dynamically allocated memory for Name */ /* Delete the dynamically allocated memory for Name */
xfree (Name); xfree (Name);
@ -650,10 +754,11 @@ static void InfoParse (void)
/* Parse the config file */ /* Parse the config file */
{ {
static const IdentTok Globals[] = { static const IdentTok Globals[] = {
{ "GLOBAL", INFOTOK_GLOBAL },
{ "RANGE", INFOTOK_RANGE },
{ "LABEL", INFOTOK_LABEL },
{ "ASMINC", INFOTOK_ASMINC }, { "ASMINC", INFOTOK_ASMINC },
{ "GLOBAL", INFOTOK_GLOBAL },
{ "LABEL", INFOTOK_LABEL },
{ "RANGE", INFOTOK_RANGE },
{ "SEGMENT", INFOTOK_SEGMENT },
}; };
while (InfoTok != INFOTOK_EOF) { while (InfoTok != INFOTOK_EOF) {
@ -664,20 +769,24 @@ static void InfoParse (void)
/* Check the token */ /* Check the token */
switch (InfoTok) { switch (InfoTok) {
case INFOTOK_ASMINC:
AsmIncSection ();
break;
case INFOTOK_GLOBAL: case INFOTOK_GLOBAL:
GlobalSection (); GlobalSection ();
break; break;
case INFOTOK_RANGE:
RangeSection ();
break;
case INFOTOK_LABEL: case INFOTOK_LABEL:
LabelSection (); LabelSection ();
break; break;
case INFOTOK_ASMINC: case INFOTOK_RANGE:
AsmIncSection (); RangeSection ();
break;
case INFOTOK_SEGMENT:
SegmentSection ();
break; break;
default: default:

View File

@ -1,4 +1,4 @@
# #
# gcc Makefile for da65 # gcc Makefile for da65
# #
@ -27,7 +27,8 @@ OBJS = asminc.o \
opc65sc02.o \ opc65sc02.o \
opctable.o \ opctable.o \
output.o \ output.o \
scanner.o scanner.o \
segment.o
LIBS = $(COMMON)/common.a LIBS = $(COMMON)/common.a

View File

@ -77,7 +77,8 @@ OBJS = asminc.obj \
opc65sc02.obj \ opc65sc02.obj \
opctable.obj \ opctable.obj \
output.obj \ output.obj \
scanner.obj scanner.obj \
segment.obj
LIBS = ../common/common.lib LIBS = ../common/common.lib

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2006 Ullrich von Bassewitz */ /* (C) 2000-2007 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -65,6 +65,7 @@ typedef enum token_t {
INFOTOK_RANGE, INFOTOK_RANGE,
INFOTOK_LABEL, INFOTOK_LABEL,
INFOTOK_ASMINC, INFOTOK_ASMINC,
INFOTOK_SEGMENT,
/* Global section */ /* Global section */
INFOTOK_ARGUMENT_COLUMN, INFOTOK_ARGUMENT_COLUMN,
@ -75,11 +76,11 @@ typedef enum token_t {
INFOTOK_INPUTNAME, INFOTOK_INPUTNAME,
INFOTOK_INPUTOFFS, INFOTOK_INPUTOFFS,
INFOTOK_INPUTSIZE, INFOTOK_INPUTSIZE,
INFOTOK_LABELBREAK, INFOTOK_LABELBREAK,
INFOTOK_MNEMONIC_COLUMN, INFOTOK_MNEMONIC_COLUMN,
INFOTOK_OUTPUTNAME, INFOTOK_OUTPUTNAME,
INFOTOK_PAGELENGTH, INFOTOK_PAGELENGTH,
INFOTOK_STARTADDR, INFOTOK_STARTADDR,
INFOTOK_TEXT_COLUMN, INFOTOK_TEXT_COLUMN,
/* Range section */ /* Range section */

109
src/da65/segment.c Normal file
View File

@ -0,0 +1,109 @@
/*****************************************************************************/
/* */
/* segment.c */
/* */
/* Segment handling for da65 */
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <string.h>
/* common */
#include "addrsize.h"
#include "xmalloc.h"
/* da65 */
#include "attrtab.h"
#include "segment.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Hash definitions */
#define HASH_SIZE 64 /* Must be power of two */
#define HASH_MASK (HASH_SIZE-1)
/* Segment definition */
typedef struct Segment Segment;
struct Segment {
Segment* NextStart; /* Pointer to next segment */
Segment* NextEnd; /* Pointer to next segment */
unsigned long Start;
unsigned long End;
unsigned AddrSize;
char Name[1]; /* Name, dynamically allocated */
};
/* Tables containing the segments. A segment is inserted using it's hash
* value. Collision is done by single linked lists.
*/
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddAbsSegment (unsigned Start, unsigned End, const char* Name)
/* Add an absolute segment to the segment table */
{
/* Get the length of the name */
unsigned Len = strlen (Name);
/* Create a new segment */
Segment* S = xmalloc (sizeof (Segment) + Len);
/* Fill in the data */
S->Start = Start;
S->End = End;
S->AddrSize = ADDR_SIZE_ABS;
memcpy (S->Name, Name, Len + 1);
/* Insert the segment into the hash tables */
S->NextStart = StartTab[Start & HASH_MASK];
StartTab[Start & HASH_MASK] = S;
S->NextEnd = EndTab[End & HASH_MASK];
EndTab[End & HASH_MASK] = S;
/* Mark the addresses within the segment */
MarkRange (Start, End, atSegment);
}

57
src/da65/segment.h Normal file
View File

@ -0,0 +1,57 @@
/*****************************************************************************/
/* */
/* segment.h */
/* */
/* Segment handling for da65 */
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef SEGMENT_H
#define SEGMENT_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void AddAbsSegment (unsigned Start, unsigned End, const char* Name);
/* Add an absolute segment to the segment table */
/* End of segment.h */
#endif