]> git.sur5r.net Git - cc65/blobdiff - src/sim65/config.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / sim65 / config.c
index ce1a272f843afeac74f6fd032b3856682cfd0cd1..f595361fc8dfb59246385f8b85924e727bb373c9 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                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;
@@ -207,8 +195,8 @@ static void ParseMemory (void)
             CfgData* D = NewCfgData ();
             CfgNextTok ();
 
-           /* An optional assignment follows */
-           CfgOptionalAssign ();
+            /* An optional assignment follows */
+            CfgOptionalAssign ();
 
             /* Check and assign the attribute value */
             switch (CfgTok) {
@@ -235,47 +223,20 @@ static void ParseMemory (void)
             /* 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.
@@ -310,8 +271,8 @@ static void ParseMemory (void)
         /* 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 */
@@ -342,7 +303,7 @@ static void ParseMemory (void)
         /* 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",
@@ -363,8 +324,8 @@ static void ParseMemory (void)
         /* 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);
     }
 }
 
@@ -374,34 +335,39 @@ static void ParseConfig (void)
 /* 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);
 }