]> git.sur5r.net Git - cc65/commitdiff
Better register tracking in the optimizer
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 24 Jul 2001 17:07:33 +0000 (17:07 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 24 Jul 2001 17:07:33 +0000 (17:07 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@812 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeent.c
src/cc65/codeent.h
src/cc65/codelab.h
src/cc65/codeseg.c
src/cc65/codeseg.h
src/cc65/coptind.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/reginfo.c [new file with mode: 0644]
src/cc65/reginfo.h [new file with mode: 0644]

index fbbd5b6e78404c89d6bdea9f293d62e21141e98b..e6f9fe542949073ea7fc99f0b6ad69636d5f1398 100644 (file)
@@ -161,7 +161,7 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
 
 
 CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
-                        CodeLabel* JumpTo, LineInfo* LI)
+                        CodeLabel* JumpTo, LineInfo* LI)
 /* Create a new code entry, initialize and return it */
 {
     /* Get the opcode description */
@@ -179,6 +179,7 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
     E->Size   = GetInsnSize (E->OPC, E->AM);
     E->JumpTo = JumpTo;
     E->LI     = UseLineInfo (LI);
+    E->RI     = 0;
     SetUseChgInfo (E, D);
     InitCollection (&E->Labels);
 
@@ -205,6 +206,9 @@ void FreeCodeEntry (CodeEntry* E)
     /* Release the line info */
     ReleaseLineInfo (E->LI);
 
+    /* Delete the register info */
+    CE_FreeRegInfo (E);
+
     /* Free the entry */
     xfree (E);
 }
@@ -273,6 +277,384 @@ void CE_SetArg (CodeEntry* E, const char* Arg)
 
 
 
