1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 04:30:10 +00:00

Finish support for .BANK.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5384 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2012-01-04 22:45:26 +00:00
parent e7e4877e6e
commit 1fccae4cff
8 changed files with 73 additions and 21 deletions

View File

@ -1275,6 +1275,49 @@ Pseudo functions expect their arguments in parenthesis, and they have a result,
either a string or an expression. 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> <sect1><tt>.BANKBYTE</tt><label id=".BANKBYTE"><p>
The function returns the bank byte (that is, bits 16-23) of its argument. The function returns the bank byte (that is, bits 16-23) of its argument.

View File

@ -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> value given on the command line with the <tt><ref id="option-S" name="-S"></tt>
option). 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> <sect1>Other SEGMENT attributes<p>

View File

@ -542,6 +542,7 @@ static void WriteOneSeg (Segment* Seg)
/* Write the segment data */ /* Write the segment data */
ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */ ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
ObjWriteVar (Seg->Flags); /* Segment flags */
ObjWriteVar (Seg->PC); /* Size */ ObjWriteVar (Seg->PC); /* Size */
ObjWriteVar (Seg->Align); /* Segment alignment */ ObjWriteVar (Seg->Align); /* Segment alignment */
ObjWrite8 (Seg->Def->AddrSize); /* Address size of the segment */ ObjWrite8 (Seg->Def->AddrSize); /* Address size of the segment */

View File

@ -47,6 +47,7 @@
#include "bitops.h" #include "bitops.h"
#include "check.h" #include "check.h"
#include "print.h" #include "print.h"
#include "segdefs.h"
#include "xmalloc.h" #include "xmalloc.h"
#include "xsprintf.h" #include "xsprintf.h"
@ -1873,7 +1874,7 @@ unsigned CfgProcess (void)
* must be placed into a memory area that has the bank * must be placed into a memory area that has the bank
* attribute. * attribute.
*/ */
if (S->Seg->BankRef && M->BankExpr == 0) { if ((S->Seg->Flags & SEG_FLAG_BANKREF) != 0 && M->BankExpr == 0) {
CfgError (GetSourcePos (S->LI), CfgError (GetSourcePos (S->LI),
"Segment `%s' is refered to by .BANK, but the " "Segment `%s' is refered to by .BANK, but the "
"memory area `%s' it is placed into has no BANK " "memory area `%s' it is placed into has no BANK "

View File

@ -589,7 +589,6 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
/* Read an expression from the given file */ /* Read an expression from the given file */
{ {
ExprNode* Expr; ExprNode* Expr;
Section* S;
/* Read the node tag and handle NULL nodes */ /* Read the node tag and handle NULL nodes */
unsigned char Op = Read8 (F); unsigned char Op = Read8 (F);
@ -614,18 +613,9 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
break; break;
case EXPR_SECTION: case EXPR_SECTION:
/* Read the section number */
Expr->V.SecNum = ReadVar (F);
break;
case EXPR_BANK: case EXPR_BANK:
/* Read the section number */ /* Read the section number */
Expr->V.SecNum = ReadVar (F); 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; break;
default: default:

View File

@ -45,6 +45,7 @@
#include "fragdefs.h" #include "fragdefs.h"
#include "hashfunc.h" #include "hashfunc.h"
#include "print.h" #include "print.h"
#include "segdefs.h"
#include "symdefs.h" #include "symdefs.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -93,6 +94,7 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
/* Initialize the fields */ /* Initialize the fields */
S->Name = Name; S->Name = Name;
S->Next = 0; S->Next = 0;
S->Flags = SEG_FLAG_NONE;
S->Sections = EmptyCollection; S->Sections = EmptyCollection;
S->MemArea = 0; S->MemArea = 0;
S->PC = 0; S->PC = 0;
@ -104,7 +106,6 @@ static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
S->AddrSize = AddrSize; S->AddrSize = AddrSize;
S->ReadOnly = 0; S->ReadOnly = 0;
S->Dumped = 0; S->Dumped = 0;
S->BankRef = 0;
/* Insert the segment into the segment list and assign the segment id */ /* Insert the segment into the segment list and assign the segment id */
S->Id = CollCount (&SegmentList); S->Id = CollCount (&SegmentList);
@ -190,6 +191,7 @@ Section* ReadSection (FILE* F, ObjData* O)
/* Read a section from a file */ /* Read a section from a file */
{ {
unsigned Name; unsigned Name;
unsigned Flags;
unsigned Size; unsigned Size;
unsigned long Alignment; unsigned long Alignment;
unsigned char Type; unsigned char Type;
@ -200,6 +202,7 @@ Section* ReadSection (FILE* F, ObjData* O)
/* Read the segment data */ /* 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 */ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */
Flags = ReadVar (F); /* Segment flags */
Size = ReadVar (F); /* Size of data */ Size = ReadVar (F); /* Size of data */
Alignment = ReadVar (F); /* Alignment */ Alignment = ReadVar (F); /* Alignment */
Type = Read8 (F); /* Segment type */ Type = Read8 (F); /* Segment type */
@ -214,6 +217,11 @@ Section* ReadSection (FILE* F, ObjData* O)
/* Get the segment for this section */ /* Get the segment for this section */
S = GetSegment (Name, Type, GetObjFileName (O)); 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 */ /* Allocate the section we will return later */
Sec = NewSection (S, Alignment, Type); Sec = NewSection (S, Alignment, Type);

View File

@ -61,6 +61,7 @@ struct Segment {
unsigned Name; /* Name index of the segment */ unsigned Name; /* Name index of the segment */
unsigned Id; /* Segment id for debug info */ unsigned Id; /* Segment id for debug info */
Segment* Next; /* Hash list */ Segment* Next; /* Hash list */
unsigned Flags; /* Segment flags */
Collection Sections; /* Sections in this segment */ Collection Sections; /* Sections in this segment */
struct MemoryArea* MemArea; /* Run memory area once placed */ struct MemoryArea* MemArea; /* Run memory area once placed */
unsigned long PC; /* PC were this segment is located */ unsigned long PC; /* PC were this segment is located */
@ -72,7 +73,6 @@ struct Segment {
unsigned char AddrSize; /* Address size of segment */ unsigned char AddrSize; /* Address size of segment */
unsigned char ReadOnly; /* True for readonly segments (config) */ unsigned char ReadOnly; /* True for readonly segments (config) */
unsigned char Dumped; /* Did we dump this segment? */ unsigned char Dumped; /* Did we dump this segment? */
unsigned char BankRef; /* We need the bank of this segment */
}; };

View File

@ -498,6 +498,7 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
unsigned long NextSeg = ftell (F) + DataSize; unsigned long NextSeg = ftell (F) + DataSize;
const char* Name = GetString (&StrPool, ReadVar (F)); const char* Name = GetString (&StrPool, ReadVar (F));
unsigned Len = strlen (Name); unsigned Len = strlen (Name);
unsigned Flags = ReadVar (F);
unsigned long Size = ReadVar (F); unsigned long Size = ReadVar (F);
unsigned long Align = ReadVar (F); unsigned long Align = ReadVar (F);
unsigned char AddrSize = Read8 (F); unsigned char AddrSize = Read8 (F);
@ -508,6 +509,7 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
/* Print the data */ /* Print the data */
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
printf (" Flags:%25u\n", Flags);
printf (" Size:%26lu\n", Size); printf (" Size:%26lu\n", Size);
printf (" Alignment:%21lu\n", Align); printf (" Alignment:%21lu\n", Align);
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,