/* 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 */
-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 */
{
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);
* 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 */
} else {
- /* Finalize the expression */
- F->V.Expr = FinalizeExpr (F->V.Expr, &F->LI);
-
/* Simplify the expression */
/* ### F->V.Expr = SimplifyExpr (F->V.Expr, &ED); */
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);
StudyULabel (Expr, D);
break;
- case EXPR_BANK:
- StudyBank (Expr, D);
- break;
-
case EXPR_PLUS:
StudyPlus (Expr, D);
break;
StudyBoolNot (Expr, D);
break;
- case EXPR_BANKRAW:
- StudyBankRaw (Expr, D);
+ case EXPR_BANK:
+ StudyBank (Expr, D);
break;
case EXPR_BYTE0:
#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)
#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)
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* 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)
/* Segment flags */
#define SEG_FLAG_NONE 0x00
-#define SEG_FLAG_BANKREF 0x01 /* Segment is referenced by .BANK */
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.
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);
+ 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 {
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 */
/* 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
long Val;
Section* S;
Export* E;
+ SegExprDesc D;
switch (Expr->Op) {
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);
Left = GetExprVal (Expr->Left);
Right = GetExprVal (Expr->Right);
if (Right == 0) {
- Error ("Division by zero");
+ Error ("Division by zero");
}
return Left / Right;
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;
default:
Internal ("Unknown expression Op type: %u", Expr->Op);
/* NOTREACHED */
- return 0;
+ return 0;
}
}
break;
case EXPR_SECTION:
- case EXPR_BANK:
/* Read the section number */
Expr->V.SecNum = ReadVar (F);
break;
/* 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 */
/* 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);