1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-25 13:29:41 +00:00
git-svn-id: svn://svn.cc65.org/cc65/trunk@2092 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-04-27 15:31:00 +00:00
parent 251547f028
commit 8bff858b09
6 changed files with 293 additions and 239 deletions

View File

@ -41,6 +41,7 @@
#include "xmalloc.h"
/* sim65 */
#include "cfgdata.h"
#include "chipdata.h"
#include "chiplib.h"
#include "error.h"
@ -88,50 +89,6 @@ static int CmpChips (void* Data attribute ((unused)),
/*****************************************************************************/
/* Code */
/*****************************************************************************/
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
/* Allocate a new chip structure, initialize and return it */
{
/* Allocate memory */
Chip* C = xmalloc (sizeof (Chip));
/* Initialize the fields */
C->Library = Library;
C->Data = Data;
C->Instances = EmptyCollection;
/* Insert the new chip into the collection of all chips */
CollAppend (&Chips, C);
/* Return the structure */
return C;
}
ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size)
/* Allocate a new chip instance for the chip. */
{
/* Allocate a new ChipInstance structure */
ChipInstance* Instance = xmalloc (sizeof (*Instance));
/* Initialize the fields */
Instance->C = 0;
Instance->Addr = Addr;
Instance->Size = Size;
Instance->InstanceData = 0;
/* Return the new struct */
return Instance;
}
static Chip* FindChip (const char* Name)
/* Find a chip by name. Returns the Chip data structure or NULL if the chip
* could not be found.
@ -158,24 +115,80 @@ static Chip* FindChip (const char* Name)
void InitChipInstance (ChipInstance* CI, const char* ChipName,
const struct CfgData** Data, unsigned Count)
/* Initialize the given chip instance. Assign it to the chip named ChipName,
* and call the init function of the chip passing the given config data.
*/
/*****************************************************************************/
/* Code */
/*****************************************************************************/
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
/* Allocate a new chip structure, initialize and return it */
{
/* Allocate memory */
Chip* C = xmalloc (sizeof (Chip));
/* Initialize the fields */
C->Library = Library;
C->Data = Data;
C->Instances = EmptyCollection;
/* Insert the new chip into the collection of all chips */
CollAppend (&Chips, C);
/* Return the structure */
return C;
}
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
unsigned Size, const Collection* Attributes)
{
ChipInstance* CI;
/* Find the chip with the given name */
Chip* C = FindChip (ChipName);
if (C == 0) {
Error ("No chip `%s' found for address $%6lX", ChipName, CI->Addr);
Error ("No chip `%s' found for address $%06X", ChipName, Addr);
}
/* Call the initialization function */
CI->InstanceData = C->Data->InitInstance (CI->Addr, CI->Size, Data, Count);
/* Allocate a new ChipInstance structure */
CI = xmalloc (sizeof (*CI));
/* Initialize the fields */
CI->C = C;
CI->Addr = Addr;
CI->Size = Size;
CI->Data = C->Data->InitInstance (Addr, Size,
(const CfgData**) Attributes->Items,
CollCount (Attributes));
/* Assign the chip instance to the chip */
CI->C = C;
CollAppend (&C->Instances, CI);
/* Return the new instance struct */
return CI;
}
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
/* Generate a chip instance mirror and return it. */
{
/* Allocate a new ChipInstance structure */
ChipInstance* CI = xmalloc (sizeof (*CI));
/* Initialize the fields */
CI->C = Orig->C;
CI->Addr = Addr;
CI->Size = Orig->Size;
CI->Data = Orig->Data;
/* Assign the chip instance to the chip */
CollAppend (&CI->C->Instances, CI);
/* Return the new instance struct */
return CI;
}

View File

