]> git.sur5r.net Git - cc65/blobdiff - src/da65/data.c
Add sample linker configurations for Atari binary output in C.
[cc65] / src / da65 / data.c
index 98f303d62369024898485da6afd7bbdf0e8a36bc..7355e60d17c75ba01549372bfb35c15b543f930b 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                 data.c                                   */
+/*                                  data.c                                   */
 /*                                                                           */
-/*                          Data output routines                            */
+/*                           Data output routines                            */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2004 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2014, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 #include "code.h"
 #include "error.h"
 #include "global.h"
+#include "labels.h"
 #include "output.h"
 #include "data.h"
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -56,15 +57,23 @@ static unsigned GetSpan (attr_t Style)
     unsigned RemainingBytes = GetRemainingBytes ();
 
     /* Count how many bytes are available. This number is limited by the
-     * number of remaining bytes, a label, or the end of the given Style
-     * attribute.
-     */
+    ** number of remaining bytes, a label, a segment change, or the end of
+    ** the given Style attribute.
+    */
     unsigned Count = 1;
     while (Count < RemainingBytes) {
-       if (MustDefLabel(PC+Count) || GetStyleAttr (PC+Count) != Style) {
-           break;
-       }
-       ++Count;
+        attr_t Attr;
+        if (MustDefLabel(PC+Count)) {
+            break;
+        }
+        Attr = GetAttr (PC+Count);
+        if ((Attr & atStyleMask) != Style) {
+            break;
+        }
+        if ((Attr & (atSegmentStart | atSegmentEnd))) {
+            break;
+        }
+        ++Count;
     }
 
     /* Return the number of bytes */
@@ -82,12 +91,13 @@ static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (u
     unsigned Count = GetSpan (Style);
 
     /* If the count is less than the member size, print a row of Count data
-     * bytes. We assume here that there is no member with a size that is less
-     * than BytesPerLine.
-     */
+    ** bytes. We assume here that there is no member with a size that is less
+    ** than BytesPerLine.
+    */
     if (Count < MemberSize) {
-       DataByteLine (Count);
-       return Count;
+        DataByteLine (Count);
+        PC += Count;
+        return Count;
     }
 
     /* Make Count an even number of multiples of MemberSize */
@@ -97,20 +107,20 @@ static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (u
     BytesLeft = Count;
     while (BytesLeft > 0) {
 
-       /* Calculate the number of bytes for the next line */
-       unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
+        /* Calculate the number of bytes for the next line */
+        unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
 
-       /* Output a line with these bytes */
-       TableFunc (Chunk);
+        /* Output a line with these bytes */
+        TableFunc (Chunk);
 
-       /* Next line */
-       BytesLeft -= Chunk;
-       PC        += Chunk;
+        /* Next line */
+        BytesLeft -= Chunk;
+        PC        += Chunk;
     }
 
     /* If the next line is not the same style, add a separator */
     if (CodeLeft() && GetStyleAttr (PC) != Style) {
-       SeparatorLine ();
+        SeparatorLine ();
     }
 
     /* Return the number of bytes output */
@@ -158,59 +168,65 @@ unsigned DWordTable (void)
 unsigned AddrTable (void)
 /* Output a table of addresses */
 {
-    unsigned BytesLeft;
-
-    /* Count how many bytes may be output. */
-    unsigned Count = GetSpan (atAddrTab);
-
-    /* Handle Count == 1 */
-    if (Count == 1) {
-       ByteTable ();
-    }
-
-    /* Make the given number even */
-    Count &= ~1U;
-
-    /* Output as many data bytes lines as needed. For addresses, each line
-     * will hold just one address.
-     */
-    BytesLeft = Count;
-    while (BytesLeft > 0) {
-
-       /* Get the address */
-       unsigned Addr = GetCodeWord (PC);
-
-       /* In pass 1, define a label, in pass 2 output the line */
-       if (Pass == 1) {
-           if (!HaveLabel (Addr)) {
-               AddIntLabel (Addr);
-           }
-       } else {
-           const char* Label = GetLabel (Addr);
-           if (Label == 0) {
-               /* OOPS! Should not happen */
-               Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
-           }
-           Indent (MIndent);
-           Output (".addr");
-           Indent (AIndent);
-           Output ("%s", Label);
-           LineComment (PC, 2);
-           LineFeed ();
-       }
-
-       /* Next line */
-       PC        += 2;
-               BytesLeft -= 2;
+    unsigned long BytesLeft = GetRemainingBytes ();
+    unsigned long Start = PC;
+
+    /* Loop while table bytes left and we don't need to create a label at the
+    ** current position.
+    */
+    while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
+
+        unsigned Addr;
+
+        /* If just one byte is left, define it and bail out */
+        if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) {
+            DataByteLine (1);
+            ++PC;
+            break;
+        }
+
+        /* More than one byte left. Define a forward label if necessary */
+        ForwardLabel (1);
+
+        /* Now get the address from the PC */
+        Addr = GetCodeWord (PC);
+
+        /* In pass 1, define a label, in pass 2 output the line */
+        if (Pass == 1) {
+            if (!HaveLabel (Addr)) {
+                AddIntLabel (Addr);
+            }
+        } else {
+            const char* Label = GetLabel (Addr, PC);
+            if (Label == 0) {
+                /* OOPS! Should not happen */
+                Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
+            }
+            Indent (MCol);
+            Output (".addr");
+            Indent (ACol);
+            Output ("%s", Label);
+            LineComment (PC, 2);
+            LineFeed ();
+        }
+
+        /* Next table entry */
+        PC        += 2;
+        BytesLeft -= 2;
+
+        /* If we must define a label here, bail out */
+        if (BytesLeft && MustDefLabel (PC)) {
+            break;
+        }
     }
 
-    /* If the next line is not a byte table line, add a separator */
+    /* If the next line is not an address table line, add a separator */
     if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
-       SeparatorLine ();
+        SeparatorLine ();
     }
 
     /* Return the number of bytes output */
-    return Count;
+    return PC - Start;
 }
 
 
