Replace all tables by hash tables. This allows to remove the ugly special
casing of "long addresses" and prepares the code base for use with the full address range of the 65816. Use fixed size data types for addresses and target data words of known size. Many other minor improvements.
This commit is contained in:
@@ -33,6 +33,11 @@
|
||||
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* da65 */
|
||||
#include "cpu.h"
|
||||
#include "error.h"
|
||||
@@ -46,14 +51,78 @@
|
||||
|
||||
|
||||
|
||||
/* Attribute table */
|
||||
static unsigned short AttrTab[0x10000];
|
||||
/* Attribute structure how it is found in the attribute table */
|
||||
typedef struct Attribute Attribute;
|
||||
struct Attribute {
|
||||
struct Attribute* Next; /* Next entry in linked list */
|
||||
uint32_t Addr; /* The full address */
|
||||
attr_t Attr; /* Actual attribute */
|
||||
};
|
||||
|
||||
/* 65816 attribute table */
|
||||
#define MAX_LONG_ATTRS 256
|
||||
static unsigned short LongAttrVal[MAX_LONG_ATTRS];
|
||||
static unsigned LongAttrAddr[MAX_LONG_ATTRS];
|
||||
static unsigned LongAttrsUsed;
|
||||
/* Attributes use a hash table and a linear list for collision resolution. The
|
||||
** hash function is easy and effective. It evaluates just the lower bits of
|
||||
** the address.
|
||||
*/
|
||||
#define ATTR_HASH_SIZE 8192u /* Must be power of two */
|
||||
static Attribute* AttributeTab[ATTR_HASH_SIZE];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* struct Attribute */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static Attribute* NewAttribute (uint32_t Addr, attr_t Attr)
|
||||
/* Create a new attribute structure and return it */
|
||||
{
|
||||
/* Create a new attribute */
|
||||
Attribute* A = xmalloc (sizeof (Attribute));
|
||||
|
||||
/* Fill in the data */
|
||||
A->Next = 0;
|
||||
A->Addr = Addr;
|
||||
A->Attr = Attr;
|
||||
|
||||
/* Return the attribute just created */
|
||||
return A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint32_t GetAttributeHash (uint32_t Addr)
|
||||
/* Get the hash for an attribute at the given address */
|
||||
{
|
||||
return (Addr & (ATTR_HASH_SIZE - 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Attribute* FindAttribute (uint32_t Addr)
|
||||
/* Search for an attribute for the given address and return it. Returns NULL
|
||||
** if no attribute exists for the address.
|
||||
*/
|
||||
{
|
||||
Attribute* A = AttributeTab[GetAttributeHash (Addr)];
|
||||
while (A) {
|
||||
if (A->Addr == Addr) {
|
||||
break;
|
||||
}
|
||||
A = A->Next;
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void InsertAttribute (Attribute* A)
|
||||
/* Insert an attribute into the hash table */
|
||||
{
|
||||
uint32_t Hash = GetAttributeHash (A->Addr);
|
||||
A->Next = AttributeTab[Hash];
|
||||
AttributeTab[Hash] = A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,51 +132,43 @@ static unsigned LongAttrsUsed;
|
||||
|
||||
|
||||
|
||||
void AddrCheck (unsigned Addr)
|
||||
void AddrCheck (uint32_t Addr)
|
||||
/* Check if the given address has a valid range */
|
||||
{
|
||||
if (Addr >= 0x10000 && CPU != CPU_65816) {
|
||||
Error ("Address out of range: %08X", Addr);
|
||||
Error ("Address out of range: $%04" PRIX32, Addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned char IsLongAddr (unsigned Addr)
|
||||
/* Is it 24-bit? */
|
||||
{
|
||||
return Addr >= 0x10000 && CPU == CPU_65816;
|
||||
}
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
attr_t GetAttr (uint32_t Addr)
|
||||
/* Return the attribute for the given address */
|
||||
{
|
||||
/* As a small optimization we cache the last used attribute so when the
|
||||
** function is called several times with the same address we do already
|
||||
** know it.
|
||||
*/
|
||||
static const Attribute* A = 0;
|
||||
if (A != 0 && A->Addr == Addr) {
|
||||
return A->Attr;
|
||||
}
|
||||
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
if (IsLongAddr (Addr)) {
|
||||
unsigned i;
|
||||
for (i = 0; i < LongAttrsUsed; i++) {
|
||||
if (LongAttrAddr[i] == Addr) {
|
||||
return LongAttrVal[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
A = FindAttribute (Addr);
|
||||
return A? A->Attr : atDefault;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SegmentDefined (unsigned Start, unsigned End)
|
||||
int SegmentDefined (uint32_t Start, uint32_t End)
|
||||
/* Return true if the atSegment bit is set somewhere in the given range */
|
||||
{
|
||||
while (Start <= End) {
|
||||
if (AttrTab[Start++] & atSegment) {
|
||||
if (GetAttr (Start++) & atSegment) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +177,7 @@ int SegmentDefined (unsigned Start, unsigned End)
|
||||
|
||||
|
||||
|
||||
int IsSegmentEnd (unsigned Addr)
|
||||
int IsSegmentEnd (uint32_t Addr)
|
||||
/* Return true if a segment ends at the given address */
|
||||
{
|
||||
return (GetAttr (Addr) & atSegmentEnd) != 0x0000;
|
||||
@@ -124,7 +185,7 @@ int IsSegmentEnd (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
int IsSegmentStart (unsigned Addr)
|
||||
int IsSegmentStart (uint32_t Addr)
|
||||
/* Return true if a segment starts at the given address */
|
||||
{
|
||||
return (GetAttr (Addr) & atSegmentStart) != 0x0000;
|
||||
@@ -155,7 +216,7 @@ unsigned GetGranularity (attr_t Style)
|
||||
|
||||
|
||||
|
||||
void MarkRange (unsigned Start, unsigned End, attr_t Attr)
|
||||
void MarkRange (uint32_t Start, uint32_t End, attr_t Attr)
|
||||
/* Mark a range with the given attribute */
|
||||
{
|
||||
/* Do it easy here... */
|
||||
@@ -166,53 +227,33 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr)
|
||||
|
||||
|
||||
|
||||
void MarkAddr (unsigned Addr, attr_t Attr)
|
||||
void MarkAddr (uint32_t Addr, attr_t Attr)
|
||||
/* Mark an address with an attribute */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
if (IsLongAddr (Addr)) {
|
||||
unsigned i;
|
||||
for (i = 0; i < LongAttrsUsed; i++) {
|
||||
if (LongAttrAddr[i] == Addr) {
|
||||
|
||||
/* We must not have more than one style bit */
|
||||
if (Attr & atStyleMask) {
|
||||
if (LongAttrVal[i] & atStyleMask) {
|
||||
Error ("Duplicate style for long address %06X", Addr);
|
||||
}
|
||||
}
|
||||
LongAttrVal[i] |= Attr;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (LongAttrsUsed >= MAX_LONG_ATTRS) {
|
||||
Error ("Too many long addresses");
|
||||
}
|
||||
LongAttrVal[LongAttrsUsed] |= Attr;
|
||||
LongAttrAddr[LongAttrsUsed] = Addr;
|
||||
LongAttrsUsed++;
|
||||
|
||||
return;
|
||||
}
|
||||
/* Get an existing attribute entry */
|
||||
Attribute* A = FindAttribute (Addr);
|
||||
|
||||
/* We must not have more than one style bit */
|
||||
if (Attr & atStyleMask) {
|
||||
if (AttrTab[Addr] & atStyleMask) {
|
||||
Error ("Duplicate style for address %04X", Addr);
|
||||
if (A != 0 && (Attr & atStyleMask) != 0) {
|
||||
if ((A->Attr & atStyleMask) != 0) {
|
||||
Error ("Duplicate style for address %04" PRIX32, Addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the style */
|
||||
AttrTab[Addr] |= Attr;
|
||||
if (A) {
|
||||
A->Attr |= Attr;
|
||||
} else {
|
||||
InsertAttribute (NewAttribute (Addr, Attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
attr_t GetStyleAttr (unsigned Addr)
|
||||
attr_t GetStyleAttr (uint32_t Addr)
|
||||
/* Return the style attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
@@ -224,7 +265,7 @@ attr_t GetStyleAttr (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
attr_t GetLabelAttr (unsigned Addr)
|
||||
attr_t GetLabelAttr (uint32_t Addr)
|
||||
/* Return the label attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
|
||||
Reference in New Issue
Block a user