]> git.sur5r.net Git - cc65/commitdiff
Working on the new backend
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 4 May 2001 16:41:23 +0000 (16:41 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 4 May 2001 16:41:23 +0000 (16:41 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@710 b7a2c559-68d2-44c3-8de9-860c34a00d81

12 files changed:
src/cc65/codeent.c
src/cc65/codeent.h
src/cc65/codelab.c
src/cc65/codelab.h
src/cc65/codeopt.c
src/cc65/codeseg.c
src/cc65/codeseg.h
src/cc65/global.c
src/cc65/global.h
src/cc65/main.c
src/cc65/opcodes.c
src/cc65/opcodes.h

index 9cf4d0688ed8249326f2e2c87a4a1944225f8625..2f980671a912bd2b6792169004ce6a222b7b4d5f 100644 (file)
@@ -39,6 +39,7 @@
 
 /* cc65 */
 #include "error.h"
+#include "global.h"
 
 /* b6502 */
 #include "codeinfo.h"
@@ -71,9 +72,10 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo)
     E->AM      = AM;
     E->Size    = GetInsnSize (E->OPC, E->AM);
     E->Hints   = 0;
-    E->Arg.Num = 0;
+    E->Arg     = 0;
+    E->Num     = 0;
     E->Flags   = 0;
-    E->Usage   = D->Info & (CI_MASK_USE | CI_MASK_CHG);
+    E->Info    = D->Info | GetAMUseInfo (AM);
     E->JumpTo  = JumpTo;
     InitCollection (&E->Labels);
 
@@ -91,7 +93,8 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo)
 void FreeCodeEntry (CodeEntry* E)
 /* Free the given code entry */
 {
-    /* ## Free the string argument if we have one */
+    /* Free the string argument if we have one */
+    xfree (E->Arg);
 
     /* Cleanup the collection */
     DoneCollection (&E->Labels);
@@ -102,77 +105,86 @@ void FreeCodeEntry (CodeEntry* E)
 
 
 
+int CodeEntryHasLabel (const CodeEntry* E)
+/* Check if the given code entry has labels attached */
+{
+    return (CollCount (&E->Labels) > 0);
+}
+
+
+
 void OutputCodeEntry (FILE* F, const CodeEntry* E)
 /* Output the code entry to a file */
 {
     const OPCDesc* D;
+    unsigned Chars;
 
     /* If we have a label, print that */
     unsigned LabelCount = CollCount (&E->Labels);
     unsigned I;
     for (I = 0; I < LabelCount; ++I) {
-       OutputCodeLabel (F, CollConstAt (&E->Labels, I));
+       OutputCodeLabel (F, CollConstAt (&E->Labels, I));
     }
 
     /* Get the opcode description */
     D = GetOPCDesc (E->OPC);
 
     /* Print the mnemonic */
-    fprintf (F, "\t%s", D->Mnemo);
+    Chars = fprintf (F, "\t%s", D->Mnemo);
 
     /* Print the operand */
     switch (E->AM) {
 
-       case AM_IMP:
-           /* implicit */
-           break;
+       case AM_IMP:
+           /* implicit */
+           break;
 
-       case AM_ACC:
-           /* accumulator */
-           fprintf (F, "\ta");
-           break;
+       case AM_ACC:
+           /* accumulator */
+           Chars += fprintf (F, "%*sa", 9-Chars, "");
+           break;
 
-       case AM_IMM:
-           /* immidiate */
-           fprintf (F, "\t#%s", E->Arg.Expr);
-           break;
+       case AM_IMM:
+           /* immidiate */
+           Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
+           break;
 
-       case AM_ZP:
-       case AM_ABS:
+       case AM_ZP:
+       case AM_ABS:
            /* zeropage and absolute */
-           fprintf (F, "\t%s", E->Arg.Expr);
+           Chars += fprintf (F, "%*s%s", 9-Chars, "", E->Arg);
            break;
 
        case AM_ZPX:
        case AM_ABSX:
            /* zeropage,X and absolute,X */
-           fprintf (F, "\t%s,x", E->Arg.Expr);
+           Chars += fprintf (F, "%*s%s,x", 9-Chars, "", E->Arg);
            break;
 
        case AM_ABSY:
            /* absolute,Y */
-           fprintf (F, "\t%s,y", E->Arg.Expr);
+           Chars += fprintf (F, "%*s%s,y", 9-Chars, "", E->Arg);
            break;
 
        case AM_ZPX_IND:
            /* (zeropage,x) */
-                   fprintf (F, "\t(%s,x)", E->Arg.Expr);
+                   Chars += fprintf (F, "%*s(%s,x)", 9-Chars, "", E->Arg);
            break;
 
        case AM_ZP_INDY:
            /* (zeropage),y */
-                   fprintf (F, "\t(%s),y", E->Arg.Expr);
+                   Chars += fprintf (F, "%*s(%s),y", 9-Chars, "", E->Arg);
            break;
 
        case AM_ZP_IND:
            /* (zeropage) */
-                   fprintf (F, "\t(%s)", E->Arg.Expr);
+                   Chars += fprintf (F, "%*s(%s)", 9-Chars, "", E->Arg);
            break;
 
        case AM_BRA:
            /* branch */
            CHECK (E->JumpTo != 0);
-           fprintf (F, "\t%s", E->JumpTo->Name);
+           Chars += fprintf (F, "%*s%s", 9-Chars, "", E->JumpTo->Name);
            break;
 
        default:
@@ -180,6 +192,19 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
 
     }
 
+    /* Print usage info if requested by the debugging flag */
+//    if (Debug) {
+       Chars += fprintf (F,
+                         "%*s; USE: %c%c%c CHG: %c%c%c",
+                         30-Chars, "",
+                         (E->Info & CI_USE_A)? 'A' : '_',
+                         (E->Info & CI_USE_X)? 'X' : '_',
+                         (E->Info & CI_USE_Y)? 'Y' : '_',
+                         (E->Info & CI_CHG_A)? 'A' : '_',
+                         (E->Info & CI_CHG_X)? 'X' : '_',
+                         (E->Info & CI_CHG_Y)? 'Y' : '_');
+//    }
+
     /* Terminate the line */
     fprintf (F, "\n");
 }
index 15acff3656867dda30894ac023adc66585d9fa05..77a1a7a12f32e1021607595e9389cf86453410c5 100644 (file)
 
 
 
+/* Flags used */
+#define CEF_USERMARK   0x0001U         /* Generic mark by user functions */
+#define CEF_NUMARG     0x0002U         /* Insn has numerical argument */
+
 /* Code entry structure */
 typedef struct CodeEntry CodeEntry;
 struct CodeEntry {
@@ -62,12 +66,10 @@ struct CodeEntry {
     am_t               AM;             /* Adressing mode */
     unsigned char      Size;           /* Estimated size */
     unsigned char      Hints;          /* Hints for this entry */
-    union {
-       unsigned        Num;            /* Numeric argument */
-       char*           Expr;           /* Textual argument */
-    } Arg;
+    char*                      Arg;            /* Argument as string */
+    unsigned           Num;            /* Numeric argument */
     unsigned short     Flags;          /* Flags */
-    unsigned short     Usage;          /* Register usage for this entry */
+    unsigned short     Info;           /* Register usage info for this entry */
     CodeLabel*         JumpTo;         /* Jump label */
     Collection         Labels;         /* Labels for this instruction */
 };
@@ -86,6 +88,9 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo);
 void FreeCodeEntry (CodeEntry* E);
 /* Free the given code entry */
 
+int CodeEntryHasLabel (const CodeEntry* E);
+/* Check if the given code entry has labels attached */
+
 void OutputCodeEntry (FILE* F, const CodeEntry* E);
 /* Output the code entry to a file */
 
index bc52e5878688cf68cc811ff7a31712f58da8b301..e02fd794638afddf257cbd4d4e2b9ef4dfa949e5 100644 (file)
@@ -36,7 +36,8 @@
 /* common */
 #include "xmalloc.h"
 
-/* cc65 */
+/* b6502 */
+#include "codeent.h"    
 #include "label.h"
 
 
@@ -82,6 +83,18 @@ void FreeCodeLabel (CodeLabel* L)
 
 
 
+void AddLabelRef (CodeLabel* L, struct CodeEntry* E)
+/* Let the CodeEntry E reference the label L */
+{
+    /* The insn at E jumps to this label */
+    E->JumpTo = L;
+
+    /* Remember that in the label */
+    CollAppend (&L->JumpFrom, E);
+}
+
+
+
 unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
 /* Remove a reference to this label, return the number of remaining references */
 {
@@ -97,7 +110,7 @@ unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
 void OutputCodeLabel (FILE* F, const CodeLabel* L)
 /* Output the code label to a file */
 {
-    fprintf (F, "%s:\n", L->Name);
+    fprintf (F, "%s:", L->Name);
 }
 
 
index 2193ada386597a5ab9f688a7802392bc89846767..8e6ef97bb56092d149b8e36b8c99d93925c029e0 100644 (file)
@@ -89,6 +89,9 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
 void FreeCodeLabel (CodeLabel* L);
 /* Free the given code label */
 
+void AddLabelRef (CodeLabel* L, struct CodeEntry* E);
+/* Let the CodeEntry E reference the label L */
+
 unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
 /* Remove a reference to this label, return the number of remaining references */
 
index c4e6040a3f6d06c75710c0406ad55ed36e9b57db..384a414559b0d8360b32e626750bfc6c72ffc687 100644 (file)
 
 
 
+/* common */
+#include "print.h"
+
+/* cc65 */
+#include "global.h"
+
 /* b6502 */
 #include "codeent.h"
+#include "codeinfo.h"
 #include "codeopt.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
@@ -53,7 +60,7 @@ static unsigned OptChanges;
 
 
 /*****************************************************************************/
-/*                            Remove dead jumps                             */
+/*                            Remove dead jumps                             */
 /*****************************************************************************/
 
 
@@ -80,34 +87,15 @@ static void OptDeadJumps (CodeSeg* S)
        /* Check if it's a branch, if it has a local target, and if the target
         * is the next instruction.
         */
-       if (E->AM == AM_BRA) {
-           printf ("BRA on entry %u:\n", I);
-           if (E->JumpTo) {
-               printf ("  JumpTo ok\n");
-               if (E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
-                   printf ("  Branch to next insn\n");
-               }
-           }
-       }
-
        if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
 
-           /* Remember the label */
-           CodeLabel* L = E->JumpTo;
+           /* Delete the dead jump */
+           DelCodeSegLine (S, I);
 
-           /* Jump to next instruction, remove it */
-           unsigned Remaining = RemoveLabelRef (L, E);
-           CollDelete (&S->Entries, I);
-           FreeCodeEntry (E);
+           /* Keep the number of entries updated */
            --Count;
 
-           /* If the label has no more references, remove it */
-           if (Remaining == 0) {
-               CollDeleteItem (&L->Owner->Labels, L);
-               FreeCodeLabel (L);
-           }
-
-           /* Remember we had changes */
+           /* Remember, we had changes */
            ++OptChanges;
 
        } else {
@@ -121,6 +109,131 @@ static void OptDeadJumps (CodeSeg* S)
 
 
 
+/*****************************************************************************/
+/*                            Remove dead code                              */
+/*****************************************************************************/
+
+
+
+static void OptDeadCode (CodeSeg* S)
+/* Remove dead code (code that follows an unconditional jump or an rts/rti
+ * and has no label) 
+ */
+{
+    unsigned I;
+
+    /* Get the number of entries, bail out if we have less than two entries */
+    unsigned Count = CollCount (&S->Entries);
+    if (Count < 2) {
+       return;
+    }
+
+    /* Walk over all entries minus the last one */
+    I = 0;
+    while (I < Count-1) {
+
+       /* Get this entry */
+       CodeEntry* E = CollAt (&S->Entries, I);
+
+               /* Check if it's an unconditional branch, and if the next entry has
+        * no labels attached
+        */
+               if ((E->OPC == OPC_JMP || E->OPC == OPC_BRA || E->OPC == OPC_RTS || E->OPC == OPC_RTI) &&
+                   !CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
+
+           /* Delete the next entry */
+           DelCodeSegLine (S, I+1);
+
+           /* Keep the number of entries updated */
+           --Count;
+
+           /* Remember, we had changes */
+           ++OptChanges;
+
+       } else {
+
+           /* Next entry */
+           ++I;
+
+       }
+    }
+}
+
+
+
+/*****************************************************************************/
+/*                         Optimize jump cascades                           */
+/*****************************************************************************/
+
+
+
+static void OptJumpCascades (CodeSeg* S)
+/* Optimize jump cascades (jumps to jumps). In such a case, the jump is
+ * replaced by a jump to the final location. This will in some cases produce
+ * worse code, because some jump targets are no longer reachable by short
+ * branches, but this is quite rare, so there are more advantages than
+ * disadvantages.
+ */
+{
+    unsigned I;
+
+    /* Get the number of entries, bail out if we have no entries */
+    unsigned Count = CollCount (&S->Entries);
+    if (Count == 0) {
+       return;
+    }
+
+    /* Walk over all entries */
+    I = 0;
+    while (I < Count) {
+
+       CodeLabel* OldLabel;
+       CodeLabel* NewLabel;
+
+       /* Get this entry */
+       CodeEntry* E = CollAt (&S->Entries, I);
+
+               /* Check if it's a branch, if it has a label attached, and if the
+        * instruction at this label is also a branch.
+        */
+       if (E->AM == AM_BRA                             &&
+           (OldLabel = E->JumpTo) != 0                 &&
+                   OldLabel->Owner->AM == AM_BRA               &&
+           (NewLabel = OldLabel->Owner->JumpTo) != 0) {
+
+           /* Get the instruction that has the new label attached */
+           CodeEntry* N = OldLabel->Owner;
+
+           /* Remove the reference to our label and delete it if this was
+            * the last reference.
+            */
+           if (RemoveLabelRef (OldLabel, E) == 0) {
+               /* Delete it */
+               DelCodeLabel (S, OldLabel);
+           }
+
+           /* Remove usage information from the entry and use the usage
+            * information from the new instruction instead.
+            */
+           E->Info &= ~(CI_MASK_USE | CI_MASK_CHG);
+           E->Info |= N->Info & ~(CI_MASK_USE | CI_MASK_CHG);
+
+           /* Use the new label */
+           AddLabelRef (NewLabel, E);
+
+           /* Remember ,we had changes */
+           ++OptChanges;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -130,15 +243,34 @@ static void OptDeadJumps (CodeSeg* S)
 void RunOpt (CodeSeg* S)
 /* Run the optimizer */
 {
-    printf ("Optimize\n");
+    typedef void (*OptFunc) (CodeSeg*);
+
+    /* Table with optimizer steps -  are called in this order */
+    static const OptFunc OptFuncs [] = {
+       OptJumpCascades,        /* Optimize jump cascades */
+               OptDeadJumps,           /* Remove dead jumps */
+       OptDeadCode,            /* Remove dead code */
+    };
 
     /* Repeat all steps until there are no more changes */
     do {
 
+       unsigned long Flags;
+       unsigned      I;
+
        /* Reset the number of changes */
        OptChanges = 0;
 
-       OptDeadJumps (S);
+               /* Run all optimization steps */
+       Flags = 1UL;
+               for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
+           if ((OptDisable & Flags) == 0) {
+               OptFuncs[I] (S);
+           } else if (Verbosity > 0 || Debug) {
+               printf ("Optimizer pass %u skipped\n", I);
+           }
+           Flags <<= 1;
+       }
 
     } while (OptChanges > 0);
 }
index b318b773929f35f5c49e6a7a6cc4e2fe068e20d0..b67585d4e9ba33e384cd611550704b167c859821 100644 (file)
@@ -136,10 +136,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
  * white space, for example.
  */
 {
-    char               Mnemo[16];
+    char                       Mnemo[16];
     const OPCDesc*     OPC;
     am_t               AM = 0;         /* Initialize to keep gcc silent */
-    char               Expr[64];
+    char               Arg[64];
     char               Reg;
     CodeEntry*         E;
     CodeLabel*         Label;
@@ -160,7 +160,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
     L = SkipSpace (L);
 
     /* Get the addressing mode */
-    Expr[0] = '\0';
+    Arg[0] = '\0';
     switch (*L) {
 
        case '\0':
@@ -170,13 +170,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
 
        case '#':
            /* Immidiate */
-           StrCopy (Expr, sizeof (Expr), L+1);
+           StrCopy (Arg, sizeof (Arg), L+1);
            AM = AM_IMM;
            break;
 
        case '(':
            /* Indirect */
-           L = ReadToken (L+1, ",)", Expr, sizeof (Expr));
+           L = ReadToken (L+1, ",)", Arg, sizeof (Arg));
 
            /* Check for errors */
            if (*L == '\0') {
@@ -214,7 +214,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
                    }
                    L = SkipSpace (L+1);
                    if (*L != '\0') {
-                       Error ("ASM code error: syntax error");
+                       Error ("ASM code error: syntax error");
                        return 0;
                    }
                    AM = AM_ZP_INDY;
@@ -238,7 +238,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
 
        default:
            /* Absolute, maybe indexed */
-           L = ReadToken (L, ",", Expr, sizeof (Expr));
+           L = ReadToken (L, ",", Arg, sizeof (Arg));
            if (*L == '\0') {
                /* Assume absolute */
                AM = AM_ABS;
@@ -257,7 +257,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
                        AM = AM_ABSY;
                    } else {
                        Error ("ASM code error: syntax error");
-                       return 0;
+                       return 0;
                    }
                    if (*L != '\0') {
                        Error ("ASM code error: syntax error");
@@ -273,7 +273,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
      * if it does not exist. Ignore anything but local labels here.
      */
     Label = 0;
-    if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Expr[0] == 'L') {
+    if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Arg[0] == 'L') {
 
        unsigned Hash;
 
@@ -284,13 +284,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
        AM = AM_BRA;
 
        /* Generate the hash over the label, then search for the label */
-       Hash = HashStr (Expr) % CS_LABEL_HASH_SIZE;
-       Label = FindCodeLabel (S, Expr, Hash);
+       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 */
        if (Label == 0) {
            /* Generate a new label */
-           Label = NewCodeSegLabel (S, Expr, Hash);
+           Label = NewCodeSegLabel (S, Arg, Hash);
        }
     }
 
@@ -298,9 +298,9 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
      * structure and initialize it.
      */
     E = NewCodeEntry (OPC, AM, Label);
-    if (Expr[0] != '\0') {
+    if (Arg[0] != '\0') {
        /* We have an additional expression */
-       E->Arg.Expr = xstrdup (Expr);
+       E->Arg = xstrdup (Arg);
     }
 
     /* Return the new code entry */
@@ -342,34 +342,7 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
 void FreeCodeSeg (CodeSeg* S)
 /* Free a code segment including all code entries */
 {
-    unsigned I, Count;
-
-    /* Free the names */
-    xfree (S->SegName);
-    xfree (S->FuncName);
-
-    /* Free the entries */
-    Count = CollCount (&S->Entries);
-    for (I = 0; I < Count; ++I) {
-       FreeCodeEntry (CollAt (&S->Entries, I));
-    }
-
-    /* Free the collections */
-    DoneCollection (&S->Entries);
-    DoneCollection (&S->Labels);
-
-    /* Free all labels */
-    for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
-       CodeLabel* L = S->LabelHash[I];
-       while (L) {
-           CodeLabel* Tmp = L;
-           L = L->Next;
-           FreeCodeLabel (Tmp);
-       }
-    }
-
-    /* Free the struct */
-    xfree (S);
+    FAIL ("Not implemented");
 }
 
 
@@ -422,7 +395,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
     E = 0;     /* Assume no insn created */
     switch (*L) {
 
-       case '\0':
+       case '\0':
            /* Empty line, just ignore it */
            break;
 
@@ -469,6 +442,45 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
 
 
 
+void DelCodeSegLine (CodeSeg* S, unsigned Index)
+/* Delete an entry from the code segment. This includes deleting any associated
+ * labels, removing references to labels and even removing the referenced labels
+ * if the reference count drops to zero.
+ */
+{
+    /* Get the code entry for the given index */
+    CodeEntry* E = CollAt (&S->Entries, Index);
+
+    /* Remove any labels associated with this entry */
+    unsigned Count;
+    while ((Count = CollCount (&E->Labels)) > 0) {
+       DelCodeLabel (S, CollAt (&E->Labels, Count-1));
+    }
+
+    /* If this insn references a label, remove the reference. And, if the
+     * the reference count for this label drops to zero, remove this label.
+     */
+    if (E->JumpTo) {
+
+       /* Remove the reference */
+               if (RemoveLabelRef (E->JumpTo, E) == 0) {
+           /* No references remaining, remove the label */
+           DelCodeLabel (S, E->JumpTo);
+       }
+
+       /* Reset the label pointer to avoid problems later */
+       E->JumpTo = 0;
+    }
+
+    /* Delete the pointer to the insn */
+    CollDelete (&S->Entries, Index);
+
+    /* Delete the instruction itself */
+    FreeCodeEntry (E);
+}
+
+
+
 void AddCodeLabel (CodeSeg* S, const char* Name)
 /* Add a code label for the next instruction to follow */
 {
@@ -480,11 +492,11 @@ void AddCodeLabel (CodeSeg* S, const char* Name)
 
     /* Did we find it? */
     if (L) {
-       /* We found it - be sure it does not already have an owner */
-       CHECK (L->Owner == 0);
+       /* We found it - be sure it does not already have an owner */
+       CHECK (L->Owner == 0);
     } else {
-       /* Not found - create a new one */
-       L = NewCodeSegLabel (S, Name, Hash);
+       /* Not found - create a new one */
+       L = NewCodeSegLabel (S, Name, Hash);
     }
 
     /* We do now have a valid label. Remember it for later */
@@ -493,6 +505,49 @@ void AddCodeLabel (CodeSeg* S, const char* Name)
 
 
 
+void DelCodeLabel (CodeSeg* S, CodeLabel* L)
+/* Remove references from this label and delete it. */
+{
+    unsigned Count, I;
+
+    /* Get the first entry in the hash chain */
+    CodeLabel* List = S->LabelHash[L->Hash];
+
+    /* First, remove the label from the hash chain */
+    if (List == L) {
+               /* First entry in hash chain */
+               S->LabelHash[L->Hash] = L->Next;
+    } else {
+               /* Must search through the chain */
+               while (List->Next != L) {
+                   /* If we've reached the end of the chain, something is *really* wrong */
+                   CHECK (List->Next != 0);
+                   /* Next entry */
+                   List = List->Next;
+               }
+               /* The next entry is the one, we have been searching for */
+               List->Next = L->Next;
+    }
+
+    /* Remove references from insns jumping to this label */
+    Count = CollCount (&L->JumpFrom);
+    for (I = 0; I < Count; ++I) {
+               /* Get the insn referencing this label */
+               CodeEntry* E = CollAt (&L->JumpFrom, I);
+               /* Remove the reference */
+               E->JumpTo = 0;
+    }
+    CollDeleteAll (&L->JumpFrom);
+
+    /* Remove the reference to the owning instruction */
+    CollDeleteItem (&L->Owner->Labels, L);
+
+    /* All references removed, delete the label itself */
+    FreeCodeLabel (L);
+}
+
+
+
 void AddCodeSegHint (CodeSeg* S, unsigned Hint)
 /* Add a hint for the preceeding instruction */
 {
@@ -551,6 +606,16 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S)
     /* Get the number of entries in this segment */
     unsigned Count = CollCount (&S->Entries);
 
+    fprintf (F, "; Labels: ");
+    for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
+       const CodeLabel* L = S->LabelHash[I];
+       while (L) {
+           fprintf (F, "%s ", L->Name);
+           L = L->Next;
+       }
+    }
+    fprintf (F, "\n");
+
     /* Output the segment directive */
     fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
 
@@ -633,19 +698,20 @@ void MergeCodeLabels (CodeSeg* S)
            unsigned RefCount = CollCount (&L->JumpFrom);
            for (K = 0; K < RefCount; ++K) {
 
-               /* Get the next instrcuction that references this label */
+               /* Get the next instruction that references this label */
                CodeEntry* E = CollAt (&L->JumpFrom, K);
 
                /* Change the reference */
                CHECK (E->JumpTo == L);
-               E->JumpTo = RefLab;
-               CollAppend (&RefLab->JumpFrom, E);
+               AddLabelRef (RefLab, E);
 
            }
 
+           /* There are no more instructions jumping to this label now */
+           CollDeleteAll (&L->JumpFrom);
+
                    /* Remove the label completely. */
-           FreeCodeLabel (L);
-           CollDelete (&E->Labels, J);
+                   DelCodeLabel (S, L);
        }
 
        /* The reference label is the only remaining label. Check if there
@@ -654,9 +720,7 @@ void MergeCodeLabels (CodeSeg* S)
         */
                if (CollCount (&RefLab->JumpFrom) == 0) {
            /* Delete the label */
-           FreeCodeLabel (RefLab);
-           /* Remove it from the list */
-           CollDelete (&E->Labels, 0);
+                   DelCodeLabel (S, RefLab);
        }
     }
 }
index 37b7820bcf1ed15e368f81c59b27dfaadd1e56fe..59bfb08423903d9df11e749bfc393097d787670e 100644 (file)
@@ -95,9 +95,18 @@ CodeSeg* PopCodeSeg (void);
 void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
 /* Add a line to the given code segment */
 
+void DelCodeSegLine (CodeSeg* S, unsigned Index);
+/* Delete an entry from the code segment. This includes deleting any associated
+ * labels, removing references to labels and even removing the referenced labels
+ * if the reference count drops to zero.
+ */
+
 void AddCodeLabel (CodeSeg* S, const char* Name);
 /* Add a code label for the next instruction to follow */
 
+void DelCodeLabel (CodeSeg* S, CodeLabel* L);
+/* Remove references from this label and delete it. */
+
 void AddCodeSegHint (CodeSeg* S, unsigned Hint);
 /* Add a hint for the preceeding instruction */
 
index 280a05d89ac293616fac5f51c5f061052f2e2d75..2a762f9223ea2ed83ab7361fc5bef170ac49bd67 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
+/* (C) 1998-2001 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -47,6 +47,7 @@ unsigned char ANSI            = 0;    /* Strict ANSI flag */
 unsigned char WriteableStrings = 0;    /* Literal strings are r/w */
 unsigned char NoWarn           = 0;    /* Suppress warnings */
 unsigned char Optimize         = 0;    /* Optimize flag */
+unsigned long OptDisable       = 0;    /* Optimizer passes to disable */
 unsigned char FavourSize       = 1;    /* Favour size over speed */
 unsigned      CodeSizeFactor   = 100;  /* Size factor for generated code */
 unsigned char InlineStdFuncs   = 0;    /* Inline some known functions */
index 20a5e6a9dfe84495af68b88405f9a2a2446e86b7..27e83955821a4cdfc96c176c5a198aaf479c457a 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 1998-2001 Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -48,6 +48,7 @@ extern unsigned char  ANSI;                   /* Strict ANSI flag */
 extern unsigned char   WriteableStrings;       /* Literal strings are r/w */
 extern unsigned char   NoWarn;                 /* Suppress warnings */
 extern unsigned char   Optimize;               /* Optimize flag */
+extern unsigned long   OptDisable;             /* Optimizer passes to disable */
 extern unsigned char   FavourSize;             /* Favour size over speed */
 extern unsigned                CodeSizeFactor;         /* Size factor for generated code */
 extern unsigned char    InlineStdFuncs;                /* Inline some known functions */
index f1840a74d4542ab76280a6dae326d1318a812409..6f3d0bbcfb009daf2802c8dba25aa046d455f8a3 100644 (file)
@@ -567,11 +567,9 @@ int main (int argc, char* argv[])
                    P = Arg + 2;
                    while (*P) {
                        switch (*P++) {
-#if 0
                            case 'f':
                                sscanf (P, "%lx", (long*) &OptDisable);
                                break;
-#endif
                            case 'i':
                                FavourSize = 0;
                                CodeSizeFactor = 200;
index 5c9ba3a9fb5718918a3b3e3c9145589aa202eaaa..8cca9cc6c7cb311f0d073c13fa4f130a99f120d5 100644 (file)
@@ -213,4 +213,22 @@ const OPCDesc* GetOPCDesc (opc_t OPC)
 
 
 
+unsigned GetAMUseInfo (am_t AM)
+/* Get usage info for the given addressing mode (addressing modes that use
+ * index registers return CI_USE... info for these registers).
+ */                           
+{
+    /* Check the addressing mode. */
+    switch (AM) {
+       case AM_ACC:      return CI_USE_A;
+       case AM_ZPX:      return CI_USE_X;
+       case AM_ABSX:     return CI_USE_X;
+       case AM_ABSY:     return CI_USE_Y;
+       case AM_ZPX_IND:  return CI_USE_X;
+       case AM_ZP_INDY:  return CI_USE_Y;
+       default:          return CI_USE_NONE;
+    }
+}
+
+
 
index 5de93e0c664815f99ce83697e40799bd07f62a65..aac5832753468d16e737767999f41d40a563ffba 100644 (file)
@@ -165,6 +165,11 @@ unsigned GetInsnSize (opc_t OPC, am_t AM);
 const OPCDesc* GetOPCDesc (opc_t OPC);
 /* Get an opcode description */
 
+unsigned GetAMUseInfo (am_t AM);
+/* Get usage info for the given addressing mode (addressing modes that use
+ * index registers return CI_USE... info for these registers).
+ */
+
 
 
 /* End of opcodes.h */