diff --git a/src/ca65/enum.c b/src/ca65/enum.c index f226e4433..0383cada1 100644 --- a/src/ca65/enum.c +++ b/src/ca65/enum.c @@ -58,7 +58,8 @@ void DoEnum (void) /* Handle the .ENUM command */ { /* Start at zero */ - ExprNode* NextExpr = GenLiteralExpr (0); + long Offs = 0; + ExprNode* BaseExpr = GenLiteralExpr (0); /* Check for a name */ int Anon = (Tok != TOK_IDENT); @@ -104,25 +105,27 @@ void DoEnum (void) /* Skip the equal sign */ NextTok (); - /* Delete the old next expression */ - FreeExpr (NextExpr); - - /* Read the new one */ + /* Read the new expression */ EnumExpr = Expression (); + /* Reset the base expression and the offset */ + FreeExpr (BaseExpr); + BaseExpr = CloneExpr (EnumExpr); + Offs = 0; + } else { - EnumExpr = NextExpr; + /* No assignment, use last value + 1 */ + EnumExpr = GenAddExpr (CloneExpr (BaseExpr), GenLiteralExpr (Offs)); } - /* Generate the next expression from the current one */ - NextExpr = GenAddExpr (CloneExpr (EnumExpr), GenLiteralExpr (1)); - NextExpr = SimplifyExpr (NextExpr); - /* Assign the value to the enum member */ SymDef (Sym, EnumExpr, ADDR_SIZE_DEFAULT, SF_NONE); + /* Increment the offset for the next member */ + ++Offs; + /* Expect end of line */ ConsumeSep (); } @@ -136,8 +139,8 @@ void DoEnum (void) /* End of enum definition */ Consume (TOK_ENDENUM, "`.ENDENUM' expected"); - /* Free the last (unused) enum expression */ - FreeExpr (NextExpr); + /* Free the base expression */ + FreeExpr (BaseExpr); } diff --git a/src/ca65/expr.c b/src/ca65/expr.c index f8e80be48..8280cc4e1 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -204,13 +204,8 @@ static ExprNode* Symbol (SymEntry* S) } else { /* Mark the symbol as referenced */ SymRef (S); - /* Remove the symbol if possible */ - if (SymHasExpr (S)) { - return CloneExpr (GetSymExpr (S)); - } else { - /* Create symbol node */ - return GenSymExpr (S); - } + /* Create symbol node */ + return GenSymExpr (S); } } @@ -1117,16 +1112,7 @@ ExprNode* Expression (void) * a pointer to the root of the tree. */ { -#if 1 - return SimplifyExpr (Expr0 ()); -#else - /* Test code */ - ExprNode* Expr = Expr0 (); - printf ("Before: "); DumpExpr (Expr, SymResolve); - Expr = SimplifyExpr (Expr); - printf ("After: "); DumpExpr (Expr, SymResolve); - return Expr; -#endif + return Expr0 (); } @@ -1139,13 +1125,8 @@ long ConstExpression (void) { long Val; -#if 1 /* Read the expression */ - ExprNode* Expr = Expr0 (); -#else - /* Test code */ ExprNode* Expr = Expression (); -#endif /* Study the expression */ ExprDesc D; @@ -1182,27 +1163,13 @@ void FreeExpr (ExprNode* Root) -ExprNode* SimplifyExpr (ExprNode* Expr) +ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D) /* Try to simplify the given expression tree */ { - if (Expr && Expr->Op != EXPR_LITERAL) { - - /* Create an expression description and initialize it */ - ExprDesc D; - ED_Init (&D); - - /* Study the expression */ - StudyExpr (Expr, &D); - - /* Now check if we can generate a literal value */ - if (ED_IsConst (&D)) { - /* No external references */ - FreeExpr (Expr); - Expr = GenLiteralExpr (D.Val); - } - - /* Free allocated memory */ - ED_Done (&D); + if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) { + /* No external references */ + FreeExpr (Expr); + Expr = GenLiteralExpr (D->Val); } return Expr; } @@ -1243,10 +1210,19 @@ static ExprNode* GenSectionExpr (unsigned SegNum) ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right) /* Generate an addition from the two operands */ { - ExprNode* Root = NewExprNode (EXPR_PLUS); - Root->Left = Left; - Root->Right = Right; - return Root; + long Val; + if (IsEasyConst (Left, &Val) && Val == 0) { + FreeExpr (Left); + return Right; + } else if (IsEasyConst (Right, &Val) && Val == 0) { + FreeExpr (Right); + return Left; + } else { + ExprNode* Root = NewExprNode (EXPR_PLUS); + Root->Left = Left; + Root->Right = Right; + return Root; + } } diff --git a/src/ca65/expr.h b/src/ca65/expr.h index a3827e873..de03e19ba 100644 --- a/src/ca65/expr.h +++ b/src/ca65/expr.h @@ -43,6 +43,16 @@ +/*****************************************************************************/ +/* Forwards */ +/*****************************************************************************/ + + + +struct ExprDesc; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -63,7 +73,7 @@ long ConstExpression (void); void FreeExpr (ExprNode* Root); /* Free the expression tree, Root is pointing to. */ -ExprNode* SimplifyExpr (ExprNode* Expr); +ExprNode* SimplifyExpr (ExprNode* Expr, const struct ExprDesc* D); /* Try to simplify the given expression tree */ ExprNode* GenLiteralExpr (long Val); diff --git a/src/ca65/objcode.c b/src/ca65/objcode.c index 890b52cee..35d4dd841 100644 --- a/src/ca65/objcode.c +++ b/src/ca65/objcode.c @@ -144,22 +144,12 @@ void EmitData (const unsigned char* Data, unsigned Size) void EmitByte (ExprNode* Expr) /* Emit one byte */ -{ - long Val; - if (IsConstExpr (Expr, &Val)) { - /* Constant expression, emit literal byte */ - FreeExpr (Expr); - if ((Val & ~0xFF) != 0) { - Error ("Range error"); - } - Emit0 (Val & 0xFF); - } else { - /* Create a new fragment */ - Fragment* F = GenFragment (FRAG_EXPR, 1); +{ + /* Create a new fragment */ + Fragment* F = GenFragment (FRAG_EXPR, 1); - /* Set the data */ - F->V.Expr = Expr; - } + /* Set the data */ + F->V.Expr = Expr; } @@ -167,22 +157,11 @@ void EmitByte (ExprNode* Expr) void EmitWord (ExprNode* Expr) /* Emit one word */ { - long Val; - if (IsConstExpr (Expr, &Val)) { - /* Constant expression, emit literal byte */ - FreeExpr (Expr); - if ((Val & ~0xFFFF) != 0) { - Error ("Range error"); - } - Emit0 (Val & 0xFF); - Emit0 ((Val >> 8) & 0xFF); - } else { - /* Create a new fragment */ - Fragment* F = GenFragment (FRAG_EXPR, 2); + /* Create a new fragment */ + Fragment* F = GenFragment (FRAG_EXPR, 2); - /* Set the data */ - F->V.Expr = Expr; - } + /* Set the data */ + F->V.Expr = Expr; } @@ -190,23 +169,11 @@ void EmitWord (ExprNode* Expr) void EmitFarAddr (ExprNode* Expr) /* Emit a 24 bit expression */ { - long Val; - if (IsConstExpr (Expr, &Val)) { - /* Constant expression, emit literal byte */ - FreeExpr (Expr); - if ((Val & ~0xFFFFFF) != 0) { - Error ("Range error"); - } - Emit0 (Val & 0xFF); - Emit0 ((Val >> 8) & 0xFF); - Emit0 ((Val >> 16) & 0xFF); - } else { - /* Create a new fragment */ - Fragment* F = GenFragment (FRAG_EXPR, 3); + /* Create a new fragment */ + Fragment* F = GenFragment (FRAG_EXPR, 3); - /* Set the data */ - F->V.Expr = Expr; - } + /* Set the data */ + F->V.Expr = Expr; } @@ -214,21 +181,11 @@ void EmitFarAddr (ExprNode* Expr) void EmitDWord (ExprNode* Expr) /* Emit one dword */ { - long Val; - if (IsConstExpr (Expr, &Val)) { - /* Constant expression, emit literal byte */ - FreeExpr (Expr); - Emit0 (Val & 0xFF); - Emit0 ((Val >> 8) & 0xFF); - Emit0 ((Val >> 16) & 0xFF); - Emit0 ((Val >> 24) & 0xFF); - } else { - /* Create a new fragment */ - Fragment* F = GenFragment (FRAG_EXPR, 4); + /* Create a new fragment */ + Fragment* F = GenFragment (FRAG_EXPR, 4); - /* Set the data */ - F->V.Expr = Expr; - } + /* Set the data */ + F->V.Expr = Expr; } diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 66f67e57f..c0e64b501 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -37,6 +37,7 @@ #include /* common */ +#include "addrsize.h" #include "mmodel.h" #include "segnames.h" #include "xmalloc.h" @@ -51,6 +52,7 @@ #include "objfile.h" #include "segment.h" #include "spool.h" +#include "studyexpr.h" #include "symtab.h" @@ -291,35 +293,44 @@ void SegCheck (void) Fragment* F = S->Root; while (F) { if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { - long Val; - if (IsConstExpr (F->V.Expr, &Val)) { - /* We are able to evaluate the expression. Check for - * range errors. - */ - unsigned I; + + /* We have an expression, study it */ + ExprDesc ED; + ED_Init (&ED); + StudyExpr (F->V.Expr, &ED); + + /* Try to simplify it before looking further */ + F->V.Expr = SimplifyExpr (F->V.Expr, &ED); + + /* Check if the expression is constant */ + if (ED_IsConst (&ED)) { + + /* The expression is constant. Check for range errors. */ int Abs = (F->Type != FRAG_SEXPR); + long Val = ED.Val; + unsigned I; if (F->Len == 1) { - if (Abs) { - /* Absolute value */ - if (Val > 255) { + if (Abs) { + /* Absolute value */ + if (Val > 255) { PError (&F->Pos, "Range error"); - } - } else { - /* PC relative value */ - if (Val < -128 || Val > 127) { + } + } else { + /* PC relative value */ + if (Val < -128 || Val > 127) { PError (&F->Pos, "Range error"); - } - } + } + } } else if (F->Len == 2) { if (Abs) { - /* Absolute value */ - if (Val > 65535) { + /* Absolute value */ + if (Val > 65535) { PError (&F->Pos, "Range error"); - } - } else { - /* PC relative value */ - if (Val < -32768 || Val > 32767) { + } + } else { + /* PC relative value */ + if (Val < -32768 || Val > 32767) { PError (&F->Pos, "Range error"); } } @@ -334,15 +345,22 @@ void SegCheck (void) Val >>= 8; } F->Type = FRAG_LITERAL; - } else { + + } else if (ED.AddrSize != ADDR_SIZE_DEFAULT) { + /* We cannot evaluate the expression now, leave the job for - * the linker. However, we are able to check for explicit - * byte expressions and we will do so. + * the linker. However, we can check if the address size + * matches the fragment size, and we will do so. */ - if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) { + if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) || + (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) || + (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) { PError (&F->Pos, "Range error"); } } + + /* Release memory allocated for the expression decriptor */ + ED_Done (&ED); } F = F->Next; } @@ -495,7 +513,7 @@ void InitSegments (void) /* Initialize segment sizes. The segment definitions do already contain * the correct values for the default case (near), so we must only change * things that should be different. - */ + */ switch (MemoryModel) { case MMODEL_NEAR: diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index 2421b3565..c71a27109 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -441,6 +441,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D) SymMarkUser (Sym); StudyExprInternal (GetSymExpr (Sym), D); SymUnmarkUser (Sym); + ED_UpdateAddrSize (D, GetSymAddrSize (Sym)); } } else { /* The symbol is either undefined or an import. In both cases, track