void SegCheck (void)
/* Check the segments for range and other errors */
{
+ 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);
/* Check if the expression is constant */
if (ED_IsConst (&ED)) {
+ unsigned J;
+
/* 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) {
- LIError (&F->LI, "Range error (%ld not in [0..255])", Val);
- }
- } else {
- /* PC relative value */
- if (Val < -128 || Val > 127) {
- LIError (&F->LI, "Range error (%ld not in [-128..127])", Val);
- }
- }
- } else if (F->Len == 2) {
- if (Abs) {
- /* Absolute value */
- if (Val > 65535) {
- LIError (&F->LI, "Range error (%ld not in [0..65535])", Val);
- }
- } else {
- /* PC relative value */
- if (Val < -32768 || Val > 32767) {
- LIError (&F->LI, "Range error (%ld not in [-32768..32767])", Val);
- }
- }
- }
+ 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 (I = 0; I < F->Len; ++I) {
- F->V.Data [I] = Val & 0xFF;
- Val >>= 8;
+ for (J = 0; J < F->Len; ++J) {
+ F->V.Data[J] = ED.Val & 0xFF;
+ ED.Val >>= 8;
}
F->Type = FRAG_LITERAL;
/* 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)) {
LIError (&F->LI, "Range error");
}
- }
+ }
/* Release memory allocated for the expression decriptor */
ED_Done (&ED);
+void InitSegments (void)
+/* Initialize segments */
+{
+ /* Create the predefined segments. Code segment is active */
+ ActiveSeg = NewSegFromDef (&CodeSegDef);
+ NewSegFromDef (&RODataSegDef);
+ NewSegFromDef (&BssSegDef);
+ NewSegFromDef (&DataSegDef);
+ NewSegFromDef (&ZeropageSegDef);
+ NewSegFromDef (&NullSegDef);
+}
+
+
+
+void SetSegmentSizes (void)
+/* Set the default segment sizes according to the memory model */
+{
+ /* 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:
+ break;
+
+ case MMODEL_FAR:
+ CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+ break;
+
+ case MMODEL_HUGE:
+ CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+ DataSegDef.AddrSize = ADDR_SIZE_FAR;
+ BssSegDef.AddrSize = ADDR_SIZE_FAR;
+ RODataSegDef.AddrSize = ADDR_SIZE_FAR;
+ break;
+
+ default:
+ Internal ("Invalid memory model: %d", MemoryModel);
+ }
+}
+
+
+
static void WriteOneSeg (Segment* Seg)
/* Write one segment to the object file */
{
-void InitSegments (void)
-/* Initialize segments */
-{
- /* Create the predefined segments. Code segment is active */
- ActiveSeg = NewSegFromDef (&CodeSegDef);
- NewSegFromDef (&RODataSegDef);
- NewSegFromDef (&BssSegDef);
- NewSegFromDef (&DataSegDef);
- NewSegFromDef (&ZeropageSegDef);
- NewSegFromDef (&NullSegDef);
-}
-
-
-
-void SetSegmentSizes (void)
-/* Set the default segment sizes according to the memory model */
-{
- /* 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:
- break;
-
- case MMODEL_FAR:
- CodeSegDef.AddrSize = ADDR_SIZE_FAR;
- break;
-
- case MMODEL_HUGE:
- CodeSegDef.AddrSize = ADDR_SIZE_FAR;
- DataSegDef.AddrSize = ADDR_SIZE_FAR;
- BssSegDef.AddrSize = ADDR_SIZE_FAR;
- RODataSegDef.AddrSize = ADDR_SIZE_FAR;
- break;
-
- default:
- Internal ("Invalid memory model: %d", MemoryModel);
- }
-}
-
-
-
void WriteSegments (void)
/* Write the segment data to the object file */
{