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

src/cc65/codeent.c
src/cc65/codeent.h
src/cc65/codeopt.c
src/cc65/codeseg.c
src/cc65/codeseg.h
src/cc65/coptind.c
src/cc65/coptind.h
src/cc65/opcodes.c
src/cc65/opcodes.h

index e77041cd659d1ce9926f1f49fc7cea782c3caaeb..9a26f2deba9d575341cd2fb85e117a532643b077 100644 (file)
@@ -139,10 +139,13 @@ static int NumArg (const char* Arg, unsigned long* Num)
 
 
 
-CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo)
+CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
 /* Create a new code entry, initialize and return it */
 {
-    /* Allocate memory */
+    /* Get the opcode description */
+    const OPCDesc* D = GetOPCDesc (OPC);
+
+    /* Allocate memory */        
     CodeEntry* E = xmalloc (sizeof (CodeEntry));
 
     /* Initialize the fields */
@@ -246,30 +249,6 @@ void AttachCodeLabel (CodeEntry* E, CodeLabel* L)
 
 
 
-int CodeEntryHasLabel (const CodeEntry* E)
-/* Check if the given code entry has labels attached */
-{
-    return (CollCount (&E->Labels) > 0);
-}
-
-
-
-unsigned GetCodeLabelCount (const CodeEntry* E)
-/* Get the number of labels attached to this entry */
-{
-    return CollCount (&E->Labels);
-}
-
-
-
-CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
-/* Get a label from this code entry */
-{
-    return CollAt (&E->Labels, Index);
-}
-
-
-
 void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
 /* Move the code label L from it's former owner to the code entry E. */
 {
@@ -283,30 +262,6 @@ void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
 
 
 
-int CodeEntryHasMark (const CodeEntry* E)
-/* Return true if the given code entry has the CEF_USERMARK flag set */
-{
-    return (E->Flags & CEF_USERMARK) != 0;
-}
-
-
-
-void CodeEntrySetMark (CodeEntry* E)
-/* Set the CEF_USERMARK flag for the given entry */
-{
-    E->Flags |= CEF_USERMARK;
-}
-
-
-
-void CodeEntryResetMark (CodeEntry* E)
-/* Reset the CEF_USERMARK flag for the given entry */
-{
-    E->Flags &= ~CEF_USERMARK;
-}
-
-
-
 void CodeEntrySetArg (CodeEntry* E, const char* Arg)
 /* Set a new argument for the given code entry. An old string is deleted. */
 {
index e862a197a4cb3cf0aab433a86b45f584812d3166..4c37eeb4fbe982ab32e4f0c96cfeb013956ccf5b 100644 (file)
@@ -42,6 +42,7 @@
 
 /* common */
 #include "coll.h"
+#include "inline.h"
 
 /* cc65 */
 #include "codelab.h"
@@ -84,7 +85,7 @@ struct CodeEntry {
 
 
 
-CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo);
+CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo);
 /* Create a new code entry, initialize and return it */
 
 void FreeCodeEntry (CodeEntry* E);
@@ -101,26 +102,68 @@ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
 void AttachCodeLabel (CodeEntry* E, CodeLabel* L);
 /* Attach the label to the entry */
 
-int CodeEntryHasLabel (const CodeEntry* E);
+#if defined(HAVE_INLINE)
+INLINE int CodeEntryHasLabel (const CodeEntry* E)
 /* Check if the given code entry has labels attached */
+{
+    return (CollCount (&E->Labels) > 0);
+}
+#else
+#  define CodeEntryHasLabel(E) (CollCount (&(E)->Labels) > 0)
+#endif
 
-unsigned GetCodeLabelCount (const CodeEntry* E);
+#if defined(HAVE_INLINE)
+INLINE unsigned GetCodeLabelCount (const CodeEntry* E)
 /* Get the number of labels attached to this entry */
+{
+    return CollCount (&E->Labels);
+}
+#else
+#  define GetCodeLabelCount(E) CollCount (&(E)->Labels)
+#endif
 
-CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index);
+#if defined(HAVE_INLINE)
+INLINE CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
 /* Get a label from this code entry */
+{
+    return CollAt (&E->Labels, Index);
+}
+#else
+#  define GetCodeLabel(E, Index)       CollAt (&(E)->Labels, (Index))
+#endif
 
 void MoveCodeLabel (CodeLabel* L, CodeEntry* E);
 /* Move the code label L from it's former owner to the code entry E. */
 
-int CodeEntryHasMark (const CodeEntry* E);
+#if defined(HAVE_INLINE)
+INLINE int CodeEntryHasMark (const CodeEntry* E)
 /* Return true if the given code entry has the CEF_USERMARK flag set */
+{
+    return (E->Flags & CEF_USERMARK) != 0;
+}
+#else
+#  define CodeEntryHasMark(E)  (((E)->Flags & CEF_USERMARK) != 0)
+#endif
 
-void CodeEntrySetMark (CodeEntry* E);
+#if defined(HAVE_INLINE)
+INLINE void CodeEntrySetMark (CodeEntry* E)
 /* Set the CEF_USERMARK flag for the given entry */
+{
+    E->Flags |= CEF_USERMARK;
+}
+#else
+#  define CodeEntrySetMark(E)  ((E)->Flags |= CEF_USERMARK)
+#endif
 
-void CodeEntryResetMark (CodeEntry* E);
+#if defined(HAVE_INLINE)
+INLINE void CodeEntryResetMark (CodeEntry* E)
 /* Reset the CEF_USERMARK flag for the given entry */
+{
+    E->Flags &= ~CEF_USERMARK;
+}
+#else
+#  define CodeEntryResetMark(E)        ((E)->Flags &= ~CEF_USERMARK)
+#endif
 
 void CodeEntrySetArg (CodeEntry* E, const char* Arg);
 /* Set a new argument for the given code entry. An old string is deleted. */
index f6fc0c38e9e965ae2565b9c4d9786b7bb3fa26bf..06b5d3826c69d03255af8c38ac64344d25e7f3f1 100644 (file)
@@ -242,6 +242,322 @@ NextEntry:
 
 
 
+/*****************************************************************************/
+/*                           nega optimizations                             */
+/*****************************************************************************/
+
+
+
+static unsigned OptNegA1 (CodeSeg* S)
+/* Check for
+ *
+ *     ldx     #$00
+ *     lda     ..
+ *     jsr     bnega
+ *
+ * Remove the ldx if the lda does not use it.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[2];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for a ldx */
+               if (E->OPC == OPC_LDX                   &&
+           E->AM == AM_IMM                     &&
+           (E->Flags & CEF_NUMARG) != 0        &&
+           E->Num == 0                         &&
+           GetCodeEntries (S, L, I+1, 2)       &&
+           L[0]->OPC == OPC_LDA                &&
+           (L[0]->Use & REG_X) == 0            &&
+           L[1]->OPC == OPC_JSR                &&
+           strcmp (L[1]->Arg, "bnega") == 0) {
+
+           /* Remove the ldx instruction */
+           DelCodeEntry (S, I);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+static unsigned OptNegA2 (CodeSeg* S)
+/* Check for
+ *
+ *     lda     ..
+ *     jsr     bnega
+ *     jeq/jne ..
+ *
+ * Adjust the conditional branch and remove the call to the subroutine.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[2];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_LDA                   &&
+           GetCodeEntries (S, L, I+1, 2)       &&
+                   L[0]->OPC == OPC_JSR                &&
+           strcmp (L[0]->Arg, "bnega") == 0    &&
+           !CodeEntryHasLabel (L[0])           &&
+           (L[1]->Info & OF_ZBRA) != 0) {
+
+           /* Invert the branch */
+           ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
+
+           /* Delete the subroutine call */
+           DelCodeEntry (S, I+1);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+/*****************************************************************************/
+/*                           negax optimizations                            */
+/*****************************************************************************/
+
+
+
+static unsigned OptNegAX1 (CodeSeg* S)
+/* Search for the sequence:
+ *
+ *     lda     (xx),y
+ *     tax
+ *     dey
+ *     lda     (xx),y
+ *     jsr     bnegax
+ *     jne/jeq ...
+ *
+ * and replace it by
+ *
+ *     lda     (xx),y
+ *     dey
+ *     ora     (xx),y
+ *     jeq/jne ...
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[5];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_LDA                   &&
+           E->AM == AM_ZP_INDY                 &&
+           GetCodeEntries (S, L, I+1, 5)       &&
+           L[0]->OPC == OPC_TAX                &&
+           L[1]->OPC == OPC_DEY                &&
+           L[2]->OPC == OPC_LDA                &&
+           L[2]->AM == AM_ZP_INDY              &&
+           strcmp (L[2]->Arg, E->Arg) == 0     &&
+           !CodeEntryHasLabel (L[2])           &&
+           L[3]->OPC == OPC_JSR                &&
+           strcmp (L[3]->Arg, "bnegax") == 0   &&
+           !CodeEntryHasLabel (L[3])           &&
+                   (L[4]->Info & OF_ZBRA) != 0) {
+
+           /* lda --> ora */
+           ReplaceOPC (L[2], OPC_ORA);
+
+           /* Invert the branch */
+           ReplaceOPC (L[4], GetInverseBranch (L[4]->OPC));
+
+           /* Delete the entries no longer needed. Beware: Deleting entries
+            * will change the indices.
+            */
+                   DelCodeEntry (S, I+4);              /* jsr bnegax */
+           DelCodeEntry (S, I+1);              /* tax */
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+static unsigned OptNegAX2 (CodeSeg* S)
+/* Search for the sequence:
+ *
+ *     lda     xx
+ *     ldx     yy
+ *     jsr     bnegax
+ *     jne/jeq ...
+ *
+ * and replace it by
+ *
+ *     lda     xx
+ *     ora     xx+1
+ *     jeq/jne ...
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[3];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_LDA                   &&
+                   GetCodeEntries (S, L, I+1, 3)       &&
+           L[0]->OPC == OPC_LDX                &&
+           !CodeEntryHasLabel (L[0])           &&
+                   L[1]->OPC == OPC_JSR                &&
+           strcmp (L[1]->Arg, "bnegax") == 0   &&
+           !CodeEntryHasLabel (L[1])           &&
+                   (L[2]->Info & OF_ZBRA) != 0) {
+
+           /* ldx --> ora */
+           ReplaceOPC (L[0], OPC_ORA);
+
+           /* Invert the branch */
+                   ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC));
+
+           /* Delete the subroutine call */
+                   DelCodeEntry (S, I+2);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+static unsigned OptNegAX3 (CodeSeg* S)
+/* Search for the sequence:
+ *
+ *     jsr     _xxx
+ *     jsr     bnega(x)
+ *     jeq/jne ...
+ *
+ * and replace it by:
+ *
+ *      jsr    _xxx
+ *     <boolean test>
+ *     jne/jeq ...
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       CodeEntry* L[2];
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check for the sequence */
+               if (E->OPC == OPC_JSR                   &&
+           E->Arg[0] == '_'                    &&
+                   GetCodeEntries (S, L, I+1, 2)       &&
+                   L[0]->OPC == OPC_JSR                &&
+           strncmp (L[0]->Arg,"bnega",5) == 0  &&
+           !CodeEntryHasLabel (L[0])           &&
+                   (L[1]->Info & OF_ZBRA) != 0) {
+
+           /* Check if we're calling bnega or bnegax */
+           int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
+
+           /* Delete the subroutine call */
+           DelCodeEntry (S, I+1);
+
+           /* Insert apropriate test code */
+           if (ByteSized) {
+               /* Test bytes */
+               InsertCodeEntry (S, NewCodeEntry (OPC_TAX, AM_IMP, 0, 0), I+1);
+           } else {
+               /* Test words */
+               InsertCodeEntry (S, NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0), I+1);
+               InsertCodeEntry (S, NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0), I+2);
+           }
+
+           /* Invert the branch */
+                   ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -271,9 +587,21 @@ static OptFunc OptFuncs [] = {
     /* Optimize jump targets */
     { OptJumpTarget,               "OptJumpTarget",            0       },
     /* Optimize conditional branches */
-    { OptCondBranches,     "OptCondBranches",          0       },
+    { OptCondBranches,             "OptCondBranches",          0       },
+    /* Replace jumps to RTS by RTS */
+    { OptRTSJumps,                 "OptRTSJumps",              0       },
     /* Remove calls to the bool transformer subroutines        */
     { OptBoolTransforms,    "OptBoolTransforms",       0       },
+    /* Optimize calls to nega */
+    { OptNegA1,                    "OptNegA1",                 0       },
+    /* Optimize calls to nega */
+    { OptNegA2,                    "OptNegA2",                 0       },
+    /* Optimize calls to negax */
+    { OptNegAX1,                   "OptNegAX1",                0       },
+    /* Optimize calls to negax */
+    { OptNegAX2,                   "OptNegAX2",                0       },
+    /* Optimize calls to negax */
+    { OptNegAX3,                   "OptNegAX3",                0       },
     /* Remove unused loads */
     { OptUnusedLoads,      "OptUnusedLoads",           0       },
     /* Optimize branch distance */
index cb9664aebcabb6f91c0a847bd976b052a34fa816..8cf8bb070a9bee056c1fd81d544c304bf46e8b60 100644 (file)
@@ -155,7 +155,7 @@ static const char* SkipSpace (const char* S)
 
 
 static const char* ReadToken (const char* L, const char* Term,
-                             char* Buf, unsigned BufSize)
+                             char* Buf, unsigned BufSize)
 /* Read the next token into Buf, return the updated line pointer. The
  * token is terminated by one of the characters given in term.
  */
