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:
parent
e7e4877e6e
commit
1fccae4cff
@ -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>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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 "
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user