/*****************************************************************************/
/* */
-/* config.c */
+/* config.c */
/* */
/* Configuration file parsing for the sim65 6502 simulator */
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "xmalloc.h"
/* sim65 */
+#include "addrspace.h"
#include "cfgdata.h"
#include "chip.h"
#include "error.h"
#include "global.h"
-#include "memory.h"
+#include "location.h"
#include "scanner.h"
#include "config.h"
/*****************************************************************************/
-/* Data */
+/* Code */
/*****************************************************************************/
-/* List of all memory locations */
-static Collection Locations;
-
-/* One memory location */
-typedef struct Location Location;
-struct Location {
- 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 */
-};
-
-
-
-/*****************************************************************************/
-/* struct CfgData */
-/*****************************************************************************/
+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 CfgDataCheckType (const CfgData* D, unsigned Type)
-/* Check the config data type */
+static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
+/* Check that a mandatory attribute was given */
{
- if (D->Type != Type) {
- Error ("%s(%u): Attribute `%s' has invalid type",
- CfgGetName (), D->Line, D->Attr);
+ if ((Attr & Mask) == 0) {
+ CfgError ("%s attribute is missing", Name);
}
}
-/*****************************************************************************/
-/* struct Location */
-/*****************************************************************************/
-
+static void ParseCPU (void)
+/* Parse a CPU section */
+{
+ static const IdentTok Attributes [] = {
+ { "TYPE", CFGTOK_TYPE },
+ { "ADDRSPACE", CFGTOK_ADDRSPACE },
+ };
+ enum {
+ atNone = 0x0000,
+ atType = 0x0001,
+ atAddrSpace = 0x0002
+ };
+ unsigned Attr = 0;
+ unsigned long Size = 0;
-static Location* NewLocation (unsigned long Start, unsigned long End)
-/* Create a new location, initialize and return it */
-{
- /* Allocate memory */
- Location* L = xmalloc (sizeof (Location));
-
- /* Initialize the fields */
- L->Start = Start;
- L->End = End;
- L->Attributes = EmptyCollection;
- L->Line = CfgErrorLine;
- L->Col = CfgErrorCol;
-
- /* Return the new struct */
- return L;
-}
+ while (CfgTok == CFGTOK_IDENT) {
+ cfgtok_t AttrTok;
+ CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
+ AttrTok = CfgTok;
-static int CmpLocations (void* Data attribute ((unused)),
- const void* lhs, const void* rhs)
-/* Compare function for CollSort */
-{
- /* Cast the object pointers */
- const Location* Left = (const Location*) rhs;
- const Location* Right = (const Location*) lhs;
-
- /* Do the compare */
- if (Left->Start < Right->Start) {
- return 1;
- } else if (Left->Start > Right->Start) {
- return -1;
- } else {
- return 0;
- }
-}
+ /* An optional assignment follows */
+ CfgNextTok ();
+ CfgOptionalAssign ();
+ /* Check which attribute was given */
+ switch (AttrTok) {
+ case CFGTOK_TYPE:
+ FlagAttr (&Attr, atType, "TYPE");
+ CfgAssureIdent ();
+ /* ### */
+ break;
-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 = CfgDataFind (&L->Attributes, AttrName);
- if (I < 0) {
- Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
- }
- return I;
-}
+ case CFGTOK_ADDRSPACE:
+ FlagAttr (&Attr, atAddrSpace, "ADDRSPACE");
+ CfgAssureInt ();
+ CfgRangeCheck (0x1000, 0x1000000);
+ Size = CfgIVal;
+ break;
+ default:
+ FAIL ("Unexpected attribute token");
+ }
-static int LocationIsMirror (const Location* L)
-/* Return true if the given location is a mirror of another one. */
-{
- /* Find the "mirror" attribute */
- return (CfgDataFind (&L->Attributes, "mirror") >= 0);
-}
+ /* Skip the attribute value and an optional comma */
+ CfgNextTok ();
+ CfgOptionalComma ();
+ }
+ /* Must have some attributes */
+ AttrCheck (Attr, atType, "TYPE");
+ AttrCheck (Attr, atAddrSpace, "ADDRSPACE");
+ /* Create the system using the specified CPU */
+ System = NewSystem (NewCPU ("6502", Size));
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
+ /* Skip the semicolon */
+ CfgConsumeSemi ();
+}
-static void ParseMemory (void)
-/* Parse a MEMORY section */
+static void ParseAddrSpace (void)
+/* Parse a ADDRSPACE section */
{
unsigned I;
- const Location* Last;
+ /* CPU must be defined before the address space */
+ if (System == 0) {
+ CfgError ("CPU must be defined before address space definitions");
+ }
+ /* Parse addresses */
while (CfgTok == CFGTOK_INTCON) {
Location* L;
CfgData* D = NewCfgData ();
CfgNextTok ();
- /* An optional assignment follows */
- CfgOptionalAssign ();
+ /* An optional assignment follows */
+ CfgOptionalAssign ();
/* Check and assign the attribute value */
switch (CfgTok) {
/* Add the attribute to the location */
CollAppend (&L->Attributes, D);
- /* Skip the attribute value and an optional comma */
- CfgNextTok ();
- CfgOptionalComma ();
- }
+ /* Skip the attribute value and an optional comma */
+ CfgNextTok ();
+ CfgOptionalComma ();
+ }
- /* Skip the semicolon */
- CfgConsumeSemi ();
+ /* Skip the semicolon */
+ CfgConsumeSemi ();
}
/* Sort all memory locations */
- CollSort (&Locations, CmpLocations, 0);
-
- /* Check for overlaps and other problems */
- Last = 0;
- for (I = 0; I < CollCount (&Locations); ++I) {
-
- /* Get this location */
- const Location* L = CollAtUnchecked (&Locations, I);
-
- /* Check for an overlap with the following location */
- if (Last && Last->End >= L->Start) {
- Error ("%s(%u): Address range overlap (overlapping entry is in line %u)",
- CfgGetName(), L->Line, Last->Line);
- }
-
- /* If the location is a mirror, it must not have other attributes,
- * and the mirror attribute must be an integer.
- */
- if (LocationIsMirror (L)) {
- const CfgData* D;
- if (CollCount (&L->Attributes) > 1) {
- Error ("%s(%u): Location at address $%06X is a mirror "
- "but has attributes", CfgGetName(), L->Line, L->Start);
- }
- D = CollConstAt (&L->Attributes, 0);
- CfgDataCheckType (D, CfgDataNumber);
- }
+ LocationSort (&Locations);
- /* Remember this entry */
- Last = L;
- }
+ /* Check the locations for overlaps and other problems */
+ LocationCheck (&Locations);
/* 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.
/* Delete the "name" attribute */
FreeCfgData (D);
- /* Assign the chip instance to memory */
- MemAssignChip (CI, L->Start, Range);
+ /* Assign the chip instance to address space */
+ ASAssignChip (CPUInstance->AS, CI, L->Start, Range);
}
/* Create the mirrors */
/* For simplicity, get the chip instance we're mirroring from the
* memory, instead of searching for the range in the list.
*/
- CI = MemGetChip (MirrorAddr);
+ CI = ASGetChip (MirrorAddr);
if (CI == 0) {
/* We are mirroring an unassigned address */
Error ("%s(%u): Mirroring an unassigned address",
/* 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);
+ /* Assign the chip instance to address space */
+ ASAssignChip (CPUInstance->AS, MCI, L->Start, Range);
}
}
/* Parse the config file */
{
static const IdentTok BlockNames [] = {
- { "MEMORY", CFGTOK_MEMORY },
+ { "ADDRSPACE", CFGTOK_ADDRSPACE },
+ { "CPU", CFGTOK_CPU },
};
cfgtok_t BlockTok;
do {
- /* Read the block ident */
- CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
- BlockTok = CfgTok;
- CfgNextTok ();
+ /* Read the block ident */
+ CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
+ BlockTok = CfgTok;
+ CfgNextTok ();
- /* Expected a curly brace */
- CfgConsume (CFGTOK_LCURLY, "`{' expected");
+ /* Expected a curly brace */
+ CfgConsume (CFGTOK_LCURLY, "`{' expected");
- /* Read the block */
- switch (BlockTok) {
+ /* Read the block */
+ switch (BlockTok) {
- case CFGTOK_MEMORY:
- ParseMemory ();
+ case CFGTOK_ADDRSPACE:
+ ParseAddrSpace ();
break;
- default:
- FAIL ("Unexpected block token");
+ case CFGTOK_CPU:
+ ParseCPU ();
+ break;
+
+ default:
+ FAIL ("Unexpected block token");
- }
+ }
- /* Skip closing brace */
- CfgConsume (CFGTOK_RCURLY, "`}' expected");
+ /* Skip closing brace */
+ CfgConsumeRCurly ();
} while (CfgTok != CFGTOK_EOF);
}