@@ -218,59 +234,65 @@ unsigned AddrTable (void)
 unsigned RtsTable (void)
 /* Output a table of RTS addresses (address - 1) */
 {
-    unsigned BytesLeft;
-
-    /* Count how many bytes may be output. */
-    unsigned Count = GetSpan (atRtsTab);
-
-    /* Handle Count == 1 */
-    if (Count == 1) {
-       ByteTable ();
+    unsigned long BytesLeft = GetRemainingBytes ();
+    unsigned long Start = PC;
+
+    /* Loop while table bytes left and we don't need to create a label at the
+    ** current position.
+    */
+    while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
+
+        unsigned Addr;
+
+        /* If just one byte is left, define it and bail out */
+        if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) {
+            DataByteLine (1);
+            ++PC;
+            break;
+        }
+
+        /* More than one byte left. Define a forward label if necessary */
+        ForwardLabel (1);
+
+        /* Now get the address from the PC */
+        Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
+
+        /* In pass 1, define a label, in pass 2 output the line */
+        if (Pass == 1) {
+            if (!HaveLabel (Addr)) {
+                AddIntLabel (Addr);
+            }
+        } else {
+            const char* Label = GetLabel (Addr, PC);
+            if (Label == 0) {
+                /* OOPS! Should not happen */
+                Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
+            }
+            Indent (MCol);
+            Output (".word");
+            Indent (ACol);
+            Output ("%s-1", Label);
+            LineComment (PC, 2);
+            LineFeed ();
+        }
+
+        /* Next table entry */
+        PC        += 2;
+        BytesLeft -= 2;
+
+        /* If we must define a label here, bail out */
+        if (BytesLeft && MustDefLabel (PC)) {
+            break;
+        }
     }
 
-    /* Make the given number even */
-    Count &= ~1U;
-
-    /* Output as many data bytes lines as needed. For addresses, each line
-     * will hold just one address.
-     */
-    BytesLeft = Count;
-    while (BytesLeft > 0) {
-
-       /* Get the address */
-       unsigned Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
-
-       /* In pass 1, define a label, in pass 2 output the line */
-       if (Pass == 1) {
-           if (!HaveLabel (Addr)) {
-               AddIntLabel (Addr);
-           }
-       } else {
-           const char* Label = GetLabel (Addr);
-           if (Label == 0) {
-               /* OOPS! Should not happen */
-               Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
-           }
-           Indent (MIndent);
-           Output (".word");
-           Indent (AIndent);
-           Output ("%s-1", Label);
-           LineComment (PC, 2);
-           LineFeed ();
-       }
-
-       /* Next line */
-       PC        += 2;
-               BytesLeft -= 2;
-    }
-
-    /* If the next line is not a byte table line, add a separator */
+    /* If the next line is not a return address table line, add a separator */
     if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
