]> git.sur5r.net Git - cc65/commitdiff
Started to add a new .BANK instruction that allows access to a memory area
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 3 Jan 2012 21:41:34 +0000 (21:41 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 3 Jan 2012 21:41:34 +0000 (21:41 +0000)
attribute named "bank". Some error checks and a lot of testing is required.
Don't use for now.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5375 b7a2c559-68d2-44c3-8de9-860c34a00d81

18 files changed:
src/ca65/expr.c
src/ca65/expr.h
src/ca65/main.c
src/ca65/pseudo.c
src/ca65/scanner.c
src/ca65/segment.c
src/ca65/studyexpr.c
src/ca65/token.h
src/common/exprdefs.c
src/common/exprdefs.h
src/ld65/config.c
src/ld65/expr.c
src/ld65/memarea.c
src/ld65/memarea.h
src/ld65/scanner.h
src/ld65/segments.c
src/ld65/segments.h
src/od65/dump.c

index 25129decc7e1b292b675dbfde8b1b5f431b2ca28..3ee1ab47ed3d50ce9fd21bac5b6bc49d216769d2 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -65,7 +65,7 @@
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                          Data                                    */
 /*****************************************************************************/
 
 
@@ -238,6 +238,19 @@ static ExprNode* HiByte (ExprNode* Operand)
 
 
 
+static ExprNode* Bank (ExprNode* Operand)
+/* Return the bank of the given segmented expression */
+{
+    /* Generate the bank expression */
+    ExprNode* Expr = NewExprNode (EXPR_BANKRAW);
+    Expr->Left = Operand;
+
+    /* Return the result */
+    return Expr;
+}
+
+
+
 static ExprNode* BankByte (ExprNode* Operand)
 /* Return the bank byte of the given expression */
 {
@@ -321,6 +334,14 @@ static ExprNode* Symbol (SymEntry* S)
 
 
 
+ExprNode* FuncBank (void)
+/* Handle the .BANK builtin function */
+{
+    return Bank (Expression ());
+}
+
+
+
 ExprNode* FuncBankByte (void)
 /* Handle the .BANKBYTE builtin function */
 {
@@ -446,7 +467,7 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
        if (TokIsSep (CurTok.Tok)) {
            Error ("Unexpected end of line");
            return GenLiteral0 ();
-       }
+       }
 
        /* Get a node with this token */
        Node = NewTokNode ();
@@ -923,7 +944,8 @@ static ExprNode* Factor (void)
             N = HiByte (Factor ());
            break;
 
-        case TOK_BANK:
+        case TOK_XOR:
+            /* ^ means the bank byte of an expression */
             NextTok ();
             N = BankByte (Factor ());
             break;
@@ -934,6 +956,10 @@ static ExprNode* Factor (void)
                    ConsumeRParen ();
            break;
 
+        case TOK_BANK:
+            N = Function (FuncBank);
+            break;
+
         case TOK_BANKBYTE:
             N = Function (FuncBankByte);
             break;
@@ -1532,6 +1558,16 @@ static ExprNode* GenSectionExpr (unsigned SecNum)
 
 
 
+static ExprNode* GenBankExpr (unsigned SecNum)
+/* Return an expression node for the given bank */
+{
+    ExprNode* Expr = NewExprNode (EXPR_BANK);
+    Expr->V.SecNum = SecNum;
+    return Expr;
+}
+
+
+
 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
 /* Generate an addition from the two operands */
 {
@@ -1739,6 +1775,10 @@ ExprNode* CloneExpr (ExprNode* Expr)
            Clone = GenSectionExpr (Expr->V.SecNum);
            break;
 
+        case EXPR_BANK:
+            Clone = GenBankExpr (Expr->V.SecNum);
+            break;
+
         default:
             /* Generate a new node */
             Clone = NewExprNode (Expr->Op);
@@ -1754,6 +1794,70 @@ ExprNode* CloneExpr (ExprNode* Expr)
 
 
 
+ExprNode* FinalizeExpr (ExprNode* Expr, const Collection* LineInfos)
+/* Finalize an expression tree before it is written to the file. This will
+ * replace EXPR_BANKRAW nodes by EXPR_BANK nodes, and replace constant
+ * expressions by their result. The LineInfos are used when diagnosing errors.
+ * Beware: The expression tree may get replaced in future versions, so don't
+ * use Expr after calling this function.
+ */
+{
+    ExprDesc ED;
+
+    /* Check the type code */
+    switch (EXPR_NODETYPE (Expr->Op)) {
+
+        case EXPR_LEAFNODE:
+            /* Nothing to do for leaf nodes */
+            break;
+
+        case EXPR_BINARYNODE:
+            Expr->Left  = FinalizeExpr (Expr->Left, LineInfos);
+            Expr->Right = FinalizeExpr (Expr->Right, LineInfos);
+            /* FALLTHROUGH */
+
+        case EXPR_UNARYNODE:
+            Expr->Left = FinalizeExpr (Expr->Left, LineInfos);
+
+            /* Special handling for BANKRAW */
+            if (Expr->Op == EXPR_BANKRAW) {
+
+                /* Study the expression */
+                ED_Init (&ED);
+                StudyExpr (Expr->Left, &ED);
+
+                /* The expression must be ok and must have exactly one segment
+                 * reference.
+                 */
+                if (ED.Flags & ED_TOO_COMPLEX) {
+                    LIError (LineInfos,
+                             "Cannot evaluate expression");
+                } else if (ED.SecCount == 0) {
+                    LIError (LineInfos,
+                             ".BANK expects a segment reference");
+                } else if (ED.SecCount > 1 || ED.SecRef[0].Count > 1) {
+                    LIError (LineInfos,
+                             "Too many segment references in argument to .BANK");
+                } else {
+                    FreeExpr (Expr->Left);
+                    Expr->Op = EXPR_BANK;
+                    Expr->Left = 0;
+                    Expr->V.SecNum = ED.SecRef[0].Ref;
+                }
+
+                /* Cleanup */
+                ED_Done (&ED);
+
+            }
+            break;
+    }
+
+    /* Return the (partial) tree */
+    return Expr;
+}
+
+
+
 void WriteExpr (ExprNode* Expr)
 /* Write the given expression to the object file */
 {
@@ -1784,13 +1888,18 @@ void WriteExpr (ExprNode* Expr)
 
         case EXPR_SECTION:
             ObjWrite8 (EXPR_SECTION);
-           ObjWrite8 (Expr->V.SecNum);
+           ObjWriteVar (Expr->V.SecNum);
            break;
 
        case EXPR_ULABEL:
             WriteExpr (ULabResolve (Expr->V.IVal));
            break;
 
+        case EXPR_BANK:
+            ObjWrite8 (EXPR_BANK);
+            ObjWriteVar (Expr->V.SecNum);
+            break;
+
         default:
            /* Not a leaf node */
             ObjWrite8 (Expr->Op);
@@ -1818,7 +1927,7 @@ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
     }
 
     /* Check the type code */
-    switch (Expr->Op & EXPR_TYPEMASK) {
+    switch (EXPR_NODETYPE (Expr->Op)) {
 
         case EXPR_LEAFNODE:
             if (Expr->Op == EXPR_SYMBOL) {
index 694a3b1a63820633023d30859c95994cc515716d..989a322bbdba9acfaeae8237fcb822f09e720cc4 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -39,6 +39,7 @@
 
 
 /* common */
+#include "coll.h"
 #include "exprdefs.h"
 
 
@@ -140,6 +141,14 @@ ExprNode* CloneExpr (ExprNode* Expr);
  * nodes, it will not resolve them.
  */
 
+ExprNode* FinalizeExpr (ExprNode* Expr, const Collection* LineInfos);
+/* Finalize an expression tree before it is written to the file. This will
+ * replace EXPR_BANKRAW nodes by EXPR_BANK nodes, and replace constant
+ * expressions by their result. The LineInfos are used when diagnosing errors.
+ * Beware: The expression tree may get replaced in future versions, so don't
+ * use Expr after calling this function.
+ */
+
 void WriteExpr (ExprNode* Expr);
 /* Write the given expression to the object file */
 
index b86147a2d1911f2efa510abfac415333e5390687..f6fa1ecc2fffe47c1ad28f534b4a45d406ee5329 100644 (file)
@@ -1061,7 +1061,7 @@ int main (int argc, char* argv [])
         SegDone ();
     }
 
-    /* If we didn't have any errors, check       the assertions */
+    /* If we didn't have any errors, check the assertions */
     if (ErrorCount == 0) {
         CheckAssertions ();
     }
index 365fd5b79c0afc897019d3b001e5b81e46fc5c1c..480fc61865d5cdb7d5d1ce89582ca5c1547a1ecf 100644 (file)
@@ -1990,6 +1990,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoASCIIZ        },
     { ccNone,           DoAssert        },
     { ccNone,          DoAutoImport    },
+    { ccNone,           DoUnexpected    },      /* .BANK */
     { ccNone,          DoUnexpected    },      /* .BANKBYTE */
     { ccNone,           DoBankBytes     },
     { ccNone,          DoUnexpected    },      /* .BLANK */
index 04f217ceb51d7ea60532d4c0f1ce68dcc1a51856..94f517483db338d74bb0176c872b24ac581fca1a 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -141,6 +141,7 @@ struct DotKeyword {
     { ".ASCIIZ",               TOK_ASCIIZ      },
     { ".ASSERT",        TOK_ASSERT      },
     { ".AUTOIMPORT",   TOK_AUTOIMPORT  },
+    { ".BANK",          TOK_BANK        },
     { ".BANKBYTE",      TOK_BANKBYTE    },
     { ".BANKBYTES",     TOK_BANKBYTES   },
     { ".BITAND",       TOK_AND         },
index 9bbccc02496596c7bbd4dda853c41939e1bd212d..0411f4d6e93d9aaca317d0faca86f7a0cede791f 100644 (file)
@@ -407,8 +407,11 @@ void SegDone (void)
 
                } else {
 
+                    /* Finalize the expression */
+                    F->V.Expr = FinalizeExpr (F->V.Expr, &F->LI);        
+
                     /* Simplify the expression */
-                    F->V.Expr = SimplifyExpr (F->V.Expr, &ED);
+                    /* ### F->V.Expr = SimplifyExpr (F->V.Expr, &ED); */
 
                    /* We cannot evaluate the expression now, leave the job for
                     * the linker. However, we can check if the address size
index b21f3b28bbc375b43a2648b14ee987eb77096295..b9f8d194651a7cb996450d1bbe5623fa9ef8743f 100644 (file)
@@ -1095,6 +1095,33 @@ static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
 
 
 
+static void StudyBank (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BANK expression node */
+{
+    /* Get the section reference */
+    ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
+
+    /* Update the data and the address size */
+    ++SecRef->Count;
+
+    /* The expression is always linker evaluated, so invalidate it */
+    ED_Invalidate (D);
+}
+
+
+
+static void StudyBankRaw (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BANKRAW expression node */
+{
+    /* Study the expression extracting section references */
+    StudyExprInternal (Expr->Left, D);
+
+    /* The expression is always linker evaluated, so invalidate it */
+    ED_Invalidate (D);
+}
+
+
+
 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
 /* Study an EXPR_BYTE0 expression node */
 {
@@ -1231,6 +1258,10 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
             StudyULabel (Expr, D);
             break;
 
+        case EXPR_BANK:
+            StudyBank (Expr, D);
+            break;
+
        case EXPR_PLUS:
             StudyPlus (Expr, D);
            break;
@@ -1331,6 +1362,10 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
             StudyBoolNot (Expr, D);
             break;
 
+        case EXPR_BANKRAW:
+            StudyBankRaw (Expr, D);
+            break;
+
         case EXPR_BYTE0:
             StudyByte0 (Expr, D);
             break;
index ad22b885cd6fea9dc98e6735814dea6be79320c7..eba24cdfaac062c7c70959c088302c678289ea5c 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2007-2011, Ullrich von Bassewitz                                      */
+/* (C) 2007-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -90,9 +90,8 @@ typedef enum token_t {
     TOK_STAR = TOK_MUL,        /* Alias */
     TOK_DIV,           /* / */
     TOK_MOD,           /* ! */
-    TOK_OR,            /* | */
+    TOK_OR,            /* | */
     TOK_XOR,           /* ^ */
-    TOK_BANK = TOK_XOR, /* Alias */
     TOK_AND,           /* & */
     TOK_SHL,           /* << */
     TOK_SHR,           /* >> */
@@ -128,6 +127,7 @@ typedef enum token_t {
     TOK_ASCIIZ,
     TOK_ASSERT,
     TOK_AUTOIMPORT,
+    TOK_BANK,
     TOK_BANKBYTE,
     TOK_BANKBYTES,
     TOK_BLANK,
index 24ece516d638234ec1aa64e3cbc7c966ee62c9c2..dfee4084ff4029b88920f5cd36ab0d94d3494e42 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -78,6 +78,10 @@ static void InternalDumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym
            printf (" SEG");
            break;
 
+        case EXPR_MEMAREA:
+            printf (" MEM");
+            break;
+
                case EXPR_PLUS:
            printf (" +");
            break;
@@ -178,6 +182,10 @@ static void InternalDumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym
            printf (" BOOL_NOT");
            break;
 
+        case EXPR_BANK:
+            printf (" BANK");
+            break;
+
                case EXPR_BYTE0:
            printf (" BYTE0");
            break;
index db85a59342be082c49738ccb04d3dbeb85148408..2e1ac6e5a58bf8308e0819f1db6ca7669c657049 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -60,6 +60,7 @@
 #define EXPR_SEGMENT                   (EXPR_LEAFNODE | 0x04)  /* Linker only */
 #define EXPR_MEMAREA                   (EXPR_LEAFNODE | 0x05)  /* Linker only */
 #define EXPR_ULABEL            (EXPR_LEAFNODE | 0x06)  /* Assembler only */
+#define EXPR_BANK               (EXPR_LEAFNODE | 0x07)
 
 /* Binary operations, left and right hand sides are valid */
 #define EXPR_PLUS                      (EXPR_BINARYNODE | 0x01)
 #define EXPR_NOT                       (EXPR_UNARYNODE | 0x02)
 #define EXPR_SWAP                      (EXPR_UNARYNODE | 0x03)
 #define EXPR_BOOLNOT           (EXPR_UNARYNODE | 0x04)
+#define EXPR_BANKRAW            (EXPR_UNARYNODE | 0x05) /* Assembler only */
 
 #define EXPR_BYTE0             (EXPR_UNARYNODE | 0x08)
 #define EXPR_BYTE1             (EXPR_UNARYNODE | 0x09)
-#define EXPR_BYTE2             (EXPR_UNARYNODE | 0x0A)
-#define EXPR_BYTE3             (EXPR_UNARYNODE | 0x0B)
-#define EXPR_WORD0             (EXPR_UNARYNODE | 0x0C)
-#define EXPR_WORD1             (EXPR_UNARYNODE | 0x0D)
+#define EXPR_BYTE2             (EXPR_UNARYNODE | 0x0A)
+#define EXPR_BYTE3             (EXPR_UNARYNODE | 0x0B)
+#define EXPR_WORD0             (EXPR_UNARYNODE | 0x0C)
+#define EXPR_WORD1             (EXPR_UNARYNODE | 0x0D)
 
 
 
@@ -121,9 +123,10 @@ struct ExprNode {
 
 
 /* Macros to determine the expression type */
-#define EXPR_IS_LEAF(Op)               (((Op) & EXPR_TYPEMASK) == EXPR_LEAFNODE)
-#define EXPR_IS_UNARY(Op)      (((Op) & EXPR_TYPEMASK) == EXPR_UNARYNODE)
-#define EXPR_IS_BINARY(OP)     (((Op) & EXPR_TYPEMASK) == EXPR_BINARYNODE)
+#define EXPR_NODETYPE(Op)       ((Op) & EXPR_TYPEMASK)
+#define EXPR_IS_LEAF(Op)               (EXPR_NODETYPE (Op) == EXPR_LEAFNODE)
+#define EXPR_IS_UNARY(Op)      (EXPR_NODETYPE (Op) == EXPR_UNARYNODE)
+#define EXPR_IS_BINARY(OP)     (EXPR_NODETYPE (Op) == EXPR_BINARYNODE)
 
 
 
index e9ee811390bb9e07a2d9470f447b4025e73c1881..c4a9f3d9cb83a8683b3625e61beb8486d25204d4 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -102,6 +102,7 @@ static Collection       MemoryAreas = STATIC_COLLECTION_INITIALIZER;
 #define MA_DEFINE              0x0010
 #define MA_FILL                0x0020
 #define MA_FILLVAL             0x0040
+#define MA_BANK         0x0080
 
 /* Segment list */
 static Collection       SegDescList = STATIC_COLLECTION_INITIALIZER;
@@ -405,13 +406,14 @@ static void ParseMemory (void)
 /* Parse a MEMORY section */
 {
     static const IdentTok Attributes [] = {
-               {   "START",    CFGTOK_START    },
-       {   "SIZE",     CFGTOK_SIZE     },
-        {   "TYPE",     CFGTOK_TYPE     },
-        {   "FILE",     CFGTOK_FILE     },
+        {   "BANK",     CFGTOK_BANK     },
         {   "DEFINE",   CFGTOK_DEFINE   },
+        {   "FILE",     CFGTOK_FILE     },
        {   "FILL",     CFGTOK_FILL     },
                {   "FILLVAL",  CFGTOK_FILLVAL  },
+       {   "SIZE",     CFGTOK_SIZE     },
+               {   "START",    CFGTOK_START    },
+        {   "TYPE",     CFGTOK_TYPE     },
     };
     static const IdentTok Types [] = {
                {   "RO",       CFGTOK_RO       },
@@ -442,21 +444,17 @@ static void ParseMemory (void)
            /* Check which attribute was given */
            switch (AttrTok) {
 
-               case CFGTOK_START:
-                   FlagAttr (&M->Attr, MA_START, "START");
-                    M->StartExpr = CfgExpr ();
-                   break;
-
-               case CFGTOK_SIZE:
-                   FlagAttr (&M->Attr, MA_SIZE, "SIZE");
-                   M->SizeExpr = CfgExpr ();
+               case CFGTOK_BANK:
+                   FlagAttr (&M->Attr, MA_BANK, "BANK");
+                   M->BankExpr = CfgExpr ();
                    break;
 
-               case CFGTOK_TYPE:
-                   FlagAttr (&M->Attr, MA_TYPE, "TYPE");
-                   CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
-                   if (CfgTok == CFGTOK_RO) {
-                       M->Flags |= MF_RO;
+               case CFGTOK_DEFINE:
+                   FlagAttr (&M->Attr, MA_DEFINE, "DEFINE");
+                   /* Map the token to a boolean */
+                   CfgBoolToken ();
+                   if (CfgTok == CFGTOK_TRUE) {
+                       M->Flags |= MF_DEFINE;
                    }
                     CfgNextTok ();
                    break;
@@ -469,16 +467,6 @@ static void ParseMemory (void)
                     CfgNextTok ();
                    break;
 
-               case CFGTOK_DEFINE:
-                   FlagAttr (&M->Attr, MA_DEFINE, "DEFINE");
-                   /* Map the token to a boolean */
-                   CfgBoolToken ();
-                   if (CfgTok == CFGTOK_TRUE) {
-                       M->Flags |= MF_DEFINE;
-                   }
-                    CfgNextTok ();
-                   break;
-
                case CFGTOK_FILL:
                    FlagAttr (&M->Attr, MA_FILL, "FILL");
                    /* Map the token to a boolean */
@@ -494,6 +482,25 @@ static void ParseMemory (void)
                    M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF);
                    break;
 
+               case CFGTOK_SIZE:
+                   FlagAttr (&M->Attr, MA_SIZE, "SIZE");
+                   M->SizeExpr = CfgExpr ();
+                   break;
+
+               case CFGTOK_START:
+                   FlagAttr (&M->Attr, MA_START, "START");
+                    M->StartExpr = CfgExpr ();
+                   break;
+
+               case CFGTOK_TYPE:
+                   FlagAttr (&M->Attr, MA_TYPE, "TYPE");
+                   CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE");
+                   if (CfgTok == CFGTOK_RO) {
+                       M->Flags |= MF_RO;
+                   }
+                    CfgNextTok ();
+                   break;
+
                default:
                    FAIL ("Unexpected attribute token");
 
@@ -1859,16 +1866,30 @@ unsigned CfgProcess (void)
                     Addr = NewAddr;
                 }
 
+                /* If the segment has .BANK expressions referring to it, it 
+                 * must be placed into a memory area that has the bank 
+                 * attribute.
+                 */
+                if (S->Seg->BankRef && M->BankExpr == 0) {
+                    CfgError (GetSourcePos (S->LI),
+                              "Segment `%s' is refered to by .BANK, but the "
+                              "memory area `%s' it is placed into has no BANK "
+                              "attribute",
+                              GetString (S->Name),
+                              GetString (M->Name));
+                }
+
                 /* Set the start address of this segment, set the readonly flag
                  * in the segment and and remember if the segment is in a
                  * relocatable file or not.
                  */
                 S->Seg->PC = Addr;
                 S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
-                S->Seg->Relocatable = M->Relocatable;
 
-                /* Remember that this segment is placed */
-                S->Seg->Placed = 1;
+                /* Remember the run memory for this segment, which is also a
+                 * flag that the segment has been placed.
+                 */
+                S->Seg->MemArea = M;
 
             } else if (S->Load == M) {
 
index d671914b7a091fe824ec7c7ab0a6f50f73a421cf..ddc53d05d739e774e61ca2349352d069cd97500d 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -72,7 +72,7 @@ ExprNode* NewExprNode (ObjData* O, unsigned char Op)
 
 static void FreeExprNode (ExprNode* E)
 /* Free a node */
-{
+{         
     /* Free the memory */
     xfree (E);
 }
@@ -99,6 +99,7 @@ int IsConstExpr (ExprNode* Root)
     int         Const;
     Export*     E;
     Section*    S;
+    MemoryArea* M;
 
     if (EXPR_IS_LEAF (Root->Op)) {
        switch (Root->Op) {
@@ -111,7 +112,7 @@ int IsConstExpr (ExprNode* Root)
                        E = GetExprExport (Root);
                /* If this export has a mark set, we've already encountered it.
                 * This means that the export is used to define it's own value,
-                * which in turn means, that we have a circular reference.
+                * which in turn means, that we have a circular reference.
                 */
                if (ExportHasMark (E)) {
                     CircularRefError (E);
@@ -119,8 +120,8 @@ int IsConstExpr (ExprNode* Root)
                } else {
                    MarkExport (E);
                    Const = IsConstExport (E);
-                   UnmarkExport (E);
-               }
+                   UnmarkExport (E);
+               }
                return Const;
 
             case EXPR_SECTION:
@@ -128,22 +129,35 @@ int IsConstExpr (ExprNode* Root)
                  * not relocatable and already placed.
                  */
                 S = GetExprSection (Root);
-                return !S->Seg->Relocatable && S->Seg->Placed;
+                M = S->Seg->MemArea;
+                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;
 
             case EXPR_SEGMENT:
                 /* A segment is const if it is not relocatable and placed */
-                return !Root->V.Seg->Relocatable && Root->V.Seg->Placed;
+                M = Root->V.Seg->MemArea;
+                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;
 
             case EXPR_MEMAREA:
                 /* A memory area is const if it is not relocatable and placed */
                 return !Root->V.Mem->Relocatable &&
                        (Root->V.Mem->Flags & MF_PLACED);
 
+            case EXPR_BANK:
+                /* A bank expression is const if the section, the segment is
+                 * part of, is already placed, and the memory area has a
+                 * constant bank expression.
+                 */
+                S = GetExprSection (Root);
+                M = S->Seg->MemArea;
+                return M != 0 && (M->Flags & MF_PLACED) != 0 &&
+                       M->BankExpr != 0 && IsConstExpr (M->BankExpr);
+
            default:
                 /* Anything else is not const */
                return 0;
 
        }
+
     } else if (EXPR_IS_UNARY (Root->Op)) {
 
        return IsConstExpr (Root->Left);
@@ -201,7 +215,7 @@ Import* GetExprImport (ExprNode* Expr)
      * import pointer.
      */
     if (Expr->Obj) {
-       /* Return the Import */
+       /* Return the Import */
                return GetObjImport (Expr->Obj, Expr->V.ImpNum);
     } else {
        return Expr->V.Imp;
@@ -226,7 +240,7 @@ Section* GetExprSection (ExprNode* Expr)
 /* Get the segment for a section expression node */
 {
     /* Check that this is really a section node */
-    PRECONDITION (Expr->Op == EXPR_SECTION);
+    PRECONDITION (Expr->Op == EXPR_SECTION || Expr->Op == EXPR_BANK);
 
     /* If we have an object file, get the section from it, otherwise
      * (internally generated expressions), get the section from the
@@ -245,9 +259,11 @@ Section* GetExprSection (ExprNode* Expr)
 long GetExprVal (ExprNode* Expr)
 /* Get the value of a constant expression */
 {
-    long Right, Left, Val;
-    Section* S;
-    Export* E;
+    long        Right;
+    long        Left;
+    long        Val;
+    Section*    S;
+    Export*     E;
 
     switch (Expr->Op) {
 
@@ -281,6 +297,10 @@ long GetExprVal (ExprNode* Expr)
         case EXPR_MEMAREA:
             return Expr->V.Mem->Start;
 
+        case EXPR_BANK:
+                   S = GetExprSection (Expr);
+            return GetExprVal (S->Seg->MemArea->BankExpr);
+
                case EXPR_PLUS:
            return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
 
@@ -345,8 +365,8 @@ long GetExprVal (ExprNode* Expr)
        case EXPR_BOOLOR:
            return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
 
-       case EXPR_BOOLXOR:
-           return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
+       case EXPR_BOOLXOR:
+           return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
 
         case EXPR_MAX:
             Left = GetExprVal (Expr->Left);
@@ -359,16 +379,16 @@ long GetExprVal (ExprNode* Expr)
             return (Left < Right)? Left : Right;
 
                case EXPR_UNARY_MINUS:
-           return -GetExprVal (Expr->Left);
+           return -GetExprVal (Expr->Left);
 
                case EXPR_NOT:
-           return ~GetExprVal (Expr->Left);
+           return ~GetExprVal (Expr->Left);
 
         case EXPR_SWAP:
-           Left = GetExprVal (Expr->Left);
-           return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
+           Left = GetExprVal (Expr->Left);
+           return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
 
-       case EXPR_BOOLNOT:
+       case EXPR_BOOLNOT:
                    return !GetExprVal (Expr->Left);
 
                case EXPR_BYTE0:
@@ -569,11 +589,12 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
 /* Read an expression from the given file */
 {
     ExprNode* Expr;
+    Section*  S;
 
     /* Read the node tag and handle NULL nodes */
     unsigned char Op = Read8 (F);
     if (Op == EXPR_NULL) {
-       return 0;
+       return 0;
     }
 
     /* Create a new node */
@@ -581,20 +602,30 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
 
     /* Check the tag and handle the different expression types */
     if (EXPR_IS_LEAF (Op)) {
-       switch (Op) {
+       switch (Op) {
 
-           case EXPR_LITERAL:
-               Expr->V.IVal = Read32Signed (F);
-               break;
+           case EXPR_LITERAL:
+               Expr->V.IVal = Read32Signed (F);
+               break;
 
-           case EXPR_SYMBOL:
-               /* Read the import number */
+           case EXPR_SYMBOL:
+               /* Read the import number */
                Expr->V.ImpNum = ReadVar (F);
                break;
 
            case EXPR_SECTION:
-               /* Read the segment number */
-               Expr->V.SecNum = Read8 (F);
+               /* Read the section number */
+               Expr->V.SecNum = ReadVar (F);
+               break;
+
+            case EXPR_BANK:
+               /* Read the section number */
+               Expr->V.SecNum = ReadVar (F);
+                /* Mark the section so we know it must be placed into a memory
+                 * area with the "bank" attribute.
+                 */
+                S = GetExprSection (Expr);
+                S->Seg->BankRef = 1;
                break;
 
            default:
@@ -624,12 +655,12 @@ int EqualExpr (ExprNode* E1, ExprNode* E2)
        return 0;
     }
     if (E1 == 0) {
-       return 1;
+       return 1;
     }
 
     /* Both pointers not NULL, check OP */
     if (E1->Op != E2->Op) {
-       return 0;
+       return 0;
     }
 
     /* OPs are identical, check data for leafs, or subtrees */
index 3e48ae285ba9ca09d430240431a691383f504e5f..4dbf8b3f62e3cb7884722194aaa7dd4cb6828bfd 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2010-2011, Ullrich von Bassewitz                                      */
+/* (C) 2010-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -63,6 +63,7 @@ MemoryArea* NewMemoryArea (const FilePos* Pos, unsigned Name)
     M->Start       = 0;
     M->SizeExpr    = 0;
     M->Size        = 0;
+    M->BankExpr    = 0;
     M->FillLevel   = 0;
     M->FillVal     = 0;
     M->Relocatable = 0;
index 4d3135fa36f8d8fd977d9ac2425ab5e7dd3fb31e..936edc3f77ddc853f4183cdb458d8a015cfa6de1 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2010-2011, Ullrich von Bassewitz                                      */
+/* (C) 2010-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -68,6 +68,7 @@ struct MemoryArea {
     unsigned long              Start;          /* Start address */
     struct ExprNode*    SizeExpr;       /* Expression for size */
     unsigned long              Size;           /* Length of memory section */
+    struct ExprNode*    BankExpr;       /* Expression for bank */
     unsigned long              FillLevel;      /* Actual fill level of segment */
     unsigned char      FillVal;        /* Value used to fill rest of seg */
     unsigned char       Relocatable;    /* Memory area is relocatable */
index 1cb71181c397f366c14c6900e5c309ab13a73222..cd69d644ee524208321f7cd9235ac88ebeb26cc1 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -84,6 +84,7 @@ typedef enum {
     CFGTOK_TYPE,
     CFGTOK_FILE,
     CFGTOK_DEFINE,
+    CFGTOK_BANK,
     CFGTOK_FILL,
     CFGTOK_FILLVAL,
     CFGTOK_EXPORT,
index d3fe119c9a21ccd9068bffe2fcbfd9da0696ffa6..b67d0e2213e644911a0f01b025df26f5b6ad5729 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -94,6 +94,7 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
     S->Name        = Name;
     S->Next       = 0;
     S->Sections    = EmptyCollection;
+    S->MemArea     = 0;
     S->PC         = 0;
     S->Size               = 0;
     S->OutputName  = 0;
@@ -102,10 +103,9 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
     S->FillVal    = 0;
     S->AddrSize    = AddrSize;
     S->ReadOnly    = 0;
-    S->Relocatable = 0;
-    S->Placed      = 0;
     S->Dumped      = 0;
-
+    S->BankRef     = 0;
+                
     /* Insert the segment into the segment list and assign the segment id */
     S->Id = CollCount (&SegmentList);
     CollAppend (&SegmentList, S);
index 86caa209489b2400d23fff8bb19636b0b5952eb1..295c75cdd05db24d09d9d047bfeee32981a048a8 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -52,6 +52,9 @@
 
 
 
+/* Forwards */
+struct MemoryArea;
+
 /* Segment structure */
 typedef struct Segment Segment;
 struct Segment {
@@ -59,6 +62,7 @@ struct Segment {
     unsigned            Id;             /* Segment id for debug info */
     Segment*           Next;           /* Hash list */
     Collection          Sections;       /* Sections in this segment */
+    struct MemoryArea*  MemArea;        /* Run memory area once placed */
     unsigned long      PC;             /* PC were this segment is located */
     unsigned long      Size;           /* Size of data so far */
     const char*         OutputName;     /* Name of output file or NULL */
@@ -67,9 +71,8 @@ struct Segment {
     unsigned char      FillVal;        /* Value to use for fill bytes */
     unsigned char      AddrSize;       /* Address size of segment */
     unsigned char       ReadOnly;       /* True for readonly segments (config) */
-    unsigned char       Relocatable;    /* True if the segment is relocatable */
-    unsigned char       Placed;         /* Did we place this segment already? */
     unsigned char              Dumped;         /* Did we dump this segment? */
+    unsigned char       BankRef;        /* We need the bank of this segment */
 };
 
 
index 66af0b5432c17d36489e8e804776d3bae93feeab..92ead85c1357618e376d49614546584cbf9b18f0 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2011, Ullrich von Bassewitz                                      */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -173,8 +173,9 @@ static void SkipExpr (FILE* F)
                break;
 
            case EXPR_SECTION:
+            case EXPR_BANK:
                /* Read the segment number */
-               (void) Read8 (F);
+               (void) ReadVar (F);
                break;
 
            default: