mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 15:29:46 +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:
parent
3ccd9f97c7
commit
1ae117fed8
@ -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)
|
||||
/* 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 */
|
||||
if (ExistingAttr != atNoLabel) {
|
||||
/* Allow redefinition if identical */
|
||||
/* Allow redefinition if identical */
|
||||
if (ExistingAttr == Attr && strcmp (SymTab[Addr], Name) == 0) {
|
||||
return;
|
||||
}
|
||||
Error ("Duplicate label for address %04X: %s/%s", Addr, SymTab[Addr], Name);
|
||||
return;
|
||||
}
|
||||
Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
/* Add an external label for a range. The first entry gets the label "Name"
|
||||
* while the others get "Name+offs".
|
||||
*/
|
||||
{
|
||||
/* Define the label */
|
||||
AddLabel (Addr, atExtLabel, 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);
|
||||
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);
|
||||
}
|
||||
/* Define the label range */
|
||||
AddLabelRange (Addr, atExtLabel, Name, Count);
|
||||
}
|
||||
|
||||
|
||||
@ -267,7 +338,7 @@ void DefOutOfRangeLabels (void)
|
||||
while (Addr < CodeStart) {
|
||||
if (MustDefLabel (Addr)) {
|
||||
DefineConst (Addr);
|
||||
}
|
||||
}
|
||||
++Addr;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -63,10 +63,10 @@ typedef enum attr_t {
|
||||
atNoLabel = 0x00, /* No label for this address */
|
||||
atExtLabel = 0x10, /* External label */
|
||||
atIntLabel = 0x20, /* Internally generated label */
|
||||
atDepLabel = 0x30, /* Dependent label (always extern) */
|
||||
atDepLabel = 0x40, /* Dependent label */
|
||||
|
||||
atStyleMask = 0x0F, /* Output style */
|
||||
atLabelMask = 0x30 /* Label information */
|
||||
atLabelMask = 0x70 /* Label information */
|
||||
} 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);
|
||||
/* 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);
|
||||
/* 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);
|
||||
/* Add an external label for a range. The first entry gets the label "Name"
|
||||
* while the others get "Name+offs".
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -189,7 +189,7 @@ unsigned AddrTable (void)
|
||||
const char* Label = GetLabel (Addr);
|
||||
if (Label == 0) {
|
||||
/* OOPS! Should not happen */
|
||||
Internal ("OOPS - Label for address %04X disappeard!", Addr);
|
||||
Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
|
||||
}
|
||||
Indent (MIndent);
|
||||
Output (".addr");
|
||||
@ -249,7 +249,7 @@ unsigned RtsTable (void)
|
||||
const char* Label = GetLabel (Addr);
|
||||
if (Label == 0) {
|
||||
/* OOPS! Should not happen */
|
||||
Internal ("OOPS - Label for address %04X disappeard!", Addr);
|
||||
Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
|
||||
}
|
||||
Indent (MIndent);
|
||||
Output (".word");
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -129,10 +129,57 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
|
||||
static void GenerateLabel (unsigned Flags, unsigned Addr)
|
||||
/* Generate a label in pass one if requested */
|
||||
{
|
||||
if (Pass == 1 && !HaveLabel (Addr)) {
|
||||
if ((Flags & flGenLabel) != 0 ||
|
||||
((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd)) {
|
||||
/* Generate labels in pass #1, and only if we don't have a label already */
|
||||
if (Pass == 1 && !HaveLabel (Addr) &&
|
||||
/* 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));
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -239,6 +239,8 @@ static void RangeSection (void)
|
||||
unsigned End = 0;
|
||||
unsigned char Type = 0;
|
||||
char* Name = 0;
|
||||
unsigned MemberSize = 0;
|
||||
|
||||
|
||||
/* Skip the token */
|
||||
InfoNextTok ();
|
||||
@ -290,15 +292,15 @@ static void RangeSection (void)
|
||||
InfoNextTok ();
|
||||
InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
|
||||
switch (InfoTok) {
|
||||
case INFOTOK_ADDRTAB: Type = atAddrTab; break;
|
||||
case INFOTOK_BYTETAB: Type = atByteTab; break;
|
||||
case INFOTOK_CODE: Type = atCode; break;
|
||||
case INFOTOK_DBYTETAB: Type = atDByteTab; break;
|
||||
case INFOTOK_DWORDTAB: Type = atDWordTab; break;
|
||||
case INFOTOK_RTSTAB: Type = atRtsTab; break;
|
||||
case INFOTOK_SKIP: Type = atSkip; break;
|
||||
case INFOTOK_TEXTTAB: Type = atTextTab; break;
|
||||
case INFOTOK_WORDTAB: Type = atWordTab; break;
|
||||
case INFOTOK_ADDRTAB: Type = atAddrTab; MemberSize = 2; break;
|
||||
case INFOTOK_BYTETAB: Type = atByteTab; MemberSize = 1; break;
|
||||
case INFOTOK_CODE: Type = atCode; MemberSize = 1; break;
|
||||
case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
|
||||
case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
|
||||
case INFOTOK_RTSTAB: Type = atRtsTab; MemberSize = 2; break;
|
||||
case INFOTOK_SKIP: Type = atSkip; MemberSize = 1; break;
|
||||
case INFOTOK_TEXTTAB: Type = atTextTab; MemberSize = 1; break;
|
||||
case INFOTOK_WORDTAB: Type = atWordTab; MemberSize = 2; break;
|
||||
}
|
||||
InfoNextTok ();
|
||||
break;
|
||||
@ -319,6 +321,11 @@ static void RangeSection (void)
|
||||
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 */
|
||||
MarkRange (Start, End, Type);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user