1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-28 06:30:16 +00:00

Fixed a bug in the handling of ranges where the granularity is not one: An

internally generated label could disrupt the output of such a range by
adding an offset not equal to the granularity. The solution is to only
add dependent labels within such a range on all addresses that do not
match the granularity (odd addresses for a .word table for example).


git-svn-id: svn://svn.cc65.org/cc65/trunk@3002 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2004-04-29 14:00:28 +00:00
parent 3ccd9f97c7
commit 1ae117fed8
5 changed files with 191 additions and 53 deletions

View File

@ -79,6 +79,30 @@ static void AddrCheck (unsigned Addr)
unsigned GetGranularity (attr_t Style)
/* Get the granularity for the given style */
{
switch (Style) {
case atDefault: return 1;
case atCode: return 1;
case atIllegal: return 1;
case atByteTab: return 1;
case atDByteTab: return 2;
case atWordTab: return 2;
case atDWordTab: return 4;
case atAddrTab: return 2;
case atRtsTab: return 2;
case atTextTab: return 1;
case atSkip:
default:
Internal ("GetGraularity called for style = %d", Style);
return 0;
}
}
void MarkRange (unsigned Start, unsigned End, attr_t Attr) void MarkRange (unsigned Start, unsigned End, attr_t Attr)
/* Mark a range with the given attribute */ /* Mark a range with the given attribute */
{ {
@ -129,11 +153,11 @@ void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
/* Must not have two symbols for one address */ /* Must not have two symbols for one address */
if (ExistingAttr != atNoLabel) { if (ExistingAttr != atNoLabel) {
/* Allow redefinition if identical */ /* Allow redefinition if identical */
if (ExistingAttr == Attr && strcmp (SymTab[Addr], Name) == 0) { if (ExistingAttr == Attr && strcmp (SymTab[Addr], Name) == 0) {
return; return;
} }
Error ("Duplicate label for address %04X: %s/%s", Addr, SymTab[Addr], Name); Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name);
} }
/* Create a new label */ /* Create a new label */
@ -145,39 +169,86 @@ void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs)
/* Add a dependent label at the given address using "base name+Offs" as the new
* name.
*/
{
/* Allocate memory for the dependent label name */
unsigned NameLen = strlen (BaseName);
char* DepName = xmalloc (NameLen + 7); /* "+$ABCD" */
/* Create the new name in the buffer */
if (UseHexOffs) {
sprintf (DepName, "%s+$%02X", BaseName, Offs);
} else {
sprintf (DepName, "%s+%u", BaseName, Offs);
}
/* Define the labels */
AddLabel (Addr, Attr | atDepLabel, DepName);
/* Free the name buffer */
xfree (DepName);
}
static void AddLabelRange (unsigned Addr, attr_t Attr, const char* Name, unsigned Count)
/* Add a label for a range. The first entry gets the label "Name" while the
* others get "Name+offs".
*/
{
/* Define the label */
AddLabel (Addr, Attr, Name);
/* Define dependent labels if necessary */
if (Count > 1) {
unsigned Offs;
/* Setup the format string */
const char* Format = UseHexOffs? "$%02X" : "%u";
/* Allocate memory for the dependent label names */
unsigned NameLen = strlen (Name);
char* DepName = xmalloc (NameLen + 7); /* "+$ABCD" */
char* DepOffs = DepName + NameLen + 1;
/* Copy the original name into the buffer */
memcpy (DepName, Name, NameLen);
DepName[NameLen] = '+';
/* Define the labels */
for (Offs = 1; Offs < Count; ++Offs) {
sprintf (DepOffs, Format, Offs);
AddLabel (Addr + Offs, Attr | atDepLabel, DepName);
}
/* Free the name buffer */
xfree (DepName);
}
}
void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count)
/* Add an internal label for a range. The first entry gets the label "Name"
* while the others get "Name+offs".
*/
{
/* Define the label range */
AddLabelRange (Addr, atIntLabel, Name, Count);
}
void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count) void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
/* Add an external label for a range. The first entry gets the label "Name" /* Add an external label for a range. The first entry gets the label "Name"
* while the others get "Name+offs". * while the others get "Name+offs".
*/ */
{ {
/* Define the label */ /* Define the label range */
AddLabel (Addr, atExtLabel, Name); AddLabelRange (Addr, atExtLabel, Name, Count);
/* Define dependent labels if necessary */
if (Count > 1) {
unsigned Offs;
/* Setup the format string */
const char* Format = UseHexOffs? "$%02X" : "%u";
/* Allocate memory for the dependent label names */
unsigned NameLen = strlen (Name);
char* DepName = xmalloc (NameLen + 7);
char* DepOffs = DepName + NameLen + 1;
/* Copy the original name into the buffer */
memcpy (DepName, Name, NameLen);
DepName[NameLen] = '+';
/* Define the labels */
for (Offs = 1; Offs < Count; ++Offs) {
sprintf (DepOffs, Format, Offs);
AddLabel (Addr + Offs, atDepLabel, DepName);
}
/* Free the name buffer */
xfree (DepName);
}
} }
@ -267,7 +338,7 @@ void DefOutOfRangeLabels (void)
while (Addr < CodeStart) { while (Addr < CodeStart) {
if (MustDefLabel (Addr)) { if (MustDefLabel (Addr)) {
DefineConst (Addr); DefineConst (Addr);
} }
++Addr; ++Addr;
} }

