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:
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)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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".
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user