mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Added labels, SIEZ attribute for labels, dependent labels etc.
git-svn-id: svn://svn.cc65.org/cc65/trunk@343 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
c15fb9b50f
commit
97f9682307
@ -121,16 +121,16 @@ const char* MakeLabelName (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
void AddLabel (unsigned Addr, const char* Name)
|
||||
void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
|
||||
/* Add a label */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
/* Get an existing label attribute */
|
||||
attr_t ExistingAttr = GetLabelAttr (Addr);
|
||||
|
||||
/* Must not have two symbols for one address */
|
||||
if (SymTab[Addr] != 0) {
|
||||
if (strcmp (SymTab[Addr], Name) == 0) {
|
||||
/* Allow label if it has the same name */
|
||||
if (ExistingAttr != atNoLabel) {
|
||||
/* 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);
|
||||
@ -138,6 +138,9 @@ void AddLabel (unsigned Addr, const char* Name)
|
||||
|
||||
/* Create a new label */
|
||||
SymTab[Addr] = xstrdup (Name);
|
||||
|
||||
/* Remember the attribute */
|
||||
AttrTab[Addr] |= Attr;
|
||||
}
|
||||
|
||||
|
||||
@ -154,6 +157,20 @@ int HaveLabel (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
int MustDefLabel (unsigned Addr)
|
||||
/* Return true if we must define a label for this address, that is, if there
|
||||
* is a label at this address, and it is an external or internal label.
|
||||
*/
|
||||
{
|
||||
/* Get the label attribute */
|
||||
attr_t A = GetLabelAttr (Addr);
|
||||
|
||||
/* Check for an internal or external label */
|
||||
return (A == atExtLabel || A == atIntLabel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* GetLabel (unsigned Addr)
|
||||
/* Return the label for an address */
|
||||
{
|
||||
@ -166,7 +183,7 @@ const char* GetLabel (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
unsigned char GetStyle (unsigned Addr)
|
||||
unsigned char GetStyleAttr (unsigned Addr)
|
||||
/* Return the style attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
@ -178,6 +195,18 @@ unsigned char GetStyle (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
unsigned char GetLabelAttr (unsigned Addr)
|
||||
/* Return the label attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return (AttrTab[Addr] & atLabelMask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DefineConst (unsigned Addr)
|
||||
/* Define an address constant */
|
||||
{
|
||||
@ -198,14 +227,14 @@ void DefOutOfRangeLabels (void)
|
||||
|
||||
/* Low range */
|
||||
for (Addr = 0; Addr < CodeStart; ++Addr) {
|
||||
if (SymTab [Addr]) {
|
||||
if (MustDefLabel (Addr)) {
|
||||
DefineConst (Addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* High range */
|
||||
for (Addr = CodeEnd+1; Addr < 0x10000; ++Addr) {
|
||||
if (SymTab [Addr]) {
|
||||
if (MustDefLabel (Addr)) {
|
||||
DefineConst (Addr);
|
||||
}
|
||||
}
|
||||
|
@ -39,13 +39,15 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
typedef enum attr_t attr_t;
|
||||
enum attr_t {
|
||||
|
||||
/* Styles */
|
||||
atDefault = 0x00, /* Default style */
|
||||
atCode = 0x01,
|
||||
atIllegal = 0x02,
|
||||
@ -55,13 +57,20 @@ enum attr_t {
|
||||
atAddrTab = 0x06,
|
||||
atRtsTab = 0x07,
|
||||
|
||||
atStyleMask = 0x0F /* Output style */
|
||||
/* Label flags */
|
||||
atNoLabel = 0x00, /* No label for this address */
|
||||
atExtLabel = 0x10, /* External label */
|
||||
atIntLabel = 0x20, /* Internally generated label */
|
||||
atDepLabel = 0x30, /* Dependent label (always extern) */
|
||||
|
||||
atStyleMask = 0x0F, /* Output style */
|
||||
atLabelMask = 0x30 /* Label information */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -77,18 +86,26 @@ const char* MakeLabelName (unsigned Addr);
|
||||
* static buffer.
|
||||
*/
|
||||
|
||||
void AddLabel (unsigned Addr, const char* Name);
|
||||
void AddLabel (unsigned Addr, attr_t Attr, const char* Name);
|
||||
/* Add a label */
|
||||
|
||||
int HaveLabel (unsigned Addr);
|
||||
/* Check if there is a label for the given address */
|
||||
|
||||
const char* GetLabel (unsigned Addr);
|
||||
/* Return the label for an address */
|
||||
int MustDefLabel (unsigned Addr);
|
||||
/* Return true if we must define a label for this address, that is, if there
|
||||
* is a label at this address, and it is an external or internal label.
|
||||
*/
|
||||
|
||||
unsigned char GetStyle (unsigned Addr);
|
||||
const char* GetLabel (unsigned Addr);
|
||||
/* Return the label for an address or NULL if there is none */
|
||||
|
||||
unsigned char GetStyleAttr (unsigned Addr);
|
||||
/* Return the style attribute for the given address */
|
||||
|
||||
unsigned char GetLabelAttr (unsigned Addr);
|
||||
/* Return the label attribute for the given address */
|
||||
|
||||
void DefOutOfRangeLabels (void);
|
||||
/* Output any labels that are out of the loaded code range */
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft compiler */
|
||||
# include <io.h>
|
||||
@ -200,7 +201,7 @@ static void RangeSection (void)
|
||||
case CFGTOK_WORDTAB: Type = atWordTab; break;
|
||||
case CFGTOK_DWORDTAB: Type = atDWordTab; break;
|
||||
case CFGTOK_ADDRTAB: Type = atAddrTab; break;
|
||||
case CFGTOK_RTSTAB: Type = atRtsTab; break;
|
||||
case CFGTOK_RTSTAB: Type = atRtsTab; break;
|
||||
}
|
||||
Needed |= tType;
|
||||
CfgNextTok ();
|
||||
@ -214,12 +215,12 @@ static void RangeSection (void)
|
||||
|
||||
/* Did we get all required values? */
|
||||
if (Needed != tAll) {
|
||||
Error ("Required values missing from this section");
|
||||
CfgError ("Required values missing from this section");
|
||||
}
|
||||
|
||||
/* Start must be less than end */
|
||||
if (Start > End) {
|
||||
Error ("Start value must not be greater than end value");
|
||||
CfgError ("Start value must not be greater than end value");
|
||||
}
|
||||
|
||||
/* Set the range */
|
||||
@ -234,12 +235,17 @@ static void RangeSection (void)
|
||||
static void LabelSection (void)
|
||||
/* Parse a label section */
|
||||
{
|
||||
static const IdentTok Globals[] = {
|
||||
{ "INPUTNAMEL", CFGTOK_INPUTNAME },
|
||||
{ "OUTPUTNAME", CFGTOK_OUTPUTNAME },
|
||||
{ "PAGELENGTH", CFGTOK_PAGELENGTH },
|
||||
static const IdentTok LabelDefs[] = {
|
||||
{ "NAME", CFGTOK_NAME },
|
||||
{ "ADDR", CFGTOK_ADDR },
|
||||
{ "SIZE", CFGTOK_SIZE },
|
||||
};
|
||||
|
||||
/* Locals - initialize to avoid gcc warnings */
|
||||
char* Name = 0;
|
||||
long Value = -1;
|
||||
long Size = -1;
|
||||
|
||||
/* Skip the token */
|
||||
CfgNextTok ();
|
||||
|
||||
@ -249,9 +255,97 @@ static void LabelSection (void)
|
||||
/* Look for section tokens */
|
||||
while (CfgTok != CFGTOK_RCURLY) {
|
||||
|
||||
/* Convert to special token */
|
||||
CfgSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
|
||||
|
||||
/* Look at the token */
|
||||
switch (CfgTok) {
|
||||
|
||||
case CFGTOK_NAME:
|
||||
CfgNextTok ();
|
||||
if (Name) {
|
||||
CfgError ("Name already given");
|
||||
}
|
||||
CfgAssureStr ();
|
||||
if (CfgSVal[0] == '\0') {
|
||||
CfgError ("Name may not be empty");
|
||||
}
|
||||
Name = xstrdup (CfgSVal);
|
||||
CfgNextTok ();
|
||||
break;
|
||||
|
||||
case CFGTOK_ADDR:
|
||||
CfgNextTok ();
|
||||
if (Value >= 0) {
|
||||
CfgError ("Value already given");
|
||||
}
|
||||
CfgAssureInt ();
|
||||
CfgRangeCheck (0, 0xFFFF);
|
||||
Value = CfgIVal;
|
||||
CfgNextTok ();
|
||||
break;
|
||||
|
||||
case CFGTOK_SIZE:
|
||||
CfgNextTok ();
|
||||
if (Size >= 0) {
|
||||
CfgError ("Size already given");
|
||||
}
|
||||
CfgAssureInt ();
|
||||
CfgRangeCheck (1, 0x800);
|
||||
Size = CfgIVal;
|
||||
CfgNextTok ();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Directive is followed by a semicolon */
|
||||
CfgConsumeSemi ();
|
||||
}
|
||||
|
||||
/* Did we get the necessary data */
|
||||
if (Name == 0) {
|
||||
CfgError ("Label name is missing");
|
||||
}
|
||||
if (Value < 0) {
|
||||
CfgError ("Label value is missing");
|
||||
}
|
||||
if (Size < 0) {
|
||||
/* Use default */
|
||||
Size = 1;
|
||||
}
|
||||
if (HaveLabel ((unsigned) Value)) {
|
||||
CfgError ("Label for address $%04lX already defined", Value);
|
||||
}
|
||||
|
||||
/* Define the label */
|
||||
AddLabel ((unsigned) Value, atExtLabel, Name);
|
||||
|
||||
/* Define dependent labels if necessary */
|
||||
if (Size > 1) {
|
||||
unsigned Offs;
|
||||
|
||||
/* 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 < (unsigned) Size; ++Offs) {
|
||||
sprintf (DepOffs, "%u", Offs);
|
||||
AddLabel ((unsigned) Value+Offs, atDepLabel, DepName);
|
||||
}
|
||||
|
||||
/* Free the name buffer */
|
||||
xfree (DepName);
|
||||
}
|
||||
|
||||
/* Delete the dynamically allocated memory for Name */
|
||||
xfree (Name);
|
||||
|
||||
/* Consume the closing brace */
|
||||
CfgConsumeRCurly ();
|
||||
}
|
||||
@ -262,8 +356,8 @@ static void CfgParse (void)
|
||||
/* Parse the config file */
|
||||
{
|
||||
static const IdentTok Globals[] = {
|
||||
{ "GLOBAL", CFGTOK_GLOBAL },
|
||||
{ "RANGE", CFGTOK_RANGE },
|
||||
{ "GLOBAL", CFGTOK_GLOBAL },
|
||||
{ "RANGE", CFGTOK_RANGE },
|
||||
{ "LABEL", CFGTOK_LABEL },
|
||||
};
|
||||
|
||||
|
@ -61,7 +61,7 @@ static unsigned GetSpan (attr_t Style)
|
||||
*/
|
||||
unsigned Count = 1;
|
||||
while (Count < RemainingBytes) {
|
||||
if (HaveLabel(PC+Count) || GetStyle (PC+Count) != Style) {
|
||||
if (MustDefLabel(PC+Count) || GetStyleAttr (PC+Count) != Style) {
|
||||
break;
|
||||
}
|
||||
++Count;
|
||||
@ -81,6 +81,15 @@ static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (u
|
||||
/* Count how many bytes may be output. */
|
||||
unsigned Count = GetSpan (Style);
|
||||
|
||||
/* If the count is less than the member size, print a row of Count data
|
||||
* bytes. We assume here that there is no member with a size that is less
|
||||
* than BytesPerLine.
|
||||
*/
|
||||
if (Count < MemberSize) {
|
||||
DataByteLine (Count);
|
||||
return Count;
|
||||
}
|
||||
|
||||
/* Make Count an even number of multiples of MemberSize */
|
||||
Count &= ~(MemberSize-1);
|
||||
|
||||
@ -100,7 +109,7 @@ static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (u
|
||||
}
|
||||
|
||||
/* If the next line is not the same style, add a separator */
|
||||
if (CodeLeft() && GetStyle (PC) != Style) {
|
||||
if (CodeLeft() && GetStyleAttr (PC) != Style) {
|
||||
SeparatorLine ();
|
||||
}
|
||||
|
||||
@ -145,12 +154,14 @@ unsigned AddrTable (void)
|
||||
/* Count how many bytes may be output. */
|
||||
unsigned Count = GetSpan (atAddrTab);
|
||||
|
||||
/* Need to handle Count == 1 here!!! ### */
|
||||
|
||||
/* Make the given number even */
|
||||
Count &= ~1U;
|
||||
|
||||
/* Output as many data bytes lines as needed. For addresses, each line
|
||||
* will hold just one address.
|
||||
*/
|
||||
*/
|
||||
BytesLeft = Count;
|
||||
while (BytesLeft > 0) {
|
||||
|
||||
@ -160,7 +171,7 @@ unsigned AddrTable (void)
|
||||
/* In pass 1, define a label, in pass 2 output the line */
|
||||
if (Pass == 1) {
|
||||
if (!HaveLabel (Addr)) {
|
||||
AddLabel (Addr, MakeLabelName (Addr));
|
||||
AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
|
||||
}
|
||||
} else {
|
||||
const char* Label = GetLabel (Addr);
|
||||
@ -182,9 +193,66 @@ unsigned AddrTable (void)
|
||||
}
|
||||
|
||||
/* If the next line is not a byte table line, add a separator */
|
||||
if (CodeLeft() && GetStyle (PC) != atAddrTab) {
|
||||
if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
|
||||
SeparatorLine ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of bytes output */
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned RtsTable (void)
|
||||
/* Output a table of RTS addresses (address - 1) */
|
||||
{
|
||||
unsigned BytesLeft;
|
||||
|
||||
/* Count how many bytes may be output. */
|
||||
unsigned Count = GetSpan (atRtsTab);
|
||||
|
||||
/* Need to handle Count == 1 here!!! ### */
|
||||
|
||||
/* Make the given number even */
|
||||
Count &= ~1U;
|
||||
|
||||
/* Output as many data bytes lines as needed. For addresses, each line
|
||||
* will hold just one address.
|
||||
*/
|
||||
BytesLeft = Count;
|
||||
while (BytesLeft > 0) {
|
||||
|
||||
/* Get the address */
|
||||
unsigned Addr = GetCodeWord (PC) + 1;
|
||||
|
||||
/* In pass 1, define a label, in pass 2 output the line */
|
||||
if (Pass == 1) {
|
||||
if (!HaveLabel (Addr)) {
|
||||
AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
|
||||
}
|
||||
} else {
|
||||
const char* Label = GetLabel (Addr);
|
||||
if (Label == 0) {
|
||||
/* OOPS! Should not happen */
|
||||
Internal ("OOPS - Label for address %04X disappeard!", Addr);
|
||||
}
|
||||
Indent (MIndent);
|
||||
Output (".word");
|
||||
Indent (AIndent);
|
||||
Output ("%s-1", Label);
|
||||
LineComment (PC, 2);
|
||||
LineFeed ();
|
||||
}
|
||||
|
||||
/* Next line */
|
||||
PC += 2;
|
||||
BytesLeft -= 2;
|
||||
}
|
||||
|
||||
/* If the next line is not a byte table line, add a separator */
|
||||
if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
|
||||
SeparatorLine ();
|
||||
}
|
||||
|
||||
/* Return the number of bytes output */
|
||||
return Count;
|
||||
|
@ -56,6 +56,9 @@ unsigned DWordTable (void);
|
||||
unsigned AddrTable (void);
|
||||
/* Output a table of addresses */
|
||||
|
||||
unsigned RtsTable (void);
|
||||
/* Output a table of RTS addresses (address - 1) */
|
||||
|
||||
|
||||
|
||||
/* End of data.h */
|
||||
|
@ -118,7 +118,7 @@ static void GenerateLabel (const OpcDesc* D, unsigned Addr)
|
||||
if (Pass == 1 && !HaveLabel (Addr)) {
|
||||
if ((D->LabelFlag & lfGenLabel) != 0 ||
|
||||
((D->LabelFlag & lfUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd)) {
|
||||
AddLabel (Addr, MakeLabelName (Addr));
|
||||
AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,4 +397,12 @@ void OH_JmpAbsolute (const OpcDesc* D)
|
||||
|
||||
|
||||
|
||||
void OH_JmpAbsoluteIndirect (const OpcDesc* D)
|
||||
{
|
||||
OH_AbsoluteIndirect (D);
|
||||
SeparatorLine ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -78,6 +78,7 @@ void OH_AbsoluteXIndirect (const OpcDesc*);
|
||||
/* Handlers for special instructions */
|
||||
void OH_Rts (const OpcDesc*);
|
||||
void OH_JmpAbsolute (const OpcDesc*);
|
||||
void OH_JmpAbsoluteIndirect (const OpcDesc* D);
|
||||
|
||||
|
||||
|
||||
|
@ -174,9 +174,8 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
const OpcDesc* D = &OpcTable[OPC];
|
||||
|
||||
/* If we have a label at this address, output the label */
|
||||
const char* Label = GetLabel (PC);
|
||||
if (Label) {
|
||||
DefLabel (Label);
|
||||
if (MustDefLabel (PC)) {
|
||||
DefLabel (GetLabel (PC));
|
||||
}
|
||||
|
||||
/* Check...
|
||||
@ -185,7 +184,7 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
* - ...if there is no label somewhere between the instruction bytes.
|
||||
* If any of these conditions is true, switch to data mode.
|
||||
*/
|
||||
if (GetStyle (PC) == atDefault) {
|
||||
if (GetStyleAttr (PC) == atDefault) {
|
||||
if (D->Size > RemainingBytes) {
|
||||
MarkAddr (PC, atIllegal);
|
||||
} else if ((D->CPU & CPU) != CPU) {
|
||||
@ -202,7 +201,7 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
}
|
||||
|
||||
/* Disassemble the line */
|
||||
switch (GetStyle (PC)) {
|
||||
switch (GetStyleAttr (PC)) {
|
||||
|
||||
case atDefault:
|
||||
case atCode:
|
||||
@ -226,6 +225,10 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
AddrTable ();
|
||||
break;
|
||||
|
||||
case atRtsTab:
|
||||
RtsTable ();
|
||||
break;
|
||||
|
||||
default:
|
||||
DataByteLine (1);
|
||||
++PC;
|
||||
|
@ -500,7 +500,7 @@ const OpcDesc OpcTable[256] = {
|
||||
1,
|
||||
0,
|
||||
CPU_ALL,
|
||||
OH_Implicit
|
||||
OH_Rts
|
||||
},
|
||||
{ /* $41 */
|
||||
"eor",
|
||||
@ -808,7 +808,7 @@ const OpcDesc OpcTable[256] = {
|
||||
3,
|
||||
lfLabel,
|
||||
CPU_ALL,
|
||||
OH_AbsoluteIndirect
|
||||
OH_JmpAbsoluteIndirect
|
||||
},
|
||||
{ /* $6d */
|
||||
"adc",
|
||||
|
@ -146,8 +146,8 @@ void LineFeed (void)
|
||||
++Page;
|
||||
PageHeader ();
|
||||
Line = 4;
|
||||
}
|
||||
Col = 1;
|
||||
}
|
||||
Col = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ void DefLabel (const char* Name)
|
||||
{
|
||||
Output ("%s:", Name);
|
||||
/* Don't start a new line if the label is fully in the left column */
|
||||
if (Col >= MIndent-1) {
|
||||
if (Col > MIndent) {
|
||||
LineFeed ();
|
||||
}
|
||||
}
|
||||
@ -174,11 +174,11 @@ void DataByteLine (unsigned ByteCount)
|
||||
Output (".byte");
|
||||
Indent (AIndent);
|
||||
for (I = 0; I < ByteCount; ++I) {
|
||||
if (I > 0) {
|
||||
Output (",$%02X", CodeBuf[PC+I]);
|
||||
} else {
|
||||
Output ("$%02X", CodeBuf[PC+I]);
|
||||
}
|
||||
if (I > 0) {
|
||||
Output (",$%02X", CodeBuf[PC+I]);
|
||||
} else {
|
||||
Output ("$%02X", CodeBuf[PC+I]);
|
||||
}
|
||||
}
|
||||
LineComment (PC, ByteCount);
|
||||
LineFeed ();
|
||||
|
@ -82,7 +82,9 @@ typedef enum token_t {
|
||||
CFGTOK_RTSTAB,
|
||||
|
||||
/* Label section */
|
||||
|
||||
CFGTOK_NAME,
|
||||
CFGTOK_ADDR,
|
||||
CFGTOK_SIZE,
|
||||
|
||||
/* */
|
||||
CFGTOK_TRUE,
|
||||
|
Loading…
Reference in New Issue
Block a user