View File

@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Römerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@ -63,10 +63,10 @@ typedef enum attr_t {
atNoLabel = 0x00, /* No label for this address */ atNoLabel = 0x00, /* No label for this address */
atExtLabel = 0x10, /* External label */ atExtLabel = 0x10, /* External label */
atIntLabel = 0x20, /* Internally generated label */ atIntLabel = 0x20, /* Internally generated label */
atDepLabel = 0x30, /* Dependent label (always extern) */ atDepLabel = 0x40, /* Dependent label */
atStyleMask = 0x0F, /* Output style */ atStyleMask = 0x0F, /* Output style */
atLabelMask = 0x30 /* Label information */ atLabelMask = 0x70 /* Label information */
} attr_t; } attr_t;
@ -77,6 +77,9 @@ typedef enum attr_t {
unsigned GetGranularity (attr_t Style);
/* Get the granularity for the given style */
void MarkRange (unsigned Start, unsigned End, attr_t Attr); void MarkRange (unsigned Start, unsigned End, attr_t Attr);
/* Mark a range with the given attribute */ /* Mark a range with the given attribute */
@ -91,6 +94,16 @@ const char* MakeLabelName (unsigned Addr);
void AddLabel (unsigned Addr, attr_t Attr, const char* Name); void AddLabel (unsigned Addr, attr_t Attr, const char* Name);
/* Add a label */ /* Add a label */
void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs);
/* Add a dependent label at the given address using "base name+Offs" as the new
* name.
*/
void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count);
/* Add an internal label for a range. The first entry gets the label "Name"
* while the others get "Name+offs".
*/
void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count); void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count);
/* Add an external label for a range. The first entry gets the label "Name" /* Add an external label for a range. The first entry gets the label "Name"
* while the others get "Name+offs". * while the others get "Name+offs".

View File

@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Römerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@ -189,7 +189,7 @@ unsigned AddrTable (void)
const char* Label = GetLabel (Addr); const char* Label = GetLabel (Addr);
if (Label == 0) { if (Label == 0) {
/* OOPS! Should not happen */ /* OOPS! Should not happen */
Internal ("OOPS - Label for address %04X disappeard!", Addr); Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
} }
Indent (MIndent); Indent (MIndent);
Output (".addr"); Output (".addr");
@ -249,7 +249,7 @@ unsigned RtsTable (void)
const char* Label = GetLabel (Addr); const char* Label = GetLabel (Addr);
if (Label == 0) { if (Label == 0) {
/* OOPS! Should not happen */ /* OOPS! Should not happen */
Internal ("OOPS - Label for address %04X disappeard!", Addr); Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
} }
Indent (MIndent); Indent (MIndent);
Output (".word"); Output (".word");

View File

