From: cuz Date: Fri, 31 Aug 2007 20:27:53 +0000 (+0000) Subject: Started to add support for segments. X-Git-Tag: V2.12.0~52 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8db6dcd414e3e679ddf2427e966ca3baae6f1957;p=cc65 Started to add support for segments. git-svn-id: svn://svn.cc65.org/cc65/trunk@3805 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/da65/attrtab.c b/src/da65/attrtab.c index 073834ad9..277ee8b0e 100644 --- a/src/da65/attrtab.c +++ b/src/da65/attrtab.c @@ -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) /* Get the granularity for the given style */ { diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index 2abe26576..23413abed 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -69,7 +69,10 @@ typedef enum attr_t { atLabelDefined = 0x0100, /* True if we defined the label */ atStyleMask = 0x000F, /* Output style */ - atLabelMask = 0x00F0 /* Label information */ + atLabelMask = 0x00F0, /* Label information */ + + /* Segment */ + atSegment = 0x0100, /* Code is in a segment */ } attr_t; @@ -83,6 +86,9 @@ typedef enum attr_t { void AddrCheck (unsigned Addr); /* 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); /* Get the granularity for the given style */ diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 3491f15bd..4a96f700d 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2000-2005 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 2000-2007 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -58,6 +58,7 @@ #include "labels.h" #include "opctable.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) /* 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) /* Parse a range section */ { @@ -311,7 +533,7 @@ static void RangeSection (void) while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ - InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive"); + InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute"); /* Look at the token */ switch (InfoTok) { @@ -425,21 +647,19 @@ static void RangeSection (void) -static void LabelSection (void) -/* Parse a label section */ +static void SegmentSection (void) +/* Parse a segment section */ { static const IdentTok LabelDefs[] = { - { "COMMENT", INFOTOK_COMMENT }, - { "ADDR", INFOTOK_ADDR }, + { "END", INFOTOK_END }, { "NAME", INFOTOK_NAME }, - { "SIZE", INFOTOK_SIZE }, + { "START", INFOTOK_START }, }; /* Locals - initialize to avoid gcc warnings */ - char* Name = 0; - char* Comment = 0; - long Value = -1; - long Size = -1; + long End = -1; + long Start = -1; + char* Name = 0; /* Skip the token */ InfoNextTok (); @@ -450,34 +670,21 @@ static void LabelSection (void) /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { - /* Convert to special token */ - InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive"); + /* Convert to special token */ + InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute"); - /* Look at the token */ - switch (InfoTok) { + /* Look at the token */ + switch (InfoTok) { - case INFOTOK_ADDR: - InfoNextTok (); - if (Value >= 0) { - InfoError ("Value already given"); - } + case INFOTOK_END: + InfoNextTok (); + if (End >= 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 (); + InfoRangeCheck (0, 0xFFFF); + End = InfoIVal; + InfoNextTok (); break; case INFOTOK_NAME: @@ -490,16 +697,16 @@ static void LabelSection (void) InfoNextTok (); break; - case INFOTOK_SIZE: - InfoNextTok (); - if (Size >= 0) { - InfoError ("Size already given"); - } - InfoAssureInt (); - InfoRangeCheck (1, 0x10000); - Size = InfoIVal; - InfoNextTok (); - break; + case INFOTOK_START: + InfoNextTok (); + if (Start >= 0) { + InfoError ("Value already given"); + } + InfoAssureInt (); + InfoRangeCheck (0, 0xFFFF); + Start = InfoIVal; + InfoNextTok (); + break; default: Internal ("Unexpected token: %u", InfoTok); @@ -509,133 +716,30 @@ static void LabelSection (void) 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; + /* Did we get the necessary data, and is it correct? */ + if (Name == 0 || Name[0] == '\0') { + InfoError ("Segment name is missing"); } - if (Value + Size > 0x10000) { - InfoError ("Invalid size (address out of range)"); + if (End < 0) { + InfoError ("End address is missing"); } - if (HaveLabel ((unsigned) Value)) { - InfoError ("Label for address $%04lX already defined", Value); + if (Start < 0) { + InfoError ("Start address is missing"); } - - /* Define the label(s) */ - if (Name[0] == '\0') { - /* Size has already beed checked */ - AddUnnamedLabel (Value); - } else { - AddExtLabelRange ((unsigned) Value, Name, Size); + if (Start == End) { + InfoError ("Segment is empty"); } - - /* 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 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 (); + if (Start > End) { + InfoError ("Start address of segment is greater than end address"); } - /* 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; + /* Check that segments do not overlap */ + if (SegmentDefined ((unsigned) Start, (unsigned) End)) { + InfoError ("Segments cannot overlap"); } - /* Open the file and read the symbol definitions */ - AsmInc (Name, CommentStart, IgnoreUnknown); + /* Remember the segment data */ + AddAbsSegment ((unsigned) Start, (unsigned) End, Name); /* Delete the dynamically allocated memory for Name */ xfree (Name); @@ -650,10 +754,11 @@ static void InfoParse (void) /* Parse the config file */ { static const IdentTok Globals[] = { + { "ASMINC", INFOTOK_ASMINC }, { "GLOBAL", INFOTOK_GLOBAL }, - { "RANGE", INFOTOK_RANGE }, { "LABEL", INFOTOK_LABEL }, - { "ASMINC", INFOTOK_ASMINC }, + { "RANGE", INFOTOK_RANGE }, + { "SEGMENT", INFOTOK_SEGMENT }, }; while (InfoTok != INFOTOK_EOF) { @@ -664,20 +769,24 @@ static void InfoParse (void) /* Check the token */ switch (InfoTok) { + case INFOTOK_ASMINC: + AsmIncSection (); + break; + case INFOTOK_GLOBAL: GlobalSection (); break; - case INFOTOK_RANGE: - RangeSection (); - break; - case INFOTOK_LABEL: LabelSection (); break; - case INFOTOK_ASMINC: - AsmIncSection (); + case INFOTOK_RANGE: + RangeSection (); + break; + + case INFOTOK_SEGMENT: + SegmentSection (); break; default: diff --git a/src/da65/make/gcc.mak b/src/da65/make/gcc.mak index 19cb66818..7932d0e6c 100644 --- a/src/da65/make/gcc.mak +++ b/src/da65/make/gcc.mak @@ -1,4 +1,4 @@ -# +# # gcc Makefile for da65 # @@ -27,7 +27,8 @@ OBJS = asminc.o \ opc65sc02.o \ opctable.o \ output.o \ - scanner.o + scanner.o \ + segment.o LIBS = $(COMMON)/common.a diff --git a/src/da65/make/watcom.mak b/src/da65/make/watcom.mak index ce2e0c3b5..8c9479209 100644 --- a/src/da65/make/watcom.mak +++ b/src/da65/make/watcom.mak @@ -77,7 +77,8 @@ OBJS = asminc.obj \ opc65sc02.obj \ opctable.obj \ output.obj \ - scanner.obj + scanner.obj \ + segment.obj LIBS = ../common/common.lib diff --git a/src/da65/scanner.h b/src/da65/scanner.h index 0c1c73ef2..4ca81774f 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2000-2006 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 2000-2007 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -65,6 +65,7 @@ typedef enum token_t { INFOTOK_RANGE, INFOTOK_LABEL, INFOTOK_ASMINC, + INFOTOK_SEGMENT, /* Global section */ INFOTOK_ARGUMENT_COLUMN, @@ -75,11 +76,11 @@ typedef enum token_t { INFOTOK_INPUTNAME, INFOTOK_INPUTOFFS, INFOTOK_INPUTSIZE, - INFOTOK_LABELBREAK, + INFOTOK_LABELBREAK, INFOTOK_MNEMONIC_COLUMN, INFOTOK_OUTPUTNAME, INFOTOK_PAGELENGTH, - INFOTOK_STARTADDR, + INFOTOK_STARTADDR, INFOTOK_TEXT_COLUMN, /* Range section */ diff --git a/src/da65/segment.c b/src/da65/segment.c new file mode 100644 index 000000000..e648a3618 --- /dev/null +++ b/src/da65/segment.c @@ -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 + +/* 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); +} + + + diff --git a/src/da65/segment.h b/src/da65/segment.h new file mode 100644 index 000000000..a27720bee --- /dev/null +++ b/src/da65/segment.h @@ -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 + + +