From 43ea0e3df9d885657886a2614c31af64a1a187f1 Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 30 Jun 2012 17:18:03 +0000 Subject: [PATCH] Move evaluation of the argument for .BANK into the linker. It is otherwise too restricted, since no imported symbols may be used. git-svn-id: svn://svn.cc65.org/cc65/trunk@5746 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/expr.c | 77 +----------------------------------- src/ca65/expr.h | 8 ---- src/ca65/segment.c | 3 -- src/ca65/studyexpr.c | 23 +---------- src/common/exprdefs.h | 3 +- src/common/objdefs.h | 4 +- src/common/segdefs.h | 1 - src/ld65/config.c | 13 ------ src/ld65/expr.c | 92 +++++++++++++++++++++++++++---------------- src/ld65/segments.c | 7 +--- 10 files changed, 66 insertions(+), 165 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 740db2aae..6c68dd8d6 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -243,7 +243,7 @@ static ExprNode* Bank (ExprNode* Operand) /* Return the bank of the given segmented expression */ { /* Generate the bank expression */ - ExprNode* Expr = NewExprNode (EXPR_BANKRAW); + ExprNode* Expr = NewExprNode (EXPR_BANK); Expr->Left = Operand; /* Return the result */ @@ -1833,76 +1833,6 @@ 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 { - Segment* S; - - FreeExpr (Expr->Left); - Expr->Op = EXPR_BANK; - Expr->Left = 0; - Expr->V.SecNum = ED.SecRef[0].Ref; - - /* Mark the segment */ - S = CollAt (&SegmentList, Expr->V.SecNum); - S->Flags |= SEG_FLAG_BANKREF; - } - - /* Cleanup */ - ED_Done (&ED); - - } - break; - } - - /* Return the (partial) tree */ - return Expr; -} - - - void WriteExpr (ExprNode* Expr) /* Write the given expression to the object file */ { @@ -1940,11 +1870,6 @@ void WriteExpr (ExprNode* Expr) 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); diff --git a/src/ca65/expr.h b/src/ca65/expr.h index 1bcaba3a0..1011b825d 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -147,14 +147,6 @@ 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/segment.c b/src/ca65/segment.c index c6a08b56d..d0367ce32 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -409,9 +409,6 @@ 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); */ diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index 0a2986f2a..76d563594 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -1097,21 +1097,6 @@ 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); @@ -1296,10 +1281,6 @@ 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; @@ -1400,8 +1381,8 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D) StudyBoolNot (Expr, D); break; - case EXPR_BANKRAW: - StudyBankRaw (Expr, D); + case EXPR_BANK: + StudyBank (Expr, D); break; case EXPR_BYTE0: diff --git a/src/common/exprdefs.h b/src/common/exprdefs.h index 50a5a25b6..fd899d900 100644 --- a/src/common/exprdefs.h +++ b/src/common/exprdefs.h @@ -60,7 +60,6 @@ #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) @@ -90,7 +89,7 @@ #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_BANK (EXPR_UNARYNODE | 0x05) #define EXPR_BYTE0 (EXPR_UNARYNODE | 0x08) #define EXPR_BYTE1 (EXPR_UNARYNODE | 0x09) diff --git a/src/common/objdefs.h b/src/common/objdefs.h index 8f026cf27..aa3c4a198 100644 --- a/src/common/objdefs.h +++ b/src/common/objdefs.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 */ @@ -46,7 +46,7 @@ /* Defines for magic and version */ #define OBJ_MAGIC 0x616E7A55 -#define OBJ_VERSION 0x0010 +#define OBJ_VERSION 0x0011 /* Size of an object file header */ #define OBJ_HDR_SIZE (24*4) diff --git a/src/common/segdefs.h b/src/common/segdefs.h index d12e60171..62fb7d557 100644 --- a/src/common/segdefs.h +++ b/src/common/segdefs.h @@ -46,7 +46,6 @@ /* Segment flags */ #define SEG_FLAG_NONE 0x00 -#define SEG_FLAG_BANKREF 0x01 /* Segment is referenced by .BANK */ diff --git a/src/ld65/config.c b/src/ld65/config.c index 54d88e6b8..bb2691407 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1870,19 +1870,6 @@ 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->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 " - "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. diff --git a/src/ld65/expr.c b/src/ld65/expr.c index 966c40698..bfcb852ea 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -142,16 +142,6 @@ int IsConstExpr (ExprNode* Root) 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; @@ -160,7 +150,30 @@ int IsConstExpr (ExprNode* Root) } else if (EXPR_IS_UNARY (Root->Op)) { - return IsConstExpr (Root->Left); + SegExprDesc D; + + /* Special handling for the BANK pseudo function */ + switch (Root->Op) { + + case EXPR_BANK: + /* Get segment references for the expression */ + GetSegExprVal (Root->Left, &D); + + /* The expression is const if the expression contains exactly + * one segment that is assigned to a memory area which has a + * bank attribute that is constant. + */ + return (D.TooComplex == 0 && + D.Seg != 0 && + D.Seg->MemArea != 0 && + D.Seg->MemArea->BankExpr != 0 && + IsConstExpr (D.Seg->MemArea->BankExpr)); + + default: + /* All others handled normal */ + return IsConstExpr (Root->Left); + + } } else { @@ -171,9 +184,9 @@ int IsConstExpr (ExprNode* Root) if (IsConstExpr (Root->Left)) { /* lhs is const, if it is zero, don't eval right */ if (GetExprVal (Root->Left) == 0) { - return 1; + return 1; } else { - return IsConstExpr (Root->Right); + return IsConstExpr (Root->Right); } } else { /* lhs not const --> tree not const */ @@ -240,7 +253,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 || Expr->Op == EXPR_BANK); + PRECONDITION (Expr->Op == EXPR_SECTION); /* If we have an object file, get the section from it, otherwise * (internally generated expressions), get the section from the @@ -264,6 +277,7 @@ long GetExprVal (ExprNode* Expr) long Val; Section* S; Export* E; + SegExprDesc D; switch (Expr->Op) { @@ -297,10 +311,6 @@ 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); @@ -314,7 +324,7 @@ long GetExprVal (ExprNode* Expr) Left = GetExprVal (Expr->Left); Right = GetExprVal (Expr->Right); if (Right == 0) { - Error ("Division by zero"); + Error ("Division by zero"); } return Left / Right; @@ -379,36 +389,53 @@ 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_BANK: + GetSegExprVal (Expr->Left, &D); + if (D.TooComplex || D.Seg == 0) { + Error ("Argument for .BANK is not segment relative or too complex"); + } + if (D.Seg->MemArea == 0) { + Error ("Segment `%s' is referenced by .BANK but " + "not assigned to a memory area", + GetString (D.Seg->Name)); + } + if (D.Seg->MemArea->BankExpr == 0) { + Error ("Memory area `%s' is referenced by .BANK but " + "has no BANK attribute", + GetString (D.Seg->MemArea->Name)); + } + return GetExprVal (D.Seg->MemArea->BankExpr); + case EXPR_BYTE0: - return GetExprVal (Expr->Left) & 0xFF; + return GetExprVal (Expr->Left) & 0xFF; case EXPR_BYTE1: - return (GetExprVal (Expr->Left) >> 8) & 0xFF; + return (GetExprVal (Expr->Left) >> 8) & 0xFF; case EXPR_BYTE2: - return (GetExprVal (Expr->Left) >> 16) & 0xFF; + return (GetExprVal (Expr->Left) >> 16) & 0xFF; case EXPR_BYTE3: - return (GetExprVal (Expr->Left) >> 24) & 0xFF; + return (GetExprVal (Expr->Left) >> 24) & 0xFF; case EXPR_WORD0: - return GetExprVal (Expr->Left) & 0xFFFF; + return GetExprVal (Expr->Left) & 0xFFFF; case EXPR_WORD1: - return (GetExprVal (Expr->Left) >> 16) & 0xFFFF; - + return (GetExprVal (Expr->Left) >> 16) & 0xFFFF; + case EXPR_FARADDR: return GetExprVal (Expr->Left) & 0xFFFFFF; @@ -418,7 +445,7 @@ long GetExprVal (ExprNode* Expr) default: Internal ("Unknown expression Op type: %u", Expr->Op); /* NOTREACHED */ - return 0; + return 0; } } @@ -619,7 +646,6 @@ ExprNode* ReadExpr (FILE* F, ObjData* O) break; case EXPR_SECTION: - case EXPR_BANK: /* Read the section number */ Expr->V.SecNum = ReadVar (F); break; diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 1474ebe55..156fd8100 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -202,7 +202,7 @@ Section* ReadSection (FILE* F, ObjData* O) /* Read the segment data */ (void) Read32 (F); /* File size of data */ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */ - Flags = ReadVar (F); /* Segment flags */ + Flags = ReadVar (F); /* Segment flags (currently unused) */ Size = ReadVar (F); /* Size of data */ Alignment = ReadVar (F); /* Alignment */ Type = Read8 (F); /* Segment type */ @@ -216,11 +216,6 @@ 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); -- 2.39.5