@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Römerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@ -129,10 +129,57 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
static void GenerateLabel (unsigned Flags, unsigned Addr) static void GenerateLabel (unsigned Flags, unsigned Addr)
/* Generate a label in pass one if requested */ /* Generate a label in pass one if requested */
{ {
if (Pass == 1 && !HaveLabel (Addr)) { /* Generate labels in pass #1, and only if we don't have a label already */
if ((Flags & flGenLabel) != 0 || if (Pass == 1 && !HaveLabel (Addr) &&
((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd)) { /* Check if we must create a label */
((Flags & flGenLabel) != 0 ||
((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
/* As a special case, handle ranges with tables or similar. Within
* such a range with a granularity > 1, do only generate dependent
* labels for all addresses but the first one. Be sure to generate
* a label for the start of the range, however.
*/
attr_t Style = GetStyleAttr (Addr);
unsigned Granularity = GetGranularity (Style);
if (Granularity == 1) {
/* Just add the label */
AddLabel (Addr, atIntLabel, MakeLabelName (Addr)); AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
} else {
/* Search for the start of the range or the last non dependent
* label in the range.
*/
unsigned Offs;
attr_t LabelAttr;
unsigned LabelAddr = Addr;
while (LabelAddr > CodeStart) {
if (Style != GetStyleAttr (LabelAddr-1)) {
/* End of range reached */
break;
}
--LabelAddr;
LabelAttr = GetLabelAttr (LabelAddr);
if ((LabelAttr & (atIntLabel|atExtLabel)) != 0 &&
(LabelAttr & atDepLabel) == 0) {
/* The address has an internal or external label */
break;
}
}
/* If the proposed label address doesn't have a label, define one */
if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
AddLabel (LabelAddr, atIntLabel, MakeLabelName (LabelAddr));
}
/* Create the label */
Offs = Addr - LabelAddr;
if (Offs == 0) {
AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
} else {
AddDepLabel (Addr, atIntLabel, GetLabel (LabelAddr), Offs);
}
} }
} }
} }

View File

@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Römerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@ -239,6 +239,8 @@ static void RangeSection (void)
unsigned End = 0; unsigned End = 0;
unsigned char Type = 0; unsigned char Type = 0;
char* Name = 0; char* Name = 0;
unsigned MemberSize = 0;
/* Skip the token */ /* Skip the token */
InfoNextTok (); InfoNextTok ();
@ -290,15 +292,15 @@ static void RangeSection (void)
InfoNextTok (); InfoNextTok ();
InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE"); InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
switch (InfoTok) { switch (InfoTok) {
case INFOTOK_ADDRTAB: Type = atAddrTab; break; case INFOTOK_ADDRTAB: Type = atAddrTab; MemberSize = 2; break;
case INFOTOK_BYTETAB: Type = atByteTab; break; case INFOTOK_BYTETAB: Type = atByteTab; MemberSize = 1; break;
case INFOTOK_CODE: Type = atCode; break; case INFOTOK_CODE: Type = atCode; MemberSize = 1; break;
case INFOTOK_DBYTETAB: Type = atDByteTab; break; case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
case INFOTOK_DWORDTAB: Type = atDWordTab; break; case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
case INFOTOK_RTSTAB: Type = atRtsTab; break; case INFOTOK_RTSTAB: Type = atRtsTab; MemberSize = 2; break;
case INFOTOK_SKIP: Type = atSkip; break; case INFOTOK_SKIP: Type = atSkip; MemberSize = 1; break;
case INFOTOK_TEXTTAB: Type = atTextTab; break; case INFOTOK_TEXTTAB: Type = atTextTab; MemberSize = 1; break;
case INFOTOK_WORDTAB: Type = atWordTab; break; case INFOTOK_WORDTAB: Type = atWordTab; MemberSize = 2; break;
} }
InfoNextTok (); InfoNextTok ();
break; break;
@ -319,6 +321,11 @@ static void RangeSection (void)
InfoError ("Start value must not be greater than end value"); InfoError ("Start value must not be greater than end value");
} }
/* Check the granularity */
if (((End - Start + 1) % MemberSize) != 0) {
InfoError ("Type of range needs a granularity of %u", MemberSize);
}
/* Set the range */ /* Set the range */
MarkRange (Start, End, Type); MarkRange (Start, End, Type);