]> git.sur5r.net Git - cc65/commitdiff
Finish support for .BANK.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 4 Jan 2012 22:45:26 +0000 (22:45 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 4 Jan 2012 22:45:26 +0000 (22:45 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@5384 b7a2c559-68d2-44c3-8de9-860c34a00d81

doc/ca65.sgml
doc/ld65.sgml
src/ca65/segment.c
src/ld65/config.c
src/ld65/expr.c
src/ld65/segments.c
src/ld65/segments.h
src/od65/dump.c

index 5d65584a9cb91bc6519e796fd4e7118b7a9321a4..8dc71c4df17fae2725897270d978e25e7bf4cc0b 100644 (file)
@@ -1275,6 +1275,49 @@ Pseudo functions expect their arguments in parenthesis, and they have a result,
 either a string or an expression.
 
 
+<sect1><tt>.BANK</tt><label id=".BANK"><p>
+
+  The <tt/.BANK/ function is used to support systems with banked memory. The
+  argument is an expression with exactly one segment reference - usually a
+  label. The function result is the value of the <tt/bank/ attribute assigned
+  to the run memory area of the segment. Please see the linker documentation
+  for more information about memory areas and their attributes.
+
+  The value of <tt/.BANK/ can be used to switch memory so that a memory bank
+  containing specific data is available.
+
+  The <tt/bank/ attribute is a 32 bit integer and so is the result of the
+  <tt/.BANK/ function. You will have to use <tt><ref id=".LOBYTE"
+  name=".LOBYTE"></tt> or similar functions to address just part of it.
+
+  Please note that <tt/.BANK/ will always get evaluated in the link stage, so
+  an expression containing <tt/.BANK/ can never be used where a constant known
+  result is expected (for example with <tt/.RES/).
+
+  Example:
+
+  <tscreen><verb>
+        .segment "BANK1"
+        .proc   banked_func_1
+                ...
+        .endproc
+
+        .segment "BANK2"
+        .proc   banked_func_2
+                ...
+        .endproc
+
+        .proc   bank_table
+               .addr   banked_func_1
+                .byte   <.BANK (banked_func_1)
+
+                .addr   banked_func_2
+                .byte   <.BANK (banked_func_2)
+        .endproc
+  </verb></tscreen>
+
+
+
 <sect1><tt>.BANKBYTE</tt><label id=".BANKBYTE"><p>
 
   The function returns the bank byte (that is, bits 16-23) of its argument.
@@ -2229,7 +2272,7 @@ Here's a list of all control commands and a description, what they do:
   is a symbol that is already defined somewhere in the source file up to the
   current position. Otherwise the function yields false. As an example, the
   <tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by
-           
+
   <tscreen><verb>
        .if     .defined(a)
   </verb></tscreen>
index 93eefcaf2bab4117b43f646bd28a9c0b4eec9dbf..457893ffc33a467ff9e8828827f118b0f76777b0 100644 (file)
@@ -713,7 +713,7 @@ This will define some external symbols that may be used in your code:
         __STACK_FILEOFFS__      The binary offset in the output file. This
                                 is not defined for relocatable output file
                                 formats (o65).
-</verb></tscreen>                             
+</verb></tscreen>
 
 A memory section may also have a type. Valid types are
 
@@ -736,6 +736,13 @@ the one defined in the <ref id="FEATURES" name="FEATURES"> section, or the
 value given on the command line with the <tt><ref id="option-S" name="-S"></tt>
 option).
 
+To support systems with banked memory, a special attribute named <tt/bank/ is
+available. The attribute value is an arbitrary 32 bit integer. The assembler
+has a builtin function named <tt/.BANK/ which may be used with an argument
+that has a segment reference (for example a symbol). The result of this
+function is the value of the bank attribute for the run memory area of the
+segment.
+
 
 <sect1>Other SEGMENT attributes<p>
 
index f1ade5f963c69dde0ccb3aba16aa2f8b25ef1708..1e3196fe70b6259876c416580a499d25bac46943 100644 (file)
@@ -542,6 +542,7 @@ static void WriteOneSeg (Segment* Seg)
 
     /* Write the segment data */
     ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
+    ObjWriteVar (Seg->Flags);                   /* Segment flags */
     ObjWriteVar (Seg->PC);                      /* Size */
     ObjWriteVar (Seg->Align);                   /* Segment alignment */
     ObjWrite8 (Seg->Def->AddrSize);             /* Address size of the segment */
index 5f5ac48edd29b3e8b305ba8709c0455b7994f905..54d88e6b8a0e8401e30e58fae97225fc9d166618 100644 (file)
@@ -47,6 +47,7 @@
 #include "bitops.h"
 #include "check.h"
 #include "print.h"
+#include "segdefs.h"
 #include "xmalloc.h"
 #include "xsprintf.h"
 
@@ -1873,7 +1874,7 @@ unsigned CfgProcess (void)
                  * must be placed into a memory area that has the bank
                  * attribute.
                  */
-                if (S->Seg->BankRef && M->BankExpr == 0) {
+                if ((S->Seg->Flags & SEG_FLAG_BANKREF) != 0 && 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 "
index ddc53d05d739e774e61ca2349352d069cd97500d..f45aa178754f5b4d157da09a3c80be7dc861a42f 100644 (file)
@@ -72,7 +72,7 @@ ExprNode* NewExprNode (ObjData* O, unsigned char Op)
 
 static void FreeExprNode (ExprNode* E)
 /* Free a node */
-{         
+{
     /* Free the memory */
     xfree (E);
 }
@@ -589,7 +589,6 @@ 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);
@@ -614,18 +613,9 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
                break;
 
            case EXPR_SECTION:
-               /* 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:
index a4e54317c30e81496e2d5c72790be92e98f31bde..1474ebe5550f4cba2b108598d110c7b226737575 100644 (file)
@@ -45,6 +45,7 @@
 #include "fragdefs.h"
 #include "hashfunc.h"
 #include "print.h"
+#include "segdefs.h"
 #include "symdefs.h"
 #include "xmalloc.h"
 
@@ -93,6 +94,7 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
     /* Initialize the fields */
     S->Name        = Name;
     S->Next       = 0;
+    S->Flags       = SEG_FLAG_NONE;
     S->Sections    = EmptyCollection;
     S->MemArea     = 0;
     S->PC         = 0;
@@ -104,7 +106,6 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
     S->AddrSize    = AddrSize;
     S->ReadOnly    = 0;
     S->Dumped      = 0;
-    S->BankRef     = 0;
 
     /* Insert the segment into the segment list and assign the segment id */
     S->Id = CollCount (&SegmentList);
@@ -190,6 +191,7 @@ Section* ReadSection (FILE* F, ObjData* O)
 /* Read a section from a file */
 {
     unsigned      Name;
+    unsigned      Flags;
     unsigned      Size;
     unsigned long Alignment;
     unsigned char Type;
@@ -198,12 +200,13 @@ Section* ReadSection (FILE* F, ObjData* O)
     Section*      Sec;
 
     /* Read the segment data */
-    (void) Read32 (F);            /* File size of data */
+    (void) Read32 (F);          /* File size of data */
     Name      = MakeGlobalStringId (O, ReadVar (F));    /* Segment name */
-    Size      = ReadVar (F);      /* Size of data */
-    Alignment = ReadVar (F);      /* Alignment */
-    Type      = Read8 (F);        /* Segment type */
-    FragCount = ReadVar (F);      /* Number of fragments */
+    Flags     = ReadVar (F);    /* Segment flags */
+    Size      = ReadVar (F);    /* Size of data */
+    Alignment = ReadVar (F);    /* Alignment */
+    Type      = Read8 (F);      /* Segment type */
+    FragCount = ReadVar (F);    /* Number of fragments */
 
 
     /* Print some data */
@@ -213,6 +216,11 @@ Section* ReadSection (FILE* F, ObjData* O)
 
     /* Get the segment for this section */
     S = GetSegment (Name, Type, GetObjFileName (O));
+                                        
+    /* The only possible flag is currently SEG_FLAG_BANKREF, and it must be
+     * applied to the segment, not the section.
+     */
+    S->Flags |= Flags;
 
     /* Allocate the section we will return later */
     Sec = NewSection (S, Alignment, Type);
index 295c75cdd05db24d09d9d047bfeee32981a048a8..9810c0f574174a9166b37bffd6265cd22038cfcb 100644 (file)
@@ -61,6 +61,7 @@ struct Segment {
     unsigned            Name;           /* Name index of the segment */
     unsigned            Id;             /* Segment id for debug info */
     Segment*           Next;           /* Hash list */
+    unsigned            Flags;          /* Segment flags */
     Collection          Sections;       /* Sections in this segment */
     struct MemoryArea*  MemArea;        /* Run memory area once placed */
     unsigned long      PC;             /* PC were this segment is located */
@@ -72,7 +73,6 @@ struct Segment {
     unsigned char      AddrSize;       /* Address size of segment */
     unsigned char       ReadOnly;       /* True for readonly segments (config) */
     unsigned char              Dumped;         /* Did we dump this segment? */
-    unsigned char       BankRef;        /* We need the bank of this segment */
 };
 
 
index e0cf5c010a05155bf39d18e39af5c91b383f5e63..b15dac59f7187fefa76c74dc80b933eab2313340 100644 (file)
@@ -498,6 +498,7 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
         unsigned long NextSeg   = ftell (F) + DataSize;
                const char*   Name      = GetString (&StrPool, ReadVar (F));
        unsigned      Len       = strlen (Name);
+        unsigned      Flags     = ReadVar (F);
        unsigned long Size      = ReadVar (F);
                unsigned long Align     = ReadVar (F);
                unsigned char AddrSize  = Read8 (F);
@@ -508,6 +509,7 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
 
        /* Print the data */
        printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
+        printf ("      Flags:%25u\n", Flags);
                printf ("      Size:%26lu\n", Size);
        printf ("      Alignment:%21lu\n", Align);
        printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,