+int CE_KnownImm (const CodeEntry* E)
+/* Return true if the argument of E is a known immediate value */
+{
+    return (E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0);
+}
+
+
+
+void CE_FreeRegInfo (CodeEntry* E)
+/* Free an existing register info struct */
+{
+    if (E->RI) {
+       FreeRegInfo (E->RI);
+       E->RI = 0;
+    }
+}
+
+
+
+void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
+/* Generate register info for this instruction. If an old info exists, it is
+ * overwritten.
+ */
+{
+    /* Pointers to the register contents */
+    RegContents* In;
+    RegContents* Out;
+
+    /* Function register usage */
+    unsigned char Use, Chg;
+
+    /* If we don't have a register info struct, allocate one. */
+    if (E->RI == 0) {
+       E->RI = NewRegInfo (InputRegs);
+    } else {
+       if (InputRegs) {
+           E->RI->In  = *InputRegs;
+       } else {
+           RC_Invalidate (&E->RI->In);
+       }
+       E->RI->Out = E->RI->In;
+    }
+
+    /* Get pointers to the register contents */
+    In  = &E->RI->In;
+    Out        = &E->RI->Out;
+
+    /* Handle the different instructions */
+    switch (E->OPC) {
+
+       case OP65_ADC:
+           /* We don't know the value of the carry, so the result is
+            * always unknown.
+            */
+           Out->RegA = -1;
+           break;
+
+       case OP65_AND:
+                   if (In->RegA >= 0) {
+               if (CE_KnownImm (E)) {
+                   Out->RegA = In->RegA & (short) E->Num;
+               } else {
+                   Out->RegA = -1;
+               }
+           }
+           break;
+
+       case OP65_ASL:
+           if (E->AM == AM65_ACC && In->RegA >= 0) {
+               Out->RegA = (In->RegA << 1) & 0xFF;
+           }
+           break;
+
+       case OP65_BCC:
+           break;
+
+       case OP65_BCS:
+           break;
+
+       case OP65_BEQ:
+           break;
+
+       case OP65_BIT:
+           break;
+
+       case OP65_BMI:
+           break;
+
+       case OP65_BNE:
+           break;
+
+       case OP65_BPL:
+           break;
+
+       case OP65_BRA:
+           break;
+
+       case OP65_BRK:
+           break;
+
+       case OP65_BVC:
+           break;
+
+       case OP65_BVS:
+           break;
+
+       case OP65_CLC:
+           break;
+
+       case OP65_CLD:
+           break;
+
+       case OP65_CLI:
+           break;
+
+       case OP65_CLV:
+           break;
+
+       case OP65_CMP:
+           break;
+
+       case OP65_CPX:
+           break;
+
+       case OP65_CPY:
+           break;
+
+       case OP65_DEA:
+           if (In->RegA >= 0) {
+               Out->RegA = In->RegA - 1;
+           }
+           break;
+
+       case OP65_DEC:
+           if (E->AM == AM65_ACC && In->RegA >= 0) {
+               Out->RegA = In->RegA - 1;
+           }
+           break;
+
+       case OP65_DEX:
+                   if (In->RegX >= 0) {
+               Out->RegX = In->RegX - 1;
+           }
+           break;
+
+       case OP65_DEY:
+                   if (In->RegY >= 0) {
+               Out->RegY = In->RegY - 1;
+           }
+           break;
+
+       case OP65_EOR:
+                   if (In->RegA >= 0) {
+               if (CE_KnownImm (E)) {
+                   Out->RegA = In->RegA ^ (short) E->Num;
+               } else {
+                   Out->RegA = -1;
+               }
+           }
+           break;
+
+       case OP65_INA:
+           if (In->RegA >= 0) {
+               Out->RegA = In->RegA + 1;
+           }
+           break;
+
+       case OP65_INC:
+           if (E->AM == AM65_ACC && In->RegA >= 0) {
+               Out->RegA = In->RegA + 1;
+           }
+           break;
+
+       case OP65_INX:
+           if (In->RegX >= 0) {
+               Out->RegX = In->RegX + 1;
+           }
+           break;
+
+       case OP65_INY:
+           if (In->RegY >= 0) {
+               Out->RegY = In->RegY + 1;
+           }
+           break;
+
+       case OP65_JCC:
+           break;
+
+       case OP65_JCS:
+           break;
+
+       case OP65_JEQ:
+           break;
+
+       case OP65_JMI:
+           break;
+
+       case OP65_JMP:
+           break;
+
+       case OP65_JNE:
+           break;
+
+       case OP65_JPL:
+           break;
+
+       case OP65_JSR:
+           /* Get the code info for the function */
+           GetFuncInfo (E->Arg, &Use, &Chg);
+           if (Chg & REG_A) {
+               Out->RegA = -1;
+           }
+           if (Chg & REG_X) {
+               Out->RegX = -1;
+           }
+           if (Chg & REG_Y) {
+               Out->RegY = -1;
+           }
+           break;
+
+       case OP65_JVC:
+           break;
+
+       case OP65_JVS:
+           break;
+
+       case OP65_LDA:
+           if (CE_KnownImm (E)) {
+               Out->RegA = (unsigned char) E->Num;
+           } else {
+               /* A is now unknown */
+               Out->RegA = -1;
+           }
+           break;
+
+       case OP65_LDX:
+           if (CE_KnownImm (E)) {
+               Out->RegX = (unsigned char) E->Num;
+           } else {
+               /* X is now unknown */
+               Out->RegX = -1;
+           }
+           break;
+
+       case OP65_LDY:
+           if (CE_KnownImm (E)) {
+               Out->RegY = (unsigned char) E->Num;
+           } else {
+               /* Y is now unknown */
+               Out->RegY = -1;
+           }
+           break;
+
+       case OP65_LSR:
+           if (E->AM == AM65_ACC && In->RegA >= 0) {
+               Out->RegA = (In->RegA >> 1) & 0xFF;
+           }
+           break;
+
+       case OP65_NOP:
+           break;
+
+       case OP65_ORA:
+           if (In->RegA >= 0) {
+               if (CE_KnownImm (E)) {
+                   Out->RegA = In->RegA | (short) E->Num;
+               } else {
+                   /* A is now unknown */
+                   Out->RegA = -1;
+               }
+           }
+           break;
+
+       case OP65_PHA:
+           break;
+
+       case OP65_PHP:
+           break;
+
+       case OP65_PHX:
+           break;
+
+       case OP65_PHY:
+           break;
+
+       case OP65_PLA:
+           Out->RegA = -1;
+           break;
+
+       case OP65_PLP:
+           break;
+
+       case OP65_PLX:
+           Out->RegX = -1;
+           break;
+
+       case OP65_PLY:
+           Out->RegY = -1;
+           break;
+
+       case OP65_ROL:
+           Out->RegA = -1;
+           break;
+
+       case OP65_ROR:
+           Out->RegA = -1;
+           break;
+
+       case OP65_RTI:
+           break;
+
+       case OP65_RTS:
+           break;
+
+       case OP65_SBC:
+           /* We don't know the value of the carry bit */
+           Out->RegA = -1;
+           break;
+
+       case OP65_SEC:
+           break;
+
+       case OP65_SED:
+           break;
+
+       case OP65_SEI:
+           break;
+
+       case OP65_STA:
+           break;
+
+       case OP65_STX:
+           break;
+
+       case OP65_STY:
+           break;
+
+       case OP65_TAX:
+           Out->RegX = In->RegA;
+           break;
+
+       case OP65_TAY:
+           Out->RegY = In->RegA;
+           break;
+
+       case OP65_TRB:
+           /* For now... */
+           Out->RegA = -1;
+           break;
+
+       case OP65_TSB:
+           /* For now... */
+           Out->RegA = -1;
+           break;
+
+       case OP65_TSX:
+           Out->RegX = -1;
+           break;
+
+       case OP65_TXA:
+           Out->RegA = In->RegX;
+           break;
+
+       case OP65_TXS:
+           break;
+
+       case OP65_TYA:
+           Out->RegA = In->RegY;
+           break;
+
+       default:
+           break;
+
+    }
+}
+
+
+
 void CE_Output (const CodeEntry* E, FILE* F)
 /* Output the code entry to a file */
 {
@@ -311,7 +693,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
            /* immidiate */
            Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
            break;
-                   
+
        case AM_ABS:
        case AM65_ZP:
        case AM65_ABS:
index 278e471bd3528506d6aa4941cc0a5c0ef88df19e..c698f7a563fe4433eceebc6e8f8c9186a52b0936 100644 (file)
@@ -48,6 +48,7 @@
 #include "codelab.h"
 #include "lineinfo.h"
 #include "opcodes.h"
+#include "reginfo.h"
 
 
 
@@ -76,6 +77,7 @@ struct CodeEntry {
     CodeLabel*         JumpTo;         /* Jump label */
     Collection         Labels;         /* Labels for this instruction */
     LineInfo*           LI;             /* Source line info for this insn */
+    RegInfo*            RI;             /* Register info for this insn */
 };
 
 
@@ -87,7 +89,7 @@ struct CodeEntry {
 
 
 CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
-                        CodeLabel* JumpTo, LineInfo* LI);
+                        CodeLabel* JumpTo, LineInfo* LI);
 /* Create a new code entry, initialize and return it */
 
 void FreeCodeEntry (CodeEntry* E);
