void SegDone (void) /* Check the segments for range and other errors. Do cleanup. */ { static const unsigned long U_Hi[4] = { 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; static const long S_Hi[4] = { 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* S = CollAtUnchecked (&SegmentList, I); Fragment* F = S->Root; while (F) { if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { /* We have an expression, study it */ ExprDesc ED; ED_Init (&ED); StudyExpr (F->V.Expr, &ED); /* Check if the expression is constant */ if (ED_IsConst (&ED)) { unsigned J; /* The expression is constant. Check for range errors. */ CHECK (F->Len <= 4); if (F->Type == FRAG_SEXPR) { long Hi = S_Hi[F->Len-1]; long Lo = ~Hi; if (ED.Val > Hi || ED.Val < Lo) { LIError (&F->LI, "Range error (%ld not in [%ld..%ld])", ED.Val, Lo, Hi); } } else { if (((unsigned long)ED.Val) > U_Hi[F->Len-1]) { LIError (&F->LI, "Range error (%lu not in [0..%lu])", (unsigned long)ED.Val, U_Hi[F->Len-1]); } } /* We don't need the expression tree any longer */ FreeExpr (F->V.Expr); /* Convert the fragment into a literal fragment */ for (J = 0; J < F->Len; ++J) { F->V.Data[J] = ED.Val & 0xFF; ED.Val >>= 8; } F->Type = FRAG_LITERAL; } else if (RelaxChecks == 0) { /* We cannot evaluate the expression now, leave the job for * the linker. However, we can check if the address size * matches the fragment size. Mismatches are errors in * most situations. */ 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)) { LIError (&F->LI, "Range error"); } } /* Release memory allocated for the expression decriptor */ ED_Done (&ED); }
void SegCheck (void) /* Check the segments for range and other errors */ { Segment* S = SegmentList; while (S) { Fragment* F = S->Root; while (F) { if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { /* 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) { PError (&F->Pos, "Range error (%ld not in [0..255])", Val); } } else { /* PC relative value */ if (Val < -128 || Val > 127) { PError (&F->Pos, "Range error (%ld not in [-128..127])", Val); } } } else if (F->Len == 2) { if (Abs) { /* Absolute value */ if (Val > 65535) { PError (&F->Pos, "Range error (%ld not in [0..65535])", Val); } } else { /* PC relative value */ if (Val < -32768 || Val > 32767) { PError (&F->Pos, "Range error (%ld not in [-32768..32767])", Val); } } } /* We don't need the expression tree any longer */ FreeExpr (F->V.Expr); /* Convert the fragment into a literal fragment */ for (I = 0; I < F->Len; ++I) { F->V.Data [I] = Val & 0xFF; Val >>= 8; } F->Type = FRAG_LITERAL; } else if (ED.AddrSize != ADDR_SIZE_DEFAULT) { /* We cannot evaluate the expression now, leave the job for * the linker. However, we can check if the address size * matches the fragment size, and we will do so. */ 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); }