@ -61,10 +61,10 @@ typedef struct ChipInstance ChipInstance;
/* One instance of a chip */
struct ChipInstance {
Chip* C; /* Pointer to corresponding chip */
unsigned long Addr; /* Start address of range */
unsigned Size; /* Size of range */
void* InstanceData; /* Chip instance data */
Chip* C; /* Pointer to corresponding chip */
unsigned Addr; /* Start address of range */
unsigned Size; /* Size of range */
void* Data; /* Chip instance data */
};
/* Chip structure */
@ -85,14 +85,12 @@ struct Chip {
Chip* NewChip (struct ChipLibrary* Library, const ChipData* Data);
/* Allocate a new chip structure, initialize and return it */
ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size);
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
unsigned Size, const Collection* Attributes);
/* Allocate a new chip instance for the chip. */
void InitChipInstance (ChipInstance* CI, const char* ChipName,
const struct CfgData** Data, unsigned Count);
/* Initialize the given chip instance. Assign it to the chip named ChipName,
* and call the init function of the chip passing the given config data.
*/
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr);
/* Generate a chip instance mirror and return it. */
void SortChips (void);
/* Sort all chips by name. Called after loading */

View File

@ -50,6 +50,7 @@
#include "chip.h"
#include "error.h"
#include "global.h"
#include "memory.h"
#include "scanner.h"
#include "config.h"
@ -67,11 +68,11 @@ static Collection Locations;
/* One memory location */
typedef struct Location Location;
struct Location {
unsigned long Start; /* Start of memory location */
unsigned long End; /* End memory location */
Collection Attributes; /* Attributes given */
unsigned Line; /* Line in config file */
unsigned Col; /* Column in config file */
unsigned Start; /* Start of memory location */
unsigned End; /* End memory location */
Collection Attributes; /* Attributes given */
unsigned Line; /* Line in config file */
unsigned Col; /* Column in config file */
};
@ -94,7 +95,7 @@ static CfgData* NewCfgData (void)
CfgData* D = xmalloc (sizeof (CfgData) + AttrLen);
/* Initialize the fields */
D->Type = CfgDataInvalid;
D->Type = CfgDataInvalid;
D->Line = CfgErrorLine;
D->Col = CfgErrorCol;
memcpy (D->Attr, CfgSVal, AttrLen+1);
@ -105,6 +106,30 @@ static CfgData* NewCfgData (void)
static void FreeCfgData (CfgData* D)
/* Free a config data structure */
{
if (D->Type == CfgDataString) {
/* Free the string value */
xfree (D->V.SVal);
}
/* Free the structure */
xfree (D);
}
static void CfgDataCheckType (const CfgData* D, unsigned Type)
/* Check the config data type */
{
if (D->Type != Type) {
Error ("%s(%u): Attribute `%s' has invalid type",
CfgGetName (), D->Line, D->Attr);
}
}
/*****************************************************************************/
/* struct Location */
/*****************************************************************************/
@ -150,9 +175,9 @@ static int CmpLocations (void* Data attribute ((unused)),
static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return it. Return NULL if the
* attribute was not found.
static int LocationFindAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return its index. Return -1 if
* the attribute was not found.
*/
{
unsigned I;
@ -166,12 +191,26 @@ static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
/* Compare the name */
if (StrCaseCmp (D->Attr, AttrName) == 0) {
/* Found */
return D;
return I;
}
}
/* Not found */
return 0;
return -1;
}
static int LocationGetAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return it. Call Error() if the
* attribute was not found.
*/
{
int I = LocationFindAttr (L, AttrName);
if (I < 0) {
Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
}
return I;
}
@ -180,40 +219,17 @@ static int LocationIsMirror (const Location* L)
/* Return true if the given location is a mirror of another one. */
{
/* Find the "mirror" attribute */
return (LocationFindAttr (L, "mirror") != 0);
return (LocationFindAttr (L, "mirror") >= 0);
}
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
/* Check if the item is already defined. Print an error if so. If not, set
* the marker that we have a definition now.
*/
{
if (*Flags & Mask) {
CfgError ("%s is already defined", Name);
}
*Flags |= Mask;
}
static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
/* Check that a mandatory attribute was given */
{
if ((Attr & Mask) == 0) {
CfgError ("%s attribute is missing", Name);
}
}
static void ParseMemory (void)
/* Parse a MEMORY section */
{
@ -312,19 +328,106 @@ static void ParseMemory (void)
if (LocationIsMirror (L)) {
const CfgData* D;
if (CollCount (&L->Attributes) > 1) {
Error ("%s(%u): Location at address $%06lX is a mirror "
Error ("%s(%u): Location at address $%06X is a mirror "
"but has attributes", CfgGetName(), L->Line, L->Start);
}
D = CollConstAt (&L->Attributes, 0);
if (D->Type != CfgDataNumber) {
Error ("%s(%u): Mirror attribute is not an integer",
CfgGetName (), L->Line);
}
CfgDataCheckType (D, CfgDataNumber);
}
/* Remember this entry */
Last = L;
}
/* Now create the chip instances. Since we can only mirror existing chips,
* we will first create all real chips and the mirrors in a second run.
*/
for (I = 0; I < CollCount (&Locations); ++I) {
int Index;
CfgData* D;
unsigned Range; /* Address range for this chip */
ChipInstance* CI;
/* Get this location */
Location* L = CollAtUnchecked (&Locations, I);
/* Skip mirrors */
if (LocationIsMirror (L)) {
continue;
}
/* The chip must have an attribute "name" of type string */
Index = LocationGetAttr (L, "name");
D = CollAt (&L->Attributes, Index);
CfgDataCheckType (D, CfgDataString);
/* Remove the "name" attribute from the attribute list */
CollDelete (&L->Attributes, Index);
/* Create the chip instance for the address range */
Range = L->End - L->Start;
CI = NewChipInstance (D->V.SVal, L->Start, Range, &L->Attributes);
/* Delete the "name" attribute */
FreeCfgData (D);
/* Assign the chip instance to memory */
MemAssignChip (CI, L->Start, Range);
}
/* Create the mirrors */
for (I = 0; I < CollCount (&Locations); ++I) {
const CfgData* D;
unsigned MirrorAddr; /* Mirror address */
unsigned Range; /* Address range for this chip */
unsigned Offs; /* Offset of the mirror */
const ChipInstance* CI; /* Original chip instance */
ChipInstance* MCI; /* Mirrored chip instance */
/* Get this location */
const Location* L = CollAtUnchecked (&Locations, I);
/* Skip non mirrors */
if (!LocationIsMirror (L)) {
continue;
}
/* Calculate the address range */
Range = L->End - L->Start;
/* Get the mirror address */
D = CollConstAt (&L->Attributes, 0);
MirrorAddr = (unsigned) D->V.IVal;
/* For simplicity, get the chip instance we're mirroring from the
* memory, instead of searching for the range in the list.
*/
CI = MemGetChip (MirrorAddr);
if (CI == 0) {
/* We are mirroring an unassigned address */
Error ("%s(%u): Mirroring an unassigned address",
CfgGetName (), L->Line);
}
/* Make sure we're mirroring the correct chip */
CHECK (MirrorAddr >= CI->Addr && MirrorAddr < CI->Addr + CI->Size);
/* Calculate the offset of the mirror */
Offs = MirrorAddr - CI->Addr;
/* Check if the mirror range is ok */
if (Offs + Range > CI->Size) {
Error ("%s(%u): Mirror range is too large", CfgGetName (), L->Line);
}
/* Clone the chip instance for the new location */
MCI = MirrorChipInstance (CI, L->Start - Offs);
/* Assign the chip instance to memory */
MemAssignChip (MCI, L->Start, Range);
}
}

