]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codeseg.c
Fixed more E_MCONST issues
[cc65] / src / cc65 / codeseg.c
index ed2819de9506ea3a4f63d8c0646c218cfed8acb9..adf023971a60b3f13b9181a239ca6d9a6ae61f0d 100644 (file)
@@ -39,6 +39,7 @@
 /* common */
 #include "chartype.h"
 #include "check.h"
+#include "global.h"
 #include "hashstr.h"
 #include "strutil.h"
 #include "xmalloc.h"
@@ -184,7 +185,7 @@ static const char* ReadToken (const char* L, const char* Term,
 
 
 
-static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
+static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
 /* Parse an instruction nnd generate a code entry from it. If the line contains
  * errors, output an error message and return NULL.
  * For simplicity, we don't accept the broad range of input a "real" assembler
@@ -296,8 +297,15 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
            /* Absolute, maybe indexed */
            L = ReadToken (L, ",", Arg, sizeof (Arg));
            if (*L == '\0') {
-               /* Assume absolute */
-               AM = AM_ABS;
+               /* Absolute, zeropage or branch */
+               if ((OPC->Info & OF_BRA) != 0) {
+                   /* Branch */
+                   AM = AM_BRA;
+               } else if (IsZPName (Arg)) {
+                   AM = AM_ZP;
+               } else {
+                   AM = AM_ABS;
+               }
            } else if (*L == ',') {
                /* Indexed */
                L = SkipSpace (L+1);
@@ -308,7 +316,11 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
                    Reg = toupper (*L);
                    L = SkipSpace (L+1);
                    if (Reg == 'X') {
-                       AM = AM_ABSX;
+                       if (IsZPName (Arg)) {
+                           AM = AM_ZPX;
+                       } else {
+                           AM = AM_ABSX;
+                       }
                    } else if (Reg == 'Y') {
                        AM = AM_ABSY;
                    } else {
@@ -329,18 +341,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
      * if it does not exist. Ignore anything but local labels here.
      */
     Label = 0;
-    if ((OPC->Info & OF_BRA) != 0 && Arg[0] == 'L') {
-
-       unsigned Hash;
-
-       /* Addressing mode must be alsobute or something is really wrong */
-       CHECK (AM == AM_ABS);
-
-       /* Addressing mode is a branch/jump */
-       AM = AM_BRA;
+    if (AM == AM_BRA && Arg[0] == 'L') {
 
        /* Generate the hash over the label, then search for the label */
-       Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
+       unsigned Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
        Label = FindCodeLabel (S, Arg, Hash);
 
        /* If we don't have the label, it's a forward ref - create it */
@@ -353,7 +357,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
     /* We do now have the addressing mode in AM. Allocate a new CodeEntry
      * structure and initialize it.
      */
-    E = NewCodeEntry (OPC->OPC, AM, Arg, Label);
+    E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI);
 
     /* Return the new code entry */
     return E;
@@ -362,7 +366,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -399,7 +403,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
 
 
 
-void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
+void AddCodeEntry (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap)
 /* Add a line to the given code segment */
 {
     const char* L;
@@ -432,7 +436,7 @@ void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
            break;
 
        default:
-           E = ParseInsn (S, L);
+           E = ParseInsn (S, LI, L);
            break;
     }
 
@@ -542,6 +546,27 @@ void DelCodeEntries (CodeSeg* S, unsigned Start, unsigned Count)
 
 
 
+void MoveCodeEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
+/* Move an entry from one position to another. OldPos is the current position
+ * of the entry, NewPos is the new position of the entry.
+ */
+{
+    /* Get the code entry and remove it from the collection */
+    CodeEntry* E = GetCodeEntry (S, OldPos);
+    CollDelete (&S->Entries, OldPos);
+
+    /* Correct NewPos if needed */
+    if (NewPos >= OldPos) {
+       /* Position has changed with removal */
+       --NewPos;
+    }
+
+    /* Now insert it at the new position */
+    CollInsert (&S->Entries, E, NewPos);
+}
+
+
+
 struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index)
 /* Get the code entry following the one with the index Index. If there is no
  * following code entry, return NULL.
@@ -831,26 +856,6 @@ void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
 
 
 
-void AddCodeSegHint (CodeSeg* S, unsigned Hint)
-/* Add a hint for the preceeding instruction */
-{
-    CodeEntry* E;
-
-    /* Get the number of entries in this segment */
-    unsigned EntryCount = GetCodeEntryCount (S);
-
-    /* Must have at least one entry */
-    CHECK (EntryCount > 0);
-
-    /* Get the last entry */
-    E = GetCodeEntry (S, EntryCount-1);
-
-    /* Add the hint */
-    E->Hints |= Hint;
-}
-
-
-
 void DelCodeSegAfter (CodeSeg* S, unsigned Last)
 /* Delete all entries including the given one */
 {
@@ -868,6 +873,16 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last)
 
        /* Check if this entry has a label reference */
        if (E->JumpTo) {
+           /* If the label is a label in the label pool and this is the last
+            * reference to the label, remove the label from the pool.
+            */
+           CodeLabel* L = E->JumpTo;
+           int Index = CollIndex (&S->Labels, L);
+           if (Index >= 0 && CollCount (&L->JumpFrom) == 1) {
+               /* Delete it from the pool */
+               CollDelete (&S->Labels, Index);
+           }
+
            /* Remove the reference to the label */
            RemoveCodeLabelRef (S, E);
        }
@@ -905,6 +920,7 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
 /* Output the code segment data to a file */
 {
     unsigned I;
+    const LineInfo* LI;
 
     /* Get the number of entries in this segment */
     unsigned Count = GetCodeEntryCount (S);
@@ -922,20 +938,37 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
        fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
     }
 
-    /* Output all entries */
+    /* Output all entries, prepended by the line information if it has changed */
+    LI = 0;
     for (I = 0; I < Count; ++I) {
+       /* Get the next entry */
+       const CodeEntry* E = CollConstAt (&S->Entries, I);
+       /* Check if the line info has changed. If so, output the source line
+        * if the option is enabled and output debug line info if the debug
+        * option is enabled.
+        */
+       if (E->LI != LI) {
+           /* Line info has changed, remember the new line info */
+           LI = E->LI;
 
-       unsigned char Use;
+           /* Add the source line as a comment */
+           if (AddSource) {
+               fprintf (F, ";\n; %s\n;\n", LI->Line);
+           }
 
-       OutputCodeEntry (CollConstAt (&S->Entries, I), F);
+           /* Add line debug info */
+           if (DebugInfo) {
+               fprintf (F, "\t.dbg\tline, \"%s\", %u\n",
+                        GetInputName (LI), GetInputLine (LI));
+           }
+       }
+       /* Output the code */
+       OutputCodeEntry (E, F);
+    }
 
-       /* Print usage info */
-       Use = GetRegInfo ((CodeSeg*) S, I+1);
-       fprintf (F,
-                "  Use: %c%c%c\n",
-                (Use & REG_A)? 'A' : '_',
-                (Use & REG_X)? 'X' : '_',
-                (Use & REG_Y)? 'Y' : '_');
+    /* If debug info is enabled, terminate the last line number information */
+    if (DebugInfo) {
+       fprintf (F, "\t.dbg\tline\n");
     }
 
     /* If this is a segment for a function, leave the function */