]> git.sur5r.net Git - cc65/commitdiff
Fixed a bug that didn't preserve the accumulator's value when a simple 16-bit fetch...
authorgreg-king5 <greg.king5@verizon.net>
Sat, 12 May 2018 17:46:16 +0000 (13:46 -0400)
committerGitHub <noreply@github.com>
Sat, 12 May 2018 17:46:16 +0000 (13:46 -0400)
Fix a 16-bit fetch-and-store cc65 optimizer bug.

src/cc65/coptstore.c
test/val/assign-use1.c [new file with mode: 0644]

index 56343c95b7a03c847135583904ea2f97b2a50a65..b0dfe3b6d52d8de36baad0760aeeb8395c735b09 100644 (file)
@@ -380,48 +380,48 @@ unsigned OptStore5 (CodeSeg* S)
 **      sta     something
 **      stx     something-else
 **
-** and replace it by
+** and, replace it by
 **
-**      lda     foo
-**      sta     something
 **      lda     bar
 **      sta     something-else
+**      lda     foo
+**      sta     something
 **
-** if X is not used later. This replacement doesn't save any cycles or bytes,
-** but it keeps the value of X, which may be reused later.
+** if the new value of X is not used later. That replacement doesn't save any
+** cycles or bytes; but, it keeps the old value of X, which may be reused later.
 */
 {
     unsigned Changes = 0;
+    unsigned I = 0;
 
     /* Walk over the entries */
-    unsigned I = 0;
     while (I < CS_GetEntryCount (S)) {
-
         CodeEntry* L[4];
 
         /* Get next entry */
         L[0] = CS_GetEntry (S, I);
 
         /* Check for the sequence */
-        if (L[0]->OPC == OP65_LDA                           &&
-            !CS_RangeHasLabel (S, I+1, 3)                   &&
-            CS_GetEntries (S, L+1, I+1, 3)                  &&
-            L[1]->OPC == OP65_LDX                           &&
-            L[2]->OPC == OP65_STA                           &&
-            L[3]->OPC == OP65_STX                           &&
+        if (L[0]->OPC == OP65_LDA               &&
+            !CS_RangeHasLabel (S, I+1, 3)       &&
+            CS_GetEntries (S, L+1, I+1, 3)      &&
+            L[1]->OPC == OP65_LDX               &&
+            L[2]->OPC == OP65_STA               &&
+            L[3]->OPC == OP65_STX               &&
             !RegXUsed (S, I+4)) {
 
-            CodeEntry* X;
+            CodeEntry* E = CS_GetEntry (S, I+1);
 
-            /* Insert the code after the sequence */
-            X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
-            CS_InsertEntry (S, X, I+4);
-            X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
-            CS_InsertEntry (S, X, I+5);
+            /* Move the high-byte code to the beginning of the sequence */
+            CS_MoveEntry (S, I+1, I);
+            CS_MoveEntry (S, I+3, I+1);
 
-            /* Delete the old code */
-            CS_DelEntry (S, I+3);
-            CS_DelEntry (S, I+1);
+            /* Change from the X register to the A register */
+            CE_ReplaceOPC (E, OP65_LDA);
+            CE_ReplaceOPC (CS_GetEntry (S, I+1), OP65_STA);
+
+            /* Move labels from the old first entry to the new first entry */
+            CS_MoveLabels (S, CS_GetEntry (S, I+2), E);
 
             /* Remember, we had changes */
             ++Changes;
@@ -429,7 +429,6 @@ unsigned OptStore5 (CodeSeg* S)
 
         /* Next entry */
         ++I;
-
     }
 
     /* Return the number of changes made */
diff --git a/test/val/assign-use1.c b/test/val/assign-use1.c
new file mode 100644 (file)
index 0000000..7440235
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+  !!DESCRIPTION!! Assign an int; then, do an operation that depends directly on that assignment.
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Greg King
+*/
+
+#include <stdio.h>
+
+static unsigned char failures = 0;
+
+static unsigned int result;
+static const unsigned int buffer = 0xABCD;
+
+int main(void)
+{
+    result = buffer;
+
+    /* Shift doesn't use high byte (X register); previous assignment should be optimized. */
+    result <<= 8;
+    if (result != 0xCD00) {
+        ++failures;
+        printf("assign-use1: left shift is $%X, not $CD00.\n", result);
+    }
+
+    result = buffer;
+
+    /* Shift does use high byte; previous assignment shouldn't be optimized by OptStore5(). */
+    result >>= 8;
+    if (result != 0x00AB) {
+        ++failures;
+        printf("assign-use1: right shift is $%X, not $00AB.\n", result);
+    }
+
+    return failures;
+}