@@ -181,7 +181,7 @@ static const char* ReadToken (const char* L, const char* Term,
     /* Return the updated line pointer */
     return L;
 }
-
+       
 
 
 static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
@@ -197,7 +197,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
     am_t               AM = 0;         /* Initialize to keep gcc silent */
     char               Arg[64];
     char               Reg;
-    CodeEntry*         E;
+    CodeEntry*         E;
     CodeLabel*         Label;
 
     /* Mnemonic */
@@ -353,7 +353,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, AM, Arg, Label);
+    E = NewCodeEntry (OPC->OPC, AM, Arg, Label);
 
     /* Return the new code entry */
     return E;
@@ -393,7 +393,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
        S->ExitRegs = REG_NONE;
     }
 
-    /* Return the new struct */             
+    /* Return the new struct */
     return S;
 }
 
@@ -527,14 +527,6 @@ void DelCodeEntry (CodeSeg* S, unsigned Index)
 
 
 
-struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
-/* Get an entry from the given code segment */
-{
-    return CollAt (&S->Entries, Index);
-}
-
-
-
 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.
@@ -545,12 +537,34 @@ struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index)
        return 0;
     } else {
        /* Code entries left */
-       return CollAt (&S->Entries, Index+1);
+               return CollAtUnchecked (&S->Entries, Index+1);
     }
 }
 
 
 
