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.
@ -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 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 current position. Otherwise the function yields false. As an example, the
<tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by <tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by
<tscreen><verb> <tscreen><verb>
.if .defined(a) .if .defined(a)
</verb></tscreen> </verb></tscreen>

View 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 __STACK_FILEOFFS__ The binary offset in the output file. This
is not defined for relocatable output file is not defined for relocatable output file
formats (o65). formats (o65).
</verb></tscreen> </verb></tscreen>
A memory section may also have a type. Valid types are 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> 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

@ -72,7 +72,7 @@ ExprNode* NewExprNode (ObjData* O, unsigned char Op)
static void FreeExprNode (ExprNode* E) static void FreeExprNode (ExprNode* E)
/* Free a node */ /* Free a node */
{ {
/* Free the memory */ /* Free the memory */
xfree (E); xfree (E);
} }
@ -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;
@ -198,12 +200,13 @@ Section* ReadSection (FILE* F, ObjData* O)
Section* Sec; Section* Sec;
/* 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 */
Size = ReadVar (F); /* Size of data */ Flags = ReadVar (F); /* Segment flags */
Alignment = ReadVar (F); /* Alignment */ Size = ReadVar (F); /* Size of data */
Type = Read8 (F); /* Segment type */ Alignment = ReadVar (F); /* Alignment */
FragCount = ReadVar (F); /* Number of fragments */ Type = Read8 (F); /* Segment type */
FragCount = ReadVar (F); /* Number of fragments */
/* Print some data */ /* Print some data */
@ -213,6 +216,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,