@@ -170,6 +172,17 @@ INLINE void CE_ResetMark (CodeEntry* E)
 void CE_SetArg (CodeEntry* E, const char* Arg);
 /* Set a new argument for the given code entry. An old string is deleted. */
 
+int CE_KnownImm (const CodeEntry* E);
+/* Return true if the argument of E is a known immediate value */
+
+void CE_FreeRegInfo (CodeEntry* E);
+/* Free an existing register info struct */
+
+void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs);
+/* Generate register info for this instruction. If an old info exists, it is
+ * overwritten.
+ */
+
 void CE_Output (const CodeEntry* E, FILE* F);
 /* Output the code entry to a file */
 
@@ -180,4 +193,4 @@ void CE_Output (const CodeEntry* E, FILE* F);
 
 
 
-        
+
index c2871c9bc3f49272aa6f7d4d932893a26dd98e38..8f298e0fbcada69b2c4002e3be48a76738cc7d6b 100644 (file)
@@ -85,6 +85,26 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
 void FreeCodeLabel (CodeLabel* L);
 /* Free the given code label */
 
+#if defined(HAVE_INLINE)
+INLINE unsigned CL_GetRefCount (const CodeLabel* L)
+/* Get the number of references for this label */
+{
+    return CollCount (&L->JumpFrom);
+}
+#else
+#  define CL_GetRefCount(L)            CollCount (&(L)->JumpFrom)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
+/* Get a code entry referencing this label */
+{
+    return CollAt (&L->JumpFrom, Index);
+}
+#else
+#  define CL_GetRef(L, Index)          CollAt (&(L)->JumpFrom, (Index))
+#endif
+
 void CL_AddRef (CodeLabel* L, struct CodeEntry* E);
 /* Let the CodeEntry E reference the label L */
 
