From 9e68be38427b03c0144dcbd541625cc10b600a56 Mon Sep 17 00:00:00 2001 From: uz Date: Tue, 3 Jan 2012 21:41:34 +0000 Subject: [PATCH] Started to add a new .BANK instruction that allows access to a memory area 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 --- src/ca65/expr.c | 121 +++++++++++++++++++++++++++++++++++++++--- src/ca65/expr.h | 11 +++- src/ca65/main.c | 2 +- src/ca65/pseudo.c | 1 + src/ca65/scanner.c | 3 +- src/ca65/segment.c | 5 +- src/ca65/studyexpr.c | 35 ++++++++++++ src/ca65/token.h | 6 +-- src/common/exprdefs.c | 10 +++- src/common/exprdefs.h | 19 ++++--- src/ld65/config.c | 83 ++++++++++++++++++----------- src/ld65/expr.c | 91 ++++++++++++++++++++----------- src/ld65/memarea.c | 3 +- src/ld65/memarea.h | 3 +- src/ld65/scanner.h | 3 +- src/ld65/segments.c | 8 +-- src/ld65/segments.h | 9 ++-- src/od65/dump.c | 5 +- 18 files changed, 323 insertions(+), 95 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 25129decc..3ee1ab47e 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -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) { diff --git a/src/ca65/expr.h b/src/ca65/expr.h index 694a3b1a6..989a322bb 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -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 */ diff --git a/src/ca65/main.c b/src/ca65/main.c index b86147a2d..f6fa1ecc2 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -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 (); } diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 365fd5b79..480fc6186 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1990,6 +1990,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoASCIIZ }, { ccNone, DoAssert }, { ccNone, DoAutoImport }, + { ccNone, DoUnexpected }, /* .BANK */ { ccNone, DoUnexpected }, /* .BANKBYTE */ { ccNone, DoBankBytes }, { ccNone, DoUnexpected }, /* .BLANK */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 04f217ceb..94f517483 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -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 }, diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 9bbccc024..0411f4d6e 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -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 diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index b21f3b28b..b9f8d1946 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -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; diff --git a/src/ca65/token.h b/src/ca65/token.h index ad22b885c..eba24cdfa 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -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, diff --git a/src/common/exprdefs.c b/src/common/exprdefs.c index 24ece516d..dfee4084f 100644 --- a/src/common/exprdefs.c +++ b/src/common/exprdefs.c @@ -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; diff --git a/src/common/exprdefs.h b/src/common/exprdefs.h index db85a5934..2e1ac6e5a 100644 --- a/src/common/exprdefs.h +++ b/src/common/exprdefs.h @@ -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) @@ -89,13 +90,14 @@ #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) diff --git a/src/ld65/config.c b/src/ld65/config.c index e9ee81139..c4a9f3d9c 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -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) { diff --git a/src/ld65/expr.c b/src/ld65/expr.c index d671914b7..ddc53d05d 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -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 */ diff --git a/src/ld65/memarea.c b/src/ld65/memarea.c index 3e48ae285..4dbf8b3f6 100644 --- a/src/ld65/memarea.c +++ b/src/ld65/memarea.c @@ -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; diff --git a/src/ld65/memarea.h b/src/ld65/memarea.h index 4d3135fa3..936edc3f7 100644 --- a/src/ld65/memarea.h +++ b/src/ld65/memarea.h @@ -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 */ diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index 1cb71181c..cd69d644e 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -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, diff --git a/src/ld65/segments.c b/src/ld65/segments.c index d3fe119c9..b67d0e221 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -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); diff --git a/src/ld65/segments.h b/src/ld65/segments.h index 86caa2094..295c75cdd 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -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 */ }; diff --git a/src/od65/dump.c b/src/od65/dump.c index 66af0b543..92ead85c1 100644 --- a/src/od65/dump.c +++ b/src/od65/dump.c @@ -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: -- 2.39.5