View File

@ -292,10 +292,13 @@ int main (int argc, char* argv[])
Error ("Simulator configuration missing");
}
/* Initialize the simulated CPU memory */
MemInit ();
/* Read the config file */
CfgRead ();
MemInit ();
/* Initialize the CPU */
CPUInit ();
#if 0
CPURun ();

View File

@ -39,84 +39,25 @@
/* common */
#include "coll.h"
#include "xmalloc.h"
/* sim65 */
#include "chip.h"
#include "cputype.h"
#include "error.h"
#include "memory.h"
/*****************************************************************************/
/* Forwards */
/*****************************************************************************/
static void MemWrite (unsigned Addr, unsigned char Val);
/* Write one byte to the memory cell */
static unsigned char MemRead (unsigned Attr);
/* Read one memory cell */
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* RAM attributes */
#define RA_READFUNC_MASK 0x000F /* Up to 16 read functions */
#define RA_WRITEFUNC_MASK 0x00F0 /* Up to 16 write functions */
#define RA_INITIALIZED 0x0100 /* Memory cell is initialized */
#define RA_WPROT 0x0200 /* Memory cell is write protected */
/* Defines reader and writer functions */
#define RA_READFUNC_SHIFT 0
#define RA_WRITEFUNC_SHIFT 4
#define RA_READFUNC_MAX 16
#define RA_WRITEFUNC_MAX 16
/* Read/write function declarations */
typedef unsigned char (*ReadFunc) (unsigned Addr);
typedef void (*WriteFunc) (unsigned Addr, unsigned char Val);
static Collection ReadFuncs = STATIC_COLLECTION_INITIALIZER;
static Collection WriteFuncs = STATIC_COLLECTION_INITIALIZER;
/* Memory attributes and the memory */
static unsigned short MemAttr[0x10000];
static unsigned char Mem[0x10000];
/*****************************************************************************/
/* Internal functions */
/*****************************************************************************/
static void MemWrite (unsigned Addr, unsigned char Val)
/* Write one byte to the memory cell */
{
if (MemAttr[Addr] & RA_WPROT) {
Warning ("Writing to write protected memory at $%04X", Addr);
}
Mem[Addr] = Val;
MemAttr[Addr] |= RA_INITIALIZED;
}
static unsigned char MemRead (unsigned Addr)
/* Read one memory cell */
{
if ((MemAttr[Addr] & RA_INITIALIZED) == 0) {
/* We're reading a memory cell that was never written */
Warning ("Reading from uninitialized memory at $%04X", Addr);
}
return Mem[Addr];
}
/* Pointer to our memory */
static const ChipInstance** MemData = 0;
unsigned MemSize = 0;
@ -129,12 +70,15 @@ static unsigned char MemRead (unsigned Addr)
void MemWriteByte (unsigned Addr, unsigned char Val)
/* Write a byte to a memory location */
{
/* Get the writer function */
unsigned WI = (MemAttr[Addr] & RA_WRITEFUNC_MASK) >> RA_WRITEFUNC_SHIFT;
WriteFunc WF = CollAt (&WriteFuncs, WI);
/* Get the instance of the chip at this address */
const ChipInstance* CI = MemData[Addr];
/* Call the writer function */
WF (Addr, Val);
/* Check if the memory is mapped */
if (CI == 0) {
Warning ("Writing to unassigned memory at $%06X", Addr);
} else {
CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
}
}
@ -142,12 +86,16 @@ void MemWriteByte (unsigned Addr, unsigned char Val)
unsigned char MemReadByte (unsigned Addr)
/* Read a byte from a memory location */
{
/* Get the reader function */
unsigned RI = (MemAttr[Addr] & RA_READFUNC_MASK) >> RA_READFUNC_SHIFT;
ReadFunc RF = CollAt (&ReadFuncs, RI);
/* Get the instance of the chip at this address */
const ChipInstance* CI = MemData[Addr];
/* Call the reader function */
return RF (Addr);
/* Check if the memory is mapped */
if (CI == 0) {
Warning ("Reading from unassigned memory at $%06X", Addr);
return 0xFF;
} else {
return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
}
}
@ -163,9 +111,9 @@ unsigned MemReadWord (unsigned Addr)
unsigned MemReadZPWord (unsigned char Addr)
/* Read a word from the zero page. This function differs from ReadMemW in that
* the read will always be in the zero page, even in case of an address
* overflow.
*/
* the read will always be in the zero page, even in case of an address
* overflow.
*/
{
unsigned W = MemReadByte (Addr++);
return (W | (MemReadByte (Addr) << 8));
@ -173,46 +121,29 @@ unsigned MemReadZPWord (unsigned char Addr)
void MemLoad (const char* Filename, unsigned Addr, unsigned Size)
/* Load the contents of the given file into the RAM at the given address.
* If Size is not zero, we will read exactly Size bytes from the file and
* consider it an error if this is not possible. The memory attributes
* for the range is set to initialized.
*/
void MemAssignChip (const ChipInstance* CI, unsigned Addr, unsigned Range)
/* Assign a chip instance to memory locations */
{
unsigned BytesToRead;
unsigned BytesRead;
unsigned I;
/* Make sure, the addresses are in a valid range */
PRECONDITION (Addr + Range <= MemSize);
/* Open the file */
FILE* F = fopen (Filename, "rb");
if (F == 0) {
Error ("Cannot open `%s': %s", Filename, strerror (errno));
/* Assign the chip instance */
while (Range--) {
CHECK (MemData[Addr] == 0);
MemData[Addr++] = CI;
}
}
/* Set the number of bytes to read */
BytesToRead = 0x10000 - Addr;
if (Size > 0) {
CHECK (Size <= BytesToRead); /* Must not exceed RAM */
BytesToRead = Size;
}
/* Read data from the file */
BytesRead = fread (Mem + Addr, 1, BytesToRead, F);
if (ferror (F)) {
Error ("Error reading from `%s': %s", Filename, strerror (errno));
}
if (Size > 0 && BytesRead != Size) {
Error ("Cannot read %u bytes from `%s'", Size, Filename);
}
/* Close the file. Ignore errors, we were just reading. */
fclose (F);
const struct ChipInstance* MemGetChip (unsigned Addr)
/* Get the chip that is located at the given address (may return NULL). */
{
/* Make sure, the address is valid */
PRECONDITION (Addr < MemSize);
/* Set the memory attribute for the range to initialized */
for (I = 0; I < BytesRead; ++I) {
MemAttr[Addr+I] |= RA_INITIALIZED;
}
/* Return the chip instance */
return MemData[Addr];
}
@ -222,23 +153,21 @@ void MemInit (void)
{
unsigned I;
/* Clear the memory and it's attributes. Writing zeroes to the
* attribute array will cause any special flags to be reset and
* the default read and write functions to be used.
*/
for (I = 0; I < sizeof (Mem) / sizeof (Mem[0]); ++I) {
Mem[I] = 0;
/* Allocate memory depending on the CPU type */
switch (CPU) {
case CPU_6502:
case CPU_65C02:
MemSize = 0x10000;
break;
default:
Internal ("Unexpected CPU type: %d", CPU);
}
for (I = 0; I < sizeof (MemAttr) / sizeof (MemAttr[0]); ++I) {
MemAttr[I] = 0;
MemData = xmalloc (MemSize);
/* Clear the memory */
for (I = 0; I < MemSize; ++I) {
MemData[I] = 0;
}
/* Add the default reader and writer functions to the collection */
CollAppend (&ReadFuncs, MemRead);
CollAppend (&WriteFuncs, MemWrite);
MemWriteByte (0xFFFC, 0x00);
MemWriteByte (0xFFFD, 0x02);
}

View File

@ -39,13 +39,21 @@
/*****************************************************************************/
/* Data */
/* Data */
/*****************************************************************************/
/* Forwards */
struct ChipInstance;
/* Memory size of the CPU */
extern unsigned MemSize;
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
@ -65,12 +73,11 @@ unsigned MemReadZPWord (unsigned char Addr);
* overflow.
*/
void MemLoad (const char* Filename, unsigned Addr, unsigned Size);
/* Load the contents of the given file into the RAM at the given address.
* If Size is not zero, we will read exactly Size bytes from the file and
* consider it an error if this is not possible. The memory attributes
* for the range is set to initialized.
*/
void MemAssignChip (const struct ChipInstance* CI, unsigned Addr, unsigned Range);
/* Assign a chip instance to memory locations */
const struct ChipInstance* MemGetChip (unsigned Addr);
/* Get the chip that is located at the given address (may return NULL). */
void MemInit (void);
/* Initialize the memory subsystem */
@ -83,3 +90,4 @@ void MemInit (void);