-       SeparatorLine ();
+        SeparatorLine ();
     }
 
     /* Return the number of bytes output */
-    return Count;
+    return PC - Start;
 }
 
 
@@ -285,72 +307,69 @@ unsigned TextTable (void)
     unsigned BytesLeft = ByteCount;
     while (BytesLeft > 0) {
 
-       unsigned I;
-
-       /* Count the number of characters that can be output as such */
-       unsigned Count = 0;
-       while (Count < BytesLeft && Count < BytesPerLine*4-1) {
-           unsigned char C = GetCodeByte (PC + Count);
-           if (C >= 0x20 && C <= 0x7E && C != '\"') {
-               ++Count;
-           } else {
-               break;
-           }
-       }
-
-       /* If we have text, output it */
-       if (Count > 0) {
-           unsigned CBytes;
-           Indent (MIndent);
-           Output (".byte");
-           Indent (AIndent);
-           Output ("\"");
-           for (I = 0; I < Count; ++I) {
-               Output ("%c", GetCodeByte (PC+I));
-           }
-           Output ("\"");
-           CBytes = Count;
-           while (CBytes > 0) {
-               unsigned Chunk = CBytes;
-               if (Chunk > BytesPerLine) {
-                   Chunk = BytesPerLine;
-               }
-               LineComment (PC, Chunk);
-               LineFeed ();
-               CBytes -= Chunk;
-               PC += Chunk;
-           }
-           BytesLeft -= Count;
-       }
-
-       /* Count the number of bytes that must be output as bytes */
-       Count = 0;
-       while (Count < BytesLeft && Count < BytesPerLine) {
-           unsigned char C = GetCodeByte (PC + Count);
-                   if (C < 0x20 || C > 0x7E || C == '\"') {
-               ++Count;
-           } else {
-               break;
-           }
-       }
-
-       /* If we have raw output bytes, print them */
-       if (Count > 0) {
-           DataByteLine (Count);
-           PC += Count;
-           BytesLeft -= Count;
-       }
+        unsigned I;
+
+        /* Count the number of characters that can be output as such */
+        unsigned Count = 0;
+        while (Count < BytesLeft && Count < BytesPerLine*4-1) {
+            unsigned char C = GetCodeByte (PC + Count);
+            if (C >= 0x20 && C <= 0x7E && C != '\"') {
+                ++Count;
+            } else {
+                break;
+            }
+        }
+
+        /* If we have text, output it */
+        if (Count > 0) {
+            unsigned CBytes;
+            Indent (MCol);
+            Output (".byte");
+            Indent (ACol);
+            Output ("\"");
+            for (I = 0; I < Count; ++I) {
+                Output ("%c", GetCodeByte (PC+I));
+            }
+            Output ("\"");
+            CBytes = Count;
+            while (CBytes > 0) {
+                unsigned Chunk = CBytes;
+                if (Chunk > BytesPerLine) {
+                    Chunk = BytesPerLine;
+                }
+                LineComment (PC, Chunk);
+                LineFeed ();
+                CBytes -= Chunk;
+                PC += Chunk;
+            }
+            BytesLeft -= Count;
+        }
+
+        /* Count the number of bytes that must be output as bytes */
+        Count = 0;
+        while (Count < BytesLeft && Count < BytesPerLine) {
+            unsigned char C = GetCodeByte (PC + Count);
+            if (C < 0x20 || C > 0x7E || C == '\"') {
+                ++Count;
+            } else {
+                break;
+            }
+        }
+
+        /* If we have raw output bytes, print them */
+        if (Count > 0) {
+            DataByteLine (Count);
+            PC += Count;
+            BytesLeft -= Count;
+        }
 
     }
 
     /* If the next line is not a byte table line, add a separator */
     if (CodeLeft() && GetStyleAttr (PC) != atTextTab) {
-       SeparatorLine ();
+        SeparatorLine ();
     }
 
     /* Return the number of bytes output */
     return ByteCount;
 }
-
-
-