/* 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);
/* 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 ();
}
/* End of enum definition */
Consume (TOK_ENDENUM, "`.ENDENUM' expected");
- /* Free the last (unused) enum expression */
- FreeExpr (NextExpr);
+ /* Free the base expression */
+ FreeExpr (BaseExpr);
}
} 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);
}
}
* 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 ();
}
{
long Val;
-#if 1
/* Read the expression */
- ExprNode* Expr = Expr0 ();
-#else
- /* Test code */
ExprNode* Expr = Expression ();
-#endif
/* Study the expression */
ExprDesc D;
-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;
}
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;
+ }
}
+/*****************************************************************************/
+/* Forwards */
+/*****************************************************************************/
+
+
+
+struct ExprDesc;
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
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);
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;
}
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;
}
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;
}
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;
}
#include <errno.h>
/* common */
+#include "addrsize.h"
#include "mmodel.h"
#include "segnames.h"
#include "xmalloc.h"
#include "objfile.h"
#include "segment.h"
#include "spool.h"
+#include "studyexpr.h"
#include "symtab.h"
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");
}
}
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;
}
/* 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:
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