Completed the coding of da65's SEGMENT feature.
Before this commit, we could define segment ranges; but, the disassembler wouldn't do anything with those definitions. Now, da65 will put ".segment" directives into its output. Fixed da65's document.
This commit is contained in:
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
||||
/* R<EFBFBD>merstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -66,6 +66,18 @@ void AddrCheck (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
/* Return the attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SegmentDefined (unsigned Start, unsigned End)
|
||||
/* Return true if the atSegment bit is set somewhere in the given range */
|
||||
{
|
||||
@@ -79,14 +91,26 @@ int SegmentDefined (unsigned Start, unsigned End)
|
||||
|
||||
|
||||
|
||||
int HaveSegmentChange (unsigned Addr)
|
||||
/* Return true if the segment change attribute is set for the given address */
|
||||
int IsSegmentEnd (unsigned Addr)
|
||||
/* Return true if a segment ends at the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
return (GetAttr (Addr) & atSegmentEnd) != 0x0000;
|
||||
}
|
||||
|
||||
/* Return the attribute */
|
||||
return (AttrTab[Addr] & atSegmentChange) != 0;
|
||||
|
||||
|
||||
int IsSegmentStart (unsigned Addr)
|
||||
/* Return true if a segment starts at the given address */
|
||||
{
|
||||
return (GetAttr (Addr) & atSegmentStart) != 0x0000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int HaveSegmentChange (unsigned Addr)
|
||||
/* Return true if the segment change attributes are set for the given address */
|
||||
{
|
||||
return (GetAttr (Addr) & (atSegmentStart | atSegmentEnd)) != 0x0000;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,18 +169,6 @@ void MarkAddr (unsigned Addr, attr_t Attr)
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
/* Return the attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
attr_t GetStyleAttr (unsigned Addr)
|
||||
/* Return the style attribute for the given address */
|
||||
{
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
||||
/* R<EFBFBD>merstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -47,33 +47,34 @@
|
||||
typedef enum attr_t {
|
||||
|
||||
/* Styles */
|
||||
atDefault = 0x0000, /* Default style */
|
||||
atCode = 0x0001,
|
||||
atIllegal = 0x0002,
|
||||
atByteTab = 0x0003, /* Same as illegal */
|
||||
atDByteTab = 0x0004,
|
||||
atWordTab = 0x0005,
|
||||
atDWordTab = 0x0006,
|
||||
atAddrTab = 0x0007,
|
||||
atRtsTab = 0x0008,
|
||||
atTextTab = 0x0009,
|
||||
atSkip = 0x000A, /* Skip code completely */
|
||||
atDefault = 0x0000, /* Default style */
|
||||
atCode = 0x0001,
|
||||
atIllegal = 0x0002,
|
||||
atByteTab = 0x0003, /* Same as illegal */
|
||||
atDByteTab = 0x0004,
|
||||
atWordTab = 0x0005,
|
||||
atDWordTab = 0x0006,
|
||||
atAddrTab = 0x0007,
|
||||
atRtsTab = 0x0008,
|
||||
atTextTab = 0x0009,
|
||||
atSkip = 0x000A, /* Skip code completely */
|
||||
|
||||
/* Label flags */
|
||||
atNoLabel = 0x0000, /* No label for this address */
|
||||
atExtLabel = 0x0010, /* External label */
|
||||
atIntLabel = 0x0020, /* Internally generated label */
|
||||
atDepLabel = 0x0040, /* Dependent label */
|
||||
atUnnamedLabel = 0x0080, /* Unnamed label */
|
||||
atNoLabel = 0x0000, /* No label for this address */
|
||||
atExtLabel = 0x0010, /* External label */
|
||||
atIntLabel = 0x0020, /* Internally generated label */
|
||||
atDepLabel = 0x0040, /* Dependent label */
|
||||
atUnnamedLabel = 0x0080, /* Unnamed label */
|
||||
|
||||
atLabelDefined = 0x0100, /* True if we defined the label */
|
||||
atLabelDefined = 0x0100, /* True if we defined the label */
|
||||
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
|
||||
/* Segment */
|
||||
atSegment = 0x0100, /* Code is in a segment */
|
||||
atSegmentChange = 0x0200, /* Either segment start or segment end */
|
||||
atSegment = 0x0100, /* Code is in a segment */
|
||||
atSegmentEnd = 0x0200, /* Segment end */
|
||||
atSegmentStart = 0x0400, /* Segment start */
|
||||
} attr_t;
|
||||
|
||||
|
||||
@@ -87,11 +88,20 @@ typedef enum attr_t {
|
||||
void AddrCheck (unsigned Addr);
|
||||
/* Check if the given address has a valid range */
|
||||
|
||||
attr_t GetAttr (unsigned Addr);
|
||||
/* Return the attribute for the given address */
|
||||
|
||||
int SegmentDefined (unsigned Start, unsigned End);
|
||||
/* Return true if the atSegment bit is set somewhere in the given range */
|
||||
|
||||
int IsSegmentEnd (unsigned Addr);
|
||||
/* Return true if a segment ends at the given address */
|
||||
|
||||
int IsSegmentStart (unsigned Addr);
|
||||
/* Return true if a segment starts at the given address */
|
||||
|
||||
int HaveSegmentChange (unsigned Addr);
|
||||
/* Return true if the segment change attribute is set for the given address */
|
||||
/* Return true if the segment change attributes are set for the given address */
|
||||
|
||||
unsigned GetGranularity (attr_t Style);
|
||||
/* Get the granularity for the given style */
|
||||
@@ -102,9 +112,6 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr);
|
||||
void MarkAddr (unsigned Addr, attr_t Attr);
|
||||
/* Mark an address with an attribute */
|
||||
|
||||
attr_t GetAttr (unsigned Addr);
|
||||
/* Return the attribute for the given address */
|
||||
|
||||
attr_t GetStyleAttr (unsigned Addr);
|
||||
/* Return the style attribute for the given address */
|
||||
|
||||
@@ -114,5 +121,4 @@ attr_t GetLabelAttr (unsigned Addr);
|
||||
|
||||
|
||||
/* End of attrtab.h */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -65,12 +65,12 @@ static unsigned GetSpan (attr_t Style)
|
||||
attr_t Attr;
|
||||
if (MustDefLabel(PC+Count)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Attr = GetAttr (PC+Count);
|
||||
if ((Attr & atStyleMask) != Style) {
|
||||
break;
|
||||
}
|
||||
if ((Attr & atSegmentChange)) {
|
||||
if ((Attr & (atSegmentStart | atSegmentEnd))) {
|
||||
break;
|
||||
}
|
||||
++Count;
|
||||
|
||||
@@ -748,9 +748,6 @@ static void SegmentSection (void)
|
||||
if (Start < 0) {
|
||||
InfoError ("Start address is missing");
|
||||
}
|
||||
if (Start == End) {
|
||||
InfoError ("Segment is empty");
|
||||
}
|
||||
if (Start > End) {
|
||||
InfoError ("Start address of segment is greater than end address");
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "opctable.h"
|
||||
#include "output.h"
|
||||
#include "scanner.h"
|
||||
#include "segment.h"
|
||||
|
||||
|
||||
|
||||
@@ -356,6 +357,14 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
/* Get the output style for the current PC */
|
||||
attr_t Style = GetStyleAttr (PC);
|
||||
|
||||
/* If a segment begins here, then name that segment.
|
||||
** Note that the segment is named even if its code is being skipped,
|
||||
** because some of its later code might not be skipped.
|
||||
*/
|
||||
if (IsSegmentStart (PC)) {
|
||||
StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
|
||||
}
|
||||
|
||||
/* If we have a label at this address, output the label and an attached
|
||||
** comment, provided that we aren't in a skip area.
|
||||
*/
|
||||
@@ -371,7 +380,7 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
** - ...if we have enough bytes remaining for the code at this address.
|
||||
** - ...if the current instruction is valid for the given CPU.
|
||||
** - ...if there is no label somewhere between the instruction bytes.
|
||||
** If any of these conditions is false, switch to data mode.
|
||||
** If any of those conditions is false, switch to data mode.
|
||||
*/
|
||||
if (Style == atDefault) {
|
||||
if (D->Size > RemainingBytes) {
|
||||
@@ -383,7 +392,14 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
} else {
|
||||
unsigned I;
|
||||
for (I = 1; I < D->Size; ++I) {
|
||||
if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
|
||||
if (HaveLabel (PC+I)) {
|
||||
Style = atIllegal;
|
||||
MarkAddr (PC, Style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (I = 1; I < D->Size - 1u; ++I) {
|
||||
if (HaveSegmentChange (PC+I)) {
|
||||
Style = atIllegal;
|
||||
MarkAddr (PC, Style);
|
||||
break;
|
||||
@@ -455,6 +471,10 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (IsSegmentEnd (PC - 1)) {
|
||||
EndSegment ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@@ -63,6 +63,8 @@ static unsigned Col = 1; /* Current column */
|
||||
static unsigned Line = 0; /* Current line on page */
|
||||
static unsigned Page = 1; /* Current output page */
|
||||
|
||||
static const char* SegmentName = 0; /* Name of current segment */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -223,23 +225,6 @@ void DefConst (const char* Name, const char* Comment, unsigned Addr)
|
||||
|
||||
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize)
|
||||
/* Start a segment */
|
||||
{
|
||||
if (Pass == PassCount) {
|
||||
Output (".segment");
|
||||
Indent (ACol);
|
||||
if (AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
Output ("\"%s\"", Name);
|
||||
} else {
|
||||
Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
|
||||
}
|
||||
LineFeed ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DataByteLine (unsigned ByteCount)
|
||||
/* Output a line with bytes */
|
||||
{
|
||||
@@ -335,6 +320,39 @@ void SeparatorLine (void)
|
||||
|
||||
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize)
|
||||
/* Start a segment */
|
||||
{
|
||||
if (Pass == PassCount) {
|
||||
LineFeed ();
|
||||
Output (".segment");
|
||||
Indent (ACol);
|
||||
SegmentName = Name;
|
||||
Output ("\"%s\"", Name);
|
||||
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||
Output (": %s", AddrSizeToStr (AddrSize));
|
||||
}
|
||||
LineFeed ();
|
||||
LineFeed ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EndSegment (void)
|
||||
/* End a segment */
|
||||
{
|
||||
LineFeed ();
|
||||
Output ("; End of \"%s\" segment", SegmentName);
|
||||
LineFeed ();
|
||||
SeparatorLine ();
|
||||
Output (".code");
|
||||
LineFeed ();
|
||||
LineFeed ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UserComment (const char* Comment)
|
||||
/* Output a comment line */
|
||||
{
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -74,12 +74,6 @@ void DefForward (const char* Name, const char* Comment, unsigned Offs);
|
||||
|
||||
void DefConst (const char* Name, const char* Comment, unsigned Addr);
|
||||
/* Define an address constant */
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize);
|
||||
/* Start a segment */
|
||||
|
||||
void EndSegment (void);
|
||||
/* End a segment */
|
||||
|
||||
void OneDataByte (void);
|
||||
/* Output a .byte line with the current code byte */
|
||||
@@ -99,6 +93,12 @@ void DataDWordLine (unsigned ByteCount);
|
||||
void SeparatorLine (void);
|
||||
/* Print a separator line */
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize);
|
||||
/* Start a segment */
|
||||
|
||||
void EndSegment (void);
|
||||
/* End a segment */
|
||||
|
||||
void UserComment (const char* Comment);
|
||||
/* Output a comment line */
|
||||
|
||||
@@ -111,5 +111,4 @@ void OutputSettings (void);
|
||||
|
||||
|
||||
/* End of output.h */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2007-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -58,18 +58,15 @@
|
||||
typedef struct Segment Segment;
|
||||
struct Segment {
|
||||
Segment* NextStart; /* Pointer to next segment */
|
||||
Segment* NextEnd; /* Pointer to next segment */
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned AddrSize;
|
||||
char Name[1]; /* Name, dynamically allocated */
|
||||
};
|
||||
|
||||
/* Tables containing the segments. A segment is inserted using it's hash
|
||||
** value. Collision is done by single linked lists.
|
||||
/* Table containing the segments. A segment is inserted using its hash
|
||||
** value. Collisions are handled by single-linked lists.
|
||||
*/
|
||||
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
|
||||
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
|
||||
|
||||
|
||||
|
||||
@@ -90,20 +87,53 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name)
|
||||
|
||||
/* Fill in the data */
|
||||
S->Start = Start;
|
||||
S->End = End;
|
||||
S->AddrSize = ADDR_SIZE_ABS;
|
||||
memcpy (S->Name, Name, Len + 1);
|
||||
|
||||
/* Insert the segment into the hash tables */
|
||||
/* Insert the segment into the hash table */
|
||||
S->NextStart = StartTab[Start % HASH_SIZE];
|
||||
StartTab[Start % HASH_SIZE] = S;
|
||||
S->NextEnd = EndTab[End % HASH_SIZE];
|
||||
EndTab[End % HASH_SIZE] = S;
|
||||
|
||||
/* Mark start and end of the segment */
|
||||
MarkAddr (Start, atSegmentChange);
|
||||
MarkAddr (End, atSegmentChange);
|
||||
MarkAddr (Start, atSegmentStart);
|
||||
MarkAddr (End, atSegmentEnd);
|
||||
|
||||
/* Mark the addresses within the segment */
|
||||
MarkRange (Start, End, atSegment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char* GetSegmentStartName (unsigned Addr)
|
||||
/* Return the name of the segment which starts at the given address */
|
||||
{
|
||||
Segment* S = StartTab[Addr % HASH_SIZE];
|
||||
|
||||
/* Search the collision list for the exact address */
|
||||
while (S != 0) {
|
||||
if (S->Start == Addr) {
|
||||
return S->Name;
|
||||
}
|
||||
S = S->NextStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned GetSegmentAddrSize (unsigned Addr)
|
||||
/* Return the address size of the segment which starts at the given address */
|
||||
{
|
||||
Segment* S = StartTab[Addr % HASH_SIZE];
|
||||
|
||||
/* Search the collision list for the exact address */
|
||||
while (S != 0) {
|
||||
if (S->Start == Addr) {
|
||||
return S->AddrSize;
|
||||
}
|
||||
S = S->NextStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2007-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -47,8 +47,13 @@
|
||||
void AddAbsSegment (unsigned Start, unsigned End, const char* Name);
|
||||
/* Add an absolute segment to the segment table */
|
||||
|
||||
char* GetSegmentStartName (unsigned Addr);
|
||||
/* Return the name of the segment which starts at the given address */
|
||||
|
||||
unsigned GetSegmentAddrSize (unsigned Addr);
|
||||
/* Return the address size of the segment which starts at the given address */
|
||||
|
||||
|
||||
|
||||
/* End of segment.h */
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user