+int GetCodeEntries (CodeSeg* S, struct CodeEntry** List,
+                           unsigned Start, unsigned Count)
+/* Get Count code entries into List starting at index start. Return true if
+ * we got the lines, return false if not enough lines were available.
+ */
+{
+    /* Check if enough entries are available */
+    if (Start + Count > CollCount (&S->Entries)) {
+       return 0;
+    }
+
+    /* Copy the entries */
+    while (Count--) {
+       *List++ = CollAtUnchecked (&S->Entries, Start++);
+    }
+
+    /* We have the entries */
+    return 1;
+}
+
+
+
 unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E)
 /* Return the index of a code entry */
 {
@@ -917,11 +931,6 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
 
 
 
-unsigned GetCodeEntryCount (const CodeSeg* S)
-/* Return the number of entries for the given code segment */
-{
-    return CollCount (&S->Entries);
-}
 
 
 
index 7904baa15aeab4b920d23dcb327c5a25bbef1d66..dd9105c3a0adae61f318bdf0a70b82ea4a74c261 100644 (file)
@@ -44,6 +44,7 @@
 /* common */
 #include "attrib.h"
 #include "coll.h"
+#include "inline.h"
 
 /* cc65 */
 #include "codelab.h"
@@ -106,14 +107,27 @@ void DelCodeEntry (CodeSeg* S, unsigned Index);
  * if the reference count drops to zero.
  */
 
-struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index);
+#if defined(HAVE_INLINE)
+INLINE struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
 /* Get an entry from the given code segment */
