-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);
/* Create a new label */
SymTab[Addr] = xstrdup (Name);
+
+ /* Remember the attribute */
+ AttrTab[Addr] |= Attr;
}
+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 */
{
-unsigned char GetStyle (unsigned Addr)
+unsigned char GetStyleAttr (unsigned Addr)
/* Return the style attribute for the given address */
{
/* Check the given address */
+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 */
{
/* 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);
}
}
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
typedef enum attr_t attr_t;
enum attr_t {
+
+ /* Styles */
atDefault = 0x00, /* Default style */
atCode = 0x01,
atIllegal = 0x02,
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 */
/*****************************************************************************/
* 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 */
+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.
+ */
+
const char* GetLabel (unsigned Addr);
-/* Return the label for an address */
+/* Return the label for an address or NULL if there is none */
-unsigned char GetStyle (unsigned Addr);
+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 */
+#include <stdio.h>
#if defined(_MSC_VER)
/* Microsoft compiler */
# include <io.h>
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 ();
/* 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 */
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 ();
/* 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 ();
/* Parse the config file */
{
static const IdentTok Globals[] = {
- { "GLOBAL", CFGTOK_GLOBAL },
- { "RANGE", CFGTOK_RANGE },
+ { "GLOBAL", CFGTOK_GLOBAL },
+ { "RANGE", CFGTOK_RANGE },
{ "LABEL", CFGTOK_LABEL },
};
*/
unsigned Count = 1;
while (Count < RemainingBytes) {
- if (HaveLabel(PC+Count) || GetStyle (PC+Count) != Style) {
+ if (MustDefLabel(PC+Count) || GetStyleAttr (PC+Count) != Style) {
break;
}
++Count;
/* 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);
}
/* If the next line is not the same style, add a separator */
- if (CodeLeft() && GetStyle (PC) != Style) {
+ if (CodeLeft() && GetStyleAttr (PC) != Style) {
SeparatorLine ();
}
/* 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) {
/* 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);
}
/* 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;
unsigned AddrTable (void);
/* Output a table of addresses */
+unsigned RtsTable (void);
+/* Output a table of RTS addresses (address - 1) */
+
/* End of data.h */
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));
}
}
}
+void OH_JmpAbsoluteIndirect (const OpcDesc* D)
+{
+ OH_AbsoluteIndirect (D);
+ SeparatorLine ();
+}
+
+
+
/* Handlers for special instructions */
void OH_Rts (const OpcDesc*);
void OH_JmpAbsolute (const OpcDesc*);
+void OH_JmpAbsoluteIndirect (const OpcDesc* D);
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...
* - ...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) {
}
/* Disassemble the line */
- switch (GetStyle (PC)) {
+ switch (GetStyleAttr (PC)) {
case atDefault:
case atCode:
AddrTable ();
break;
+ case atRtsTab:
+ RtsTable ();
+ break;
+
default:
DataByteLine (1);
++PC;
1,
0,
CPU_ALL,
- OH_Implicit
+ OH_Rts
},
{ /* $41 */
"eor",
3,
lfLabel,
CPU_ALL,
- OH_AbsoluteIndirect
+ OH_JmpAbsoluteIndirect
},
{ /* $6d */
"adc",
++Page;
PageHeader ();
Line = 4;
- }
- Col = 1;
+ }
+ Col = 1;
}
}
{
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 ();
}
}
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 ();
CFGTOK_RTSTAB,
/* Label section */
-
+ CFGTOK_NAME,
+ CFGTOK_ADDR,
+ CFGTOK_SIZE,
/* */
CFGTOK_TRUE,