index a82073aa4d5047fa1394a3a4e7583fcf8f22a206..84c32797ccabecb0909cf0bf1eb336429ac48f64 100644 (file)
@@ -63,7 +63,7 @@
 
 
 static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E)
-/* Move all labels from the label pool to the given entry and remove them 
+/* Move all labels from the label pool to the given entry and remove them
  * from the pool.
  */
 {
@@ -545,7 +545,7 @@ void CS_DelEntry (CodeSeg* S, unsigned Index)
     FreeCodeEntry (E);
 }
 
-                  
+
 
 void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count)
 /* Delete a range of code entries. This includes removing references to labels,
@@ -1000,4 +1000,104 @@ void CS_Output (const CodeSeg* S, FILE* F)
 
 
 
+void CS_FreeRegInfo (CodeSeg* S)
+/* Free register infos for all instructions */
+{
+    unsigned I;
+    for (I = 0; I < CS_GetEntryCount (S); ++I) {
+        CE_FreeRegInfo (CS_GetEntry(S, I));
+    }
+}
+
+
+
+void CS_GenRegInfo (CodeSeg* S)
+/* Generate register infos for all instructions */
+{
+    unsigned I;
+    RegContents Regs;
+    RegContents* CurrentRegs;
+    int WasJump;
+
+    /* Be sure to delete all register infos */
+    CS_FreeRegInfo (S);
+
+    /* On entry, the register contents are unknown */
+    RC_Invalidate (&Regs);
+    CurrentRegs = &Regs;
+
+    /* First pass. Walk over all insns an note just the changes from one
+     * insn to the next one.
+     */
+    WasJump = 0;
+    for (I = 0; I < CS_GetEntryCount (S); ++I) {
+
+       /* Get the next instruction */
+       CodeEntry* E = CollAtUnchecked (&S->Entries, I);
+
+       /* If the instruction has a label, we need some special handling */
+       unsigned LabelCount = CE_GetLabelCount (E);
+       if (LabelCount > 0) {
+
+           /* Loop over all entry points that jump here. If these entry
+            * points already have register info, check if all values are
+            * known and identical. If all values are identical, and the
+            * preceeding instruction was not an unconditional branch, check
+            * if the register value on exit of the preceeding instruction
+            * is also identical. If all these values are identical, the
+            * value of a register is known, otherwise it is unknown.
+            */
+           CodeLabel* Label = CE_GetLabel (E, 0);
+           unsigned Entry;
+           if (WasJump) {
+               /* Preceeding insn was an unconditional branch */
+               CodeEntry* J = CL_GetRef(Label, 0);
+               if (J->RI) {
+                   Regs = J->RI->Out;
+               } else {
+                   RC_Invalidate (&Regs);
+               }
+               Entry = 1;
+           } else {
+               Regs = *CurrentRegs;
+               Entry = 0;
+           }
+
+           while (Entry < CL_GetRefCount (Label)) {
+               /* Get this entry */
+               CodeEntry* J = CL_GetRef (Label, Entry);
+               if (J->RI == 0) {
+                   /* No register info for this entry, bail out */
+                   RC_Invalidate (&Regs);
+                   break;
+               }
+               if (J->RI->Out.RegA != Regs.RegA) {
+                   Regs.RegA = -1;
+               }
+               if (J->RI->Out.RegX != Regs.RegX) {
+                   Regs.RegX = -1;
+               }
+               if (J->RI->Out.RegY != Regs.RegY) {
+                   Regs.RegY = -1;
+               }
+               ++Entry;
+           }
+
+           /* Use this register info */
+           CurrentRegs = &Regs;
+
+       }
+
+       /* Generate register info for this instruction */
+        CE_GenRegInfo (E, CurrentRegs);
+
+       /* Output registers for this insn are input for the next */
+       CurrentRegs = &E->RI->Out;
+
+       /* Remember for the next insn if this insn was an uncondition branch */
+       WasJump = (E->Info & OF_UBRA) != 0;
+    }
+}
+
+
 