+{
+    return CollAt (&S->Entries, Index);
+}
+#else
+#  define GetCodeEntry(S, Index)       CollAt(&(S)->Entries, (Index))
+#endif
 
 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.
  */
 
+int GetCodeEntries (CodeSeg* S, struct CodeEntry** List,
+                           unsigned Start, unsigned Count);
+/* Get Count code entries into List starting at index start. Return true if
+ * we got the lines, return false if not enough lines were available.
+ */
+
 unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E);
 /* Return the index of a code entry */
 
@@ -162,8 +176,15 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last);
 void OutputCodeSeg (const CodeSeg* S, FILE* F);
 /* Output the code segment data to a file */
 
-unsigned GetCodeEntryCount (const CodeSeg* S);
+#if defined(HAVE_INLINE)
+INLINE unsigned GetCodeEntryCount (const CodeSeg* S)
 /* Return the number of entries for the given code segment */
+{
+    return CollCount (&S->Entries);
+}
+#else
+#  define GetCodeEntryCount(S) CollCount (&(S)->Entries)
+#endif
 
 
 
index 7843967dbe30ad6da07342f5a3cc22699f5d2989..5e263a8dca86afb286f27badf161ca8f78077379 100644 (file)
 
 
 
+/*****************************************************************************/
+/*                       Replace jumps to RTS by RTS                        */
+/*****************************************************************************/
+
+
+
+unsigned OptRTSJumps (CodeSeg* S)
+/* Replace jumps to RTS by RTS */
+{
+    unsigned Changes = 0;
+
+    /* Walk over all entries minus the last one */
+    unsigned I = 0;
+    while (I < GetCodeEntryCount (S)) {
+
+       /* Get the next entry */
+       CodeEntry* E = GetCodeEntry (S, I);
+
+               /* Check if it's an unconditional branch to a local target */
+               if ((E->Info & OF_UBRA) != 0            &&
+           E->JumpTo != 0                      &&
+           E->JumpTo->Owner->OPC == OPC_RTS) {
+
+           /* Delete the jump */
+           DelCodeEntry (S, I);
+
+           /* Insert an RTS instruction instead */
+           InsertCodeEntry (S, NewCodeEntry (OPC_RTS, AM_IMP, 0, 0), I);
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                            Remove dead jumps                             */
 /*****************************************************************************/
@@ -118,9 +163,11 @@ unsigned OptDeadCode (CodeSeg* S)
        return 0;
     }
 
-    /* Walk over all entries minus the last one */
+    /* Walk over all entries */
     I = 0;
-    while (I < Count-1) {
+    while (I < Count) {
+
+       CodeEntry* N;
 
        /* Get this entry */
        CodeEntry* E = GetCodeEntry (S, I);
@@ -128,7 +175,9 @@ unsigned OptDeadCode (CodeSeg* S)
                /* Check if it's an unconditional branch, and if the next entry has
         * no labels attached
         */
-               if ((E->Info & OF_DEAD) != 0 && !CodeEntryHasLabel (GetCodeEntry (S, I+1))) {
+               if ((E->Info & OF_DEAD) != 0            &&
+           (N = GetNextCodeEntry (S, I)) != 0  &&
+           !CodeEntryHasLabel (N)) {
 
            /* Delete the next entry */
            DelCodeEntry (S, I+1);
index bf67a20eb4bcd17859959d22753d321ba84e1cdd..d0afc5c0f7fe2f06407bb48ce649c2acd7c291e0 100644 (file)
 
 
 
-unsigned OptDeadJumps (CodeSeg* S);
+unsigned OptRTSJumps (CodeSeg* S);
+/* Replace jumps to RTS by RTS */
+
+unsigned OptDeadJumps (CodeSeg* S); 
 /* Remove dead jumps (jumps to the next instruction) */
 
 unsigned OptDeadCode (CodeSeg* S);
index 476f674f49b8733ad7838f51d77173c27b108de6..b9e51903644285b5040f77cc5a61ca197fe0e18f 100644 (file)
 
 
 
-/* Mapper table, mnemonic --> opcode */
-static const OPCDesc OPCTable[OPC_COUNT] = {
-    { OPC_ADC, "adc", 0, REG_A,           REG_A,    OF_NONE            },
-    { OPC_AND, "and", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_ASL, "asl", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BIT, "bit", 0, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA           },
-    { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA           },
-    { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_CMP, "cmp", 0, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_CPX, "cpx", 0, REG_X,    REG_NONE, OF_NONE           },
-    { OPC_CPY, "cpy", 0, REG_Y,    REG_NONE, OF_NONE           },
-    { OPC_DEA, "dea", 1, REG_A,    REG_A,    OF_NONE           },
-    { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_DEX, "dex", 1, REG_X,    REG_X,    OF_NONE           },
-    { OPC_DEY, "dey", 1, REG_Y,    REG_Y,    OF_NONE           },
-    { OPC_EOR, "eor", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_INA, "ina", 1, REG_A,    REG_A,    OF_NONE           },
-    { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_INX, "inx", 1, REG_X,    REG_X,    OF_NONE           },
-    { OPC_INY, "iny", 1, REG_Y,    REG_Y,    OF_NONE           },
-    { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA  },
-    { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA  },
-    { OPC_LDA, "lda", 0, REG_NONE, REG_A,    OF_LOAD                   },
-    { OPC_LDX, "ldx", 0, REG_NONE, REG_X,    OF_LOAD           },
-    { OPC_LDY, "ldy", 0, REG_NONE, REG_Y,    OF_LOAD           },
-    { OPC_LSR, "lsr", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_ORA, "ora", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_PHA, "pha", 1, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_PHX, "phx", 1, REG_X,    REG_NONE, OF_NONE           },
-    { OPC_PHY, "phy", 1, REG_Y,    REG_NONE, OF_NONE           },
-    { OPC_PLA, "pla", 1, REG_NONE, REG_A,    OF_NONE           },
-    { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_PLX, "plx", 1, REG_NONE, REG_X,    OF_NONE           },
-    { OPC_PLY, "ply", 1, REG_NONE, REG_Y,    OF_NONE           },
-    { OPC_ROL, "rol", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_ROR, "ror", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET            },
-    { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET            },
-    { OPC_SBC, "sbc", 0, REG_A,    REG_A,    OF_NONE           },
-    { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE           },
-    { OPC_STA, "sta", 0, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_STX, "stx", 0, REG_X,    REG_NONE, OF_NONE           },
-    { OPC_STY, "sty", 0, REG_Y,    REG_NONE, OF_NONE           },
-    { OPC_TAX, "tax", 1, REG_A,    REG_X,    OF_NONE           },
-    { OPC_TAY, "tay", 1, REG_A,    REG_Y,    OF_NONE           },
-    { OPC_TRB, "trb", 0, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_TSB, "tsb", 0, REG_A,    REG_NONE, OF_NONE           },
-    { OPC_TSX, "tsx", 1, REG_NONE, REG_X,    OF_NONE           },
-    { OPC_TXA, "txa", 1, REG_X,    REG_A,    OF_NONE           },
-    { OPC_TXS, "txs", 1, REG_X,    REG_NONE, OF_NONE           },
-    { OPC_TYA, "tya", 1, REG_A,    REG_A,    OF_NONE           },
+/* Opcode description table */
+const OPCDesc OPCTable[OPC_COUNT] = {
+    { OPC_ADC, "adc", 0, REG_A,           REG_A,    OF_NONE                        },
+    { OPC_AND, "and", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_ASL, "asl", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA             },
+    { OPC_BIT, "bit", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA             },
+    { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA                       },
+    { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CMP, "cmp", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_CPX, "cpx", 0, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_CPY, "cpy", 0, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_DEA, "dea", 1, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_DEX, "dex", 1, REG_X,    REG_X,    OF_NONE                       },
+    { OPC_DEY, "dey", 1, REG_Y,    REG_Y,    OF_NONE                       },
+    { OPC_EOR, "eor", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_INA, "ina", 1, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_INX, "inx", 1, REG_X,    REG_X,    OF_NONE                       },
+    { OPC_INY, "iny", 1, REG_Y,    REG_Y,    OF_NONE                       },
+    { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA    },
+    { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA             },
+    { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA    },
+    { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_LDA, "lda", 0, REG_NONE, REG_A,    OF_LOAD                               },
+    { OPC_LDX, "ldx", 0, REG_NONE, REG_X,    OF_LOAD                       },
+    { OPC_LDY, "ldy", 0, REG_NONE, REG_Y,    OF_LOAD                       },
+    { OPC_LSR, "lsr", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_ORA, "ora", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_PHA, "pha", 1, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_PHX, "phx", 1, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_PHY, "phy", 1, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_PLA, "pla", 1, REG_NONE, REG_A,    OF_NONE                       },
+    { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_PLX, "plx", 1, REG_NONE, REG_X,    OF_NONE                       },
+    { OPC_PLY, "ply", 1, REG_NONE, REG_Y,    OF_NONE                       },
+    { OPC_ROL, "rol", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_ROR, "ror", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET                        },
+    { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET                        },
+    { OPC_SBC, "sbc", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_STA, "sta", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_STX, "stx", 0, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_STY, "sty", 0, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_TAX, "tax", 1, REG_A,    REG_X,    OF_NONE                       },
+    { OPC_TAY, "tay", 1, REG_A,    REG_Y,    OF_NONE                       },
+    { OPC_TRB, "trb", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_TSB, "tsb", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_TSX, "tsx", 1, REG_NONE, REG_X,    OF_NONE                       },
+    { OPC_TXA, "txa", 1, REG_X,    REG_A,    OF_NONE                       },
+    { OPC_TXS, "txs", 1, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_TYA, "tya", 1, REG_A,    REG_A,    OF_NONE                       },
 };
 
 
@@ -203,30 +203,6 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
 
 
 
-const OPCDesc* GetOPCDesc (opc_t OPC)
-/* Get an opcode description */
-{
-    /* Check the range */
-    PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
-
-    /* Return the description */
-    return &OPCTable [OPC];
-}
-
-
-
-unsigned char GetOPCInfo (opc_t OPC)
-/* Get opcode information */
-{
-    /* Check the range */
-    PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
-
-    /* Return the info */
-    return OPCTable[OPC].Info;
-}
-
-
-
 unsigned char GetAMUseInfo (am_t AM)
 /* Get usage info for the given addressing mode (addressing modes that use
  * index registers return REG_r info for these registers).
index c4898b09122d18b99ab0000fd4422e284bbf35f3..b9d297f90e2dd1b055a65789d98dd2b291a94011 100644 (file)
 
 
 
+/* common */
+#include "inline.h"
+
+
+
 /*****************************************************************************/
 /*                                  Data                                    */
 /*****************************************************************************/
@@ -155,7 +160,8 @@ typedef enum {
 #define OF_NONE        0x0000U                 /* No additional information */
 #define OF_UBRA        0x0001U                 /* Unconditional branch */
 #define OF_CBRA        0x0002U                 /* Conditional branch */
-#define OF_LBRA 0x0004U                        /* Jump/branch is long */
+#define OF_ZBRA 0x0004U                        /* Branch on zero flag condition */
+#define OF_LBRA 0x0008U                        /* Jump/branch is long */
 #define OF_RET         0x0010U                 /* Return from function */
 #define OF_LOAD 0x0020U                        /* Register load */
 #define OF_BRA         (OF_UBRA|OF_CBRA)       /* Operation is a jump/branch */
@@ -171,6 +177,9 @@ typedef struct {
     unsigned char   Info;                      /* Additional information */
 } OPCDesc;
 
+/* Opcode description table */
+extern const OPCDesc OPCTable[OPC_COUNT];
+
 
 
 /*****************************************************************************/
@@ -187,11 +196,27 @@ const OPCDesc* FindOpcode (const char* OPC);
 unsigned GetInsnSize (opc_t OPC, am_t AM);
 /* Return the size of the given instruction */
 
-const OPCDesc* GetOPCDesc (opc_t OPC);
+#if defined(HAVE_INLINE)
+INLINE const OPCDesc* GetOPCDesc (opc_t OPC)
 /* Get an opcode description */
+{
+    /* Return the description */
+    return &OPCTable [OPC];
+}
+#else
+#  define GetOPCDesc(OPC)      (&OPCTable [(OPC)])
+#endif
 
-unsigned char GetOPCInfo (opc_t OPC);
+#if defined(HAVE_INLINE)
+INLINE unsigned char GetOPCInfo (opc_t OPC)
 /* Get opcode information */
+{
+    /* Return the info */
+    return OPCTable[OPC].Info;
+}
+#else
+#  define GetOPCInfo(OPC)      (OPCTable[(OPC)].Info)
+#endif
 
 unsigned char GetAMUseInfo (am_t AM);
 /* Get usage info for the given addressing mode (addressing modes that use