]> git.sur5r.net Git - cc65/commitdiff
Replace staxspidx if possible
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 13 Feb 2002 11:42:56 +0000 (11:42 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 13 Feb 2002 11:42:56 +0000 (11:42 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1153 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/coptstop.c

index a9575022f0ecde28674bd6eac0fc87eb377d8fef..dcb405709cbbe23c9818096192f66c06bd85dbb4 100644 (file)
@@ -157,6 +157,55 @@ static unsigned Opt_staspidx (CodeSeg* S, unsigned Push, unsigned Store,
 
 
 
+static unsigned Opt_staxspidx (CodeSeg* S, unsigned Push, unsigned Store,
+                              const char* ZPLo, const char* ZPHi)
+/* Optimize the staxspidx sequence if possible */
+{
+    CodeEntry* X;
+    CodeEntry* PushEntry;
+    CodeEntry* StoreEntry;
+
+    /* Get the push entry */
+    PushEntry = CS_GetEntry (S, Push);
+
+    /* Store the value into the zeropage instead of pushing it */
+    X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
+    CS_InsertEntry (S, X, Push+1);
+    X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
+    CS_InsertEntry (S, X, Push+2);
+
+    /* Correct the index of the store and get a pointer to the entry */
+    Store += 2;
+    StoreEntry = CS_GetEntry (S, Store);
+
+    /* Inline the store */
+    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, StoreEntry->LI);
+    CS_InsertEntry (S, X, Store+1);
+    X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, StoreEntry->LI);
+    CS_InsertEntry (S, X, Store+2);
+    if (StoreEntry->RI->In.RegX >= 0) {
+       /* Value of X is known */
+       char Buf [16];
+       xsprintf (Buf, sizeof (Buf), "$%02X", StoreEntry->RI->In.RegX);
+               X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, StoreEntry->LI);
+    } else {
+       /* Value unknown */
+       X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, StoreEntry->LI);
+    }
+    CS_InsertEntry (S, X, Store+3);
+    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, StoreEntry->LI);
+    CS_InsertEntry (S, X, Store+4);
+
+    /* Remove the push and the call to the staspidx function */
+    CS_DelEntry (S, Store);
+    CS_DelEntry (S, Push);
+
+    /* We changed the sequence */
+    return 1;
+}
+
+
+
 static unsigned Opt_tosaddax (CodeSeg* S, unsigned Push, unsigned Add,
                              const char* ZPLo, const char* ZPHi)
 /* Optimize the tosaddax sequence if possible */
@@ -492,20 +541,29 @@ static unsigned Opt_tosxorax (CodeSeg* S, unsigned Push, unsigned Xor,
 
 
 
+/* Flags for the functions */
+typedef enum {
+    STOP_NONE,             /* Nothing special */
+    STOP_A_UNUSED           /* Call only if a unused later */
+} STOP_FLAGS;
+
+
 typedef unsigned (*OptFunc) (CodeSeg* S, unsigned Push, unsigned Store,
-                            const char* ZPLo, const char* ZPHi);
+                            const char* ZPLo, const char* ZPHi);
 typedef struct OptFuncDesc OptFuncDesc;
 struct OptFuncDesc {
-    const char*         Name;   /* Name of the replaced runtime function */
-    OptFunc             Func;   /* Function pointer */
+    const char*     Name;   /* Name of the replaced runtime function */
+    OptFunc         Func;   /* Function pointer */
+    STOP_FLAGS      Flags;  /* Flags */
 };
 
 static const OptFuncDesc FuncTable[] = {
-    { "staspidx",       Opt_staspidx    },
-    { "tosaddax",       Opt_tosaddax    },
-    { "tosandax",       Opt_tosandax    },
-    { "tosorax",        Opt_tosorax     },
-    { "tosxorax",       Opt_tosxorax    },
+    { "staspidx",   Opt_staspidx,  STOP_NONE },
+    { "staxspidx",  Opt_staxspidx, STOP_A_UNUSED },
+    { "tosaddax",   Opt_tosaddax,  STOP_NONE },
+    { "tosandax",   Opt_tosandax,  STOP_NONE },
+    { "tosorax",    Opt_tosorax,   STOP_NONE },
+    { "tosxorax",   Opt_tosxorax,  STOP_NONE },
 };
 #define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0]))
 
@@ -586,28 +644,40 @@ unsigned OptStackOps (CodeSeg* S)
                const OptFuncDesc* F = FindFunc (E->Arg);
                if (F) {
 
-                   /* Determine the register to use */
-                   const char* ZPLo;
-                   const char* ZPHi;
-                           UsedRegs |= GetRegInfo (S, I+1, REG_SREG | REG_PTR1 | REG_PTR2);
-                   if ((UsedRegs & REG_SREG) == REG_NONE) {
-                       /* SREG is available */
-                       ZPLo = "sreg";
-                       ZPHi = "sreg+1";
-                   } else if ((UsedRegs & REG_PTR1) == REG_NONE) {
-                       ZPLo = "ptr1";
-                       ZPHi = "ptr1+1";
-                   } else if ((UsedRegs & REG_PTR2) == REG_NONE) {
-                       ZPLo = "ptr2";
-                       ZPHi = "ptr2+1";
-                   } else {
-                       /* No registers available */
-                       ZPLo = 0;
-                       ZPHi = 0;
-                   }
-
-                   /* If we have a register, call the optimizer function */
-                   if (ZPLo && ZPHi) {
+                   const char* ZPLo = 0;
+                   const char* ZPHi = 0;
+                   int PreCondOk    = 1;
+
+                   /* Check the flags */
+                   if (F->Flags & STOP_A_UNUSED) {
+                       /* a must be unused later */
+                       if (RegAUsed (S, I+1)) {
+                           /* Cannot optimize */
+                           PreCondOk = 0;
+                       }
+                   }
+
+                   /* Determine the zero page locations to use */
+                   if (PreCondOk) {
+                       UsedRegs |= GetRegInfo (S, I+1, REG_SREG | REG_PTR1 | REG_PTR2);
+                       if ((UsedRegs & REG_SREG) == REG_NONE) {
+                           /* SREG is available */
+                           ZPLo = "sreg";
+                           ZPHi = "sreg+1";
+                       } else if ((UsedRegs & REG_PTR1) == REG_NONE) {
+                           ZPLo = "ptr1";
+                           ZPHi = "ptr1+1";
+                       } else if ((UsedRegs & REG_PTR2) == REG_NONE) {
+                           ZPLo = "ptr2";
+                           ZPHi = "ptr2+1";
+                       } else {
+                           /* No registers available */
+                           PreCondOk = 0;
+                       }
+                   }
+
+                   /* If preconditions are ok, call the optimizer function */
+                   if (PreCondOk) {
 
                        /* Adjust stack offsets */
                        unsigned Op = I + AdjustStackOffset (S, Push, I, 2);