index 59353e8894bcacfa970b8074a6f558a87be27910..99342f4234d11c1837d3c2deb6993c21647be69f 100644 (file)
@@ -215,6 +215,12 @@ INLINE unsigned CS_GetEntryCount (const CodeSeg* S)
 #  define CS_GetEntryCount(S)  CollCount (&(S)->Entries)
 #endif
 
+void CS_FreeRegInfo (CodeSeg* S);
+/* Free register infos for all instructions */
+
+void CS_GenRegInfo (CodeSeg* S);
+/* Generate register infos for all instructions */
+
 
 
 /* End of codeseg.h */
index ba1ffdc7fb87f4b3c51e88d91b9478ac676146e4..36ca5b3d7dd04e8b3ce6cc6dc255bd50f7d80d4f 100644 (file)
 
 
 
-/*****************************************************************************/
-/*                                 Helpers                                  */
-/*****************************************************************************/
-
-
-
-static int IsKnownImm (const CodeEntry* E)
-/* Return true if the argument of E is a known immediate value */
-{
-    return (E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0);
-}
-
-
-
 /*****************************************************************************/
 /*                       Replace jumps to RTS by RTS                        */
 /*****************************************************************************/
@@ -670,312 +656,56 @@ unsigned OptDuplicateLoads (CodeSeg* S)
 /* Remove loads of registers where the value loaded is already in the register. */
 {
     unsigned Changes = 0;
+    unsigned I;
 
-    /* Remember the last load instructions for all registers */
-    int RegA = -1;
-    int RegX = -1;
-    int RegY = -1;
+    /* Generate register info for this step */
+    CS_GenRegInfo (S);
 
     /* Walk over the entries */
-    unsigned I = 0;
+    I = 0;
     while (I < CS_GetEntryCount (S)) {
 
-       unsigned char Use, Chg;
-       CodeEntry* N;
+       CodeEntry* N;
 
        /* Get next entry */
                CodeEntry* E = CS_GetEntry (S, I);
 
-       /* Assume we won't delete the entry */
-       int Delete = 0;
-
-       /* If this entry has a label attached, remove all knownledge about the
-                * register contents. This may be improved but for now it's ok.
-        */
-       if (CE_HasLabel (E)) {
-           RegA = RegX = RegY = -1;
-       }
+       /* Assume we won't delete the entry */
+       int Delete = 0;
 
        /* Handle the different instructions */
        switch (E->OPC) {
 
-           case OP65_ADC:
-               /* We don't know the value of the carry, so the result is
-                * always unknown.
-                */
-               RegA = -1;
-               break;
-
-           case OP65_AND:
-               if (RegA >= 0) {
-                           if (IsKnownImm (E)) {
-                       RegA &= (int) E->Num;
-                   } else {
-                       RegA = -1;
-                   }
-               }
-               break;
-
-           case OP65_ASL:
-               if (RegA >= 0) {
-                   RegA = (RegA << 1) & 0xFF;
-               }
-               break;
-
-           case OP65_BCC:
-               break;
-
-           case OP65_BCS:
-               break;
-
-           case OP65_BEQ:
-               break;
-
-           case OP65_BIT:
-               break;
-
-           case OP65_BMI:
-               break;
-
-           case OP65_BNE:
-               break;
-
-           case OP65_BPL:
-               break;
-
-           case OP65_BRA:
-               break;
-
-           case OP65_BRK:
-               break;
-
-           case OP65_BVC:
-               break;
-
-           case OP65_BVS:
-               break;
-
-           case OP65_CLC:
-               break;
-
-           case OP65_CLD:
-               break;
-
-           case OP65_CLI:
-               break;
-
-           case OP65_CLV:
-               break;
-
-           case OP65_CMP:
-               break;
-
-           case OP65_CPX:
-               break;
-
-           case OP65_CPY:
-               break;
-
-           case OP65_DEA:
-               DEC (RegA, 1);
-               break;
-
-           case OP65_DEC:
-               break;
-
-           case OP65_DEX:
-               DEC (RegX, 1);
-               break;
-
-           case OP65_DEY:
-               DEC (RegY, 1);
-               break;
-
-           case OP65_EOR:
-               if (RegA >= 0) {
-                           if (IsKnownImm (E)) {
-                               RegA ^= (int) E->Num;
-                   } else {
-                       RegA = -1;
-                   }
-               }
-               break;
-
-           case OP65_INA:
-               INC (RegA, 1);
-               break;
-
-           case OP65_INC:
-               break;
-
-           case OP65_INX:
-               INC (RegX, 1);
-               break;
-
-           case OP65_INY:
-               INC (RegY, 1);
-               break;
-
-           case OP65_JCC:
-               break;
-
-           case OP65_JCS:
-               break;
-
-           case OP65_JEQ:
-               break;
-
-           case OP65_JMI:
-               break;
-
-           case OP65_JMP:
-               break;
-
-           case OP65_JNE:
-               break;
-
-           case OP65_JPL:
-               break;
-
-           case OP65_JSR:
-               /* Get the code info for the function */
-               GetFuncInfo (E->Arg, &Use, &Chg);
-               if (Chg & REG_A) {
-                   RegA = -1;
-               }
-               if (Chg & REG_X) {
-                   RegX = -1;
-               }
-               if (Chg & REG_Y) {
-                   RegY = -1;
-               }
-               break;
-
-           case OP65_JVC:
-               break;
-
-           case OP65_JVS:
-               break;
-
            case OP65_LDA:
-               if (IsKnownImm (E)) {
-                   N = CS_GetNextEntry (S, I);
-                   if (RegA >= 0 && RegA == E->Num && N && (N->Info & OF_FBRA) == 0) {
-                       Delete = 1;
-                   } else {
-                       RegA = (unsigned char) E->Num;
-                   }
-               } else {
-                   /* A is now unknown */
-                   RegA = -1;
+               if (E->RI->In.RegA >= 0               && /* Value of A is known */
+                           CE_KnownImm (E)                   && /* Value to be loaded is known */
+                           E->RI->In.RegA == E->Num          && /* Both are equal */
+                           (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
+                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   Delete = 1;
                }
                break;
 
            case OP65_LDX:
-               if (IsKnownImm (E)) {
-                   N = CS_GetNextEntry (S, I);
-                           if (RegX >= 0 && RegX == E->Num && N && (N->Info & OF_FBRA) == 0) {
-                       Delete = 1;
-                   } else {
-                       RegX = (unsigned char) E->Num;
-                   }
-               } else {
-                   /* X is now unknown */
-                   RegX = -1;
+                       if (E->RI->In.RegX >= 0               && /* Value of X is known */
+                   CE_KnownImm (E)                   && /* Value to be loaded is known */
+                   E->RI->In.RegX == E->Num          && /* Both are equal */
+                           (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
+                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   Delete = 1;
                }
                break;
 
            case OP65_LDY:
-               if (IsKnownImm (E)) {
-                   N = CS_GetNextEntry (S, I);
-                           if (RegY >= 0 && RegY == E->Num && N && (N->Info & OF_FBRA) == 0) {
-                       Delete = 1;
-                   } else {
-                       RegY = (unsigned char) E->Num;
-                   }
-               } else {
-                   /* Y is now unknown */
-                   RegY = -1;
-               }
-               break;
-
-           case OP65_LSR:
-               if (RegA >= 0) {
-                   RegA = (RegA >> 1) & 0xFF;
-               }
-               break;
-
-           case OP65_NOP:
-               break;
-
-           case OP65_ORA:
-               if (RegA >= 0) {
-                   if (IsKnownImm (E)) {
-                       RegA |= (unsigned char) E->Num;
-                   } else {
-                       /* A is now unknown */
-                       RegA = -1;
-                   }
+                       if (E->RI->In.RegY >= 0               && /* Value of Y is known */
+                   CE_KnownImm (E)                   && /* Value to be loaded is known */
+                   E->RI->In.RegY == E->Num          && /* Both are equal */
+                           (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
+                   (N->Info & OF_FBRA) == 0) {          /* Which is not a cond branch */
+                   Delete = 1;
                }
                break;
 
-           case OP65_PHA:
-               break;
-
-           case OP65_PHP:
-               break;
-
-           case OP65_PHX:
-               break;
-
-           case OP65_PHY:
-               break;
-
-           case OP65_PLA:
-               RegA = -1;
-               break;
-
-           case OP65_PLP:
-               break;
-
-           case OP65_PLX:
-               RegX = -1;
-               break;
-
-           case OP65_PLY:
-               RegY = -1;
-               break;
-
-           case OP65_ROL:
-               RegA = -1;
-               break;
-
-           case OP65_ROR:
-               RegA = -1;
-               break;
-
-           case OP65_RTI:
-               break;
-
-           case OP65_RTS:
-               break;
-
-           case OP65_SBC:
-               RegA = -1;
-               break;
-
-           case OP65_SEC:
-               break;
-
-           case OP65_SED:
-               break;
-
-           case OP65_SEI:
-               break;
-
-           case OP65_STA:
-               break;
-
            case OP65_STX:
                /* If the value in the X register is known and the same as
                 * that in the A register, replace the store by a STA. The
@@ -983,11 +713,13 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                 * later. STX does support the zeropage,y addressing mode,
                 * so be sure to check for that.
                 */
-               if (RegX >= 0 && RegX == RegA &&
-                   E->AM != AM65_ABSY && E->AM != AM65_ZPY) {
+                       if (E->RI->In.RegX >= 0               &&
+                   E->RI->In.RegX == E->RI->In.RegA  &&
+                   E->AM != AM65_ABSY                &&
+                   E->AM != AM65_ZPY) {
                    /* Use the A register instead */
-                   CE_ReplaceOPC (E, OP65_STA);
-               }
+                           CE_ReplaceOPC (E, OP65_STA);
+               }                               
                break;
 
            case OP65_STY:
@@ -998,65 +730,54 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                 * replacement by X, but check for invalid addressing modes
                 * in this case.
                 */
-                       if (RegY >= 0) {
-                   if (RegY == RegA) {
-                       CE_ReplaceOPC (E, OP65_STA);
-                   } else if (RegY == RegX && E->AM != AM65_ABSX && E->AM != AM65_ZPX) {
-                       CE_ReplaceOPC (E, OP65_STX);
+                       if (E->RI->In.RegY >= 0) {
+                   if (E->RI->In.RegY == E->RI->In.RegA) {
+                       CE_ReplaceOPC (E, OP65_STA);
+                   } else if (E->RI->In.RegY == E->RI->In.RegX &&
+                              E->AM != AM65_ABSX               &&
+                              E->AM != AM65_ZPX) {
+                       CE_ReplaceOPC (E, OP65_STX);
                    }
                }
                break;
 
            case OP65_TAX:
-               N = CS_GetNextEntry (S, I);
-               if (RegA >= 0 && RegA == RegX && N && (N->Info & OF_FBRA) == 0) {
+                if (E->RI->In.RegA >= 0                 &&
+                   E->RI->In.RegA == E->RI->In.RegX    &&
+                   (N = CS_GetNextEntry (S, I)) != 0   &&
+                   (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
-               } else {
-                   RegX = RegA;
                }
                break;
 
            case OP65_TAY:
-               N = CS_GetNextEntry (S, I);
-                       if (RegA >= 0 && RegA == RegY && N && (N->Info & OF_FBRA) == 0) {
+                if (E->RI->In.RegA >= 0                 &&
+                   E->RI->In.RegA == E->RI->In.RegY    &&
+                   (N = CS_GetNextEntry (S, I)) != 0   &&
+                   (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
-               } else {
-                   RegY = RegA;
                }
                break;
 
-           case OP65_TRB:
-               break;
-
-           case OP65_TSB:
-               break;
-
-           case OP65_TSX:
-               RegX = -1;
-               break;
-
-           case OP65_TXA:
-               N = CS_GetNextEntry (S, I);
-                       if (RegX >= 0 && RegX == RegA && N && (N->Info & OF_FBRA) == 0) {
+                   case OP65_TXA:
+                if (E->RI->In.RegX >= 0                 &&
+                   E->RI->In.RegX == E->RI->In.RegA    &&
+                   (N = CS_GetNextEntry (S, I)) != 0   &&
+                   (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
-               } else {
-                   RegA = RegX;
                }
                break;
 
-           case OP65_TXS:
-               break;
-
            case OP65_TYA:
-               N = CS_GetNextEntry (S, I);
-                       if (RegY >= 0 && RegY == RegA && N && (N->Info & OF_FBRA) == 0) {
+                if (E->RI->In.RegY >= 0                 &&
+                   E->RI->In.RegY == E->RI->In.RegA    &&
+                   (N = CS_GetNextEntry (S, I)) != 0   &&
+                   (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
-               } else {
-                   RegA = RegY;
                }
                break;
 
index ff780220c4be2247278e8a59aac354533434bd10..38db8dffdca730b43dbb1587421af082d863726e 100644 (file)
@@ -58,6 +58,7 @@ OBJS =        anonname.o      \
        opcodes.o       \
        preproc.o       \
        pragma.o        \
+       reginfo.o       \
        scanner.o       \
        segments.o      \
        stdfunc.o       \
index 4b90b5dfe9bedcc08bb156a900c9dc759dbd9cd4..62a982120dbaad74916d2da4fd4410271eb444d9 100644 (file)
@@ -103,6 +103,7 @@ OBJS =      anonname.obj    \
        opcodes.obj     \
        preproc.obj     \
        pragma.obj      \
+       reginfo.obj     \
        scanner.obj     \
        segments.obj    \
        stdfunc.obj     \
@@ -170,6 +171,7 @@ FILE main.obj
 FILE opcodes.obj
 FILE preproc.obj
 FILE pragma.obj
+FILE reginfo.obj
 FILE scanner.obj
 FILE segments.obj
 FILE stdfunc.obj
diff --git a/src/cc65/reginfo.c b/src/cc65/reginfo.c
new file mode 100644 (file)
index 0000000..f62dd37
--- /dev/null
@@ -0,0 +1,93 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                reginfo.c                                 */
+/*                                                                           */
+/*                       6502 register tracking info                        */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2001      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* common */
+#include "xmalloc.h"
+
+/* cc65 */
+#include "reginfo.h"
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+void RC_Invalidate (RegContents* C)
+/* Invalidate all registers */
+{
+    C->RegA   = -1;
+    C->RegX   = -1;
+    C->RegY   = -1;
+    C->SRegLo = -1;
+    C->SRegHi = -1;
+}
+
+
+
+RegInfo* NewRegInfo (const RegContents* RC)
+/* Allocate a new register info, initialize and return it. If RC is not
+ * a NULL pointer, it is used to initialize both, the input and output
+ * registers. If the pointer is NULL, all registers are set to unknown.
+ */
+{
+    /* Allocate memory */
+    RegInfo* RI = xmalloc (sizeof (RegInfo));
+
+    /* Initialize the registers */
+    if (RC) {
+       RI->In  = *RC;
+       RI->Out = *RC;
+    } else {
+       RC_Invalidate (&RI->In);
+       RC_Invalidate (&RI->Out);
+    }
+
+    /* Return the new struct */
+    return RI;
+}
+
+
+
+void FreeRegInfo (RegInfo* RI)
+/* Free a RegInfo struct */
+{
+    xfree (RI);
+}
+
+
+
diff --git a/src/cc65/reginfo.h b/src/cc65/reginfo.h
new file mode 100644 (file)
index 0000000..21415a8
--- /dev/null
@@ -0,0 +1,95 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                reginfo.h                                 */
+/*                                                                           */
+/*                       6502 register tracking info                        */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2001      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef REGINFO_H
+#define REGINFO_H
+
+
+
+/* common */
+#include "inline.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Register contents */
+typedef struct RegContents RegContents;
+struct RegContents {
+    short              RegA;
+    short       RegX;
+    short       RegY;
+    short       SRegLo;
+    short       SRegHi;
+};
+
+/* Register change info */
+typedef struct RegInfo RegInfo;
+struct RegInfo {
+    RegContents        In;                     /* Incoming register values */
+    RegContents Out;                    /* Outgoing register values */
+};
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+void RC_Invalidate (RegContents* C);
+/* Invalidate all registers */
+
+RegInfo* NewRegInfo (const RegContents* RC);
+/* Allocate a new register info, initialize and return it. If RC is not
+ * a NULL pointer, it is used to initialize both, the input and output
+ * registers. If the pointer is NULL, all registers are set to unknown.
+ */
+
+void FreeRegInfo (RegInfo* RI);
+/* Free a RegInfo struct */
+
+
+
+/* End of reginfo.h */
+#endif
+
+
+