From 2b2c082efb11920ec7e720402079c2d2dae345b8 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira Date: Sun, 20 Jul 2025 14:36:30 +0200 Subject: [PATCH] Fix bug in PR #2778 Don't replace incaxy like incax[1-8]. --- src/cc65/codeopt.c | 2 ++ src/cc65/coptmisc.c | 64 +++++++++++++++++++++++++++++++++++++++++++-- src/cc65/coptmisc.h | 5 +++- test/val/bug2205.c | 9 +++++-- 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index eccceccb3..3b88f1c16 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -114,6 +114,7 @@ static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 }; static OptFunc DOptAXLoad = { OptAXLoad, "OptAXLoad", 50, 0, 0, 0, 0, 0 }; +static OptFunc DOptAXLoad2 = { OptAXLoad2, "OptAXLoad2", 66, 0, 0, 0, 0, 0 }; static OptFunc DOptAXOps = { OptAXOps, "OptAXOps", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 }; @@ -876,6 +877,7 @@ static unsigned RunOptGroup7 (CodeSeg* S) */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptAXLoad, 5); + Changes += RunOptFunc (S, &DOptAXLoad2, 5); Changes += RunOptFunc (S, &DOptUnusedStores, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); diff --git a/src/cc65/coptmisc.c b/src/cc65/coptmisc.c index 0ba447562..3e1b40b8d 100644 --- a/src/cc65/coptmisc.c +++ b/src/cc65/coptmisc.c @@ -499,7 +499,7 @@ unsigned OptAXOps (CodeSeg* S) unsigned OptAXLoad (CodeSeg* S) -/* Merge jsr incax/jsr ldaxi into ldy/jsr ldaxidx */ +/* Merge jsr incax[1-8]/jsr ldaxi into ldy/jsr ldaxidx */ { unsigned Changes = 0; unsigned I; @@ -514,9 +514,10 @@ unsigned OptAXLoad (CodeSeg* S) /* Get the next entry */ const CodeEntry* E = CS_GetEntry (S, I); - /* Check for incax followed by jsr/jmp ldaxi */ + /* Check for incax[1-8] followed by jsr/jmp ldaxi */ if (E->OPC == OP65_JSR && strncmp (E->Arg, "incax", 5) == 0 && + strcmp (E->Arg, "incaxy") != 0 && (N = CS_GetNextEntry (S, I)) != 0 && (N->OPC == OP65_JSR || N->OPC == OP65_JMP) && strcmp (N->Arg, "ldaxi") == 0 && @@ -555,6 +556,65 @@ unsigned OptAXLoad (CodeSeg* S) +unsigned OptAXLoad2 (CodeSeg* S) +/* Merge ldy/jsr incaxy/jsr ldaxi into ldy/jsr ldaxidx */ +{ + unsigned Changes = 0; + unsigned I; + + /* Walk over the entries */ + I = 0; + while (I < CS_GetEntryCount (S)) { + + signed Val; + CodeEntry* E[3]; + CodeEntry *X; + char *End; + + /* Get the next entry */ + E[0] = CS_GetEntry (S, I); + + /* Check for ldy followed by incaxy followed by jsr/jmp ldaxi */ + if (E[0]->OPC == OP65_LDY && + E[0]->AM == AM65_IMM && + CS_GetEntries (S, E+1, I+1, 2) && + E[1]->OPC == OP65_JSR && + strcmp (E[1]->Arg, "incaxy") == 0 && + (E[2]->OPC == OP65_JSR || E[2]->OPC == OP65_JMP) && + strcmp (E[2]->Arg, "ldaxi") == 0 && + !CS_RangeHasLabel (S, I, 3)) { + + /* Replace with ldy (y+1) / jsr ldaxidx */ + Val = strtoul(E[0]->Arg + 1, &End, 16); + Val++; + + X = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg(Val), 0, E[0]->LI); + CS_InsertEntry (S, X, I+3); + X = NewCodeEntry (E[2]->OPC, AM65_ABS, "ldaxidx", 0, E[0]->LI); + CS_InsertEntry (S, X, I+4); + + CS_DelEntries (S, I, 3); + + /* Regenerate register info */ + CS_GenRegInfo (S); + + /* Remember we had changes */ + ++Changes; + + } else { + + /* Next entry */ + ++I; + } + + } + + /* Return the number of changes made */ + return Changes; +} + + + unsigned OptGotoSPAdj (CodeSeg* S) /* Optimize SP adjustment for forward 'goto' */ { diff --git a/src/cc65/coptmisc.h b/src/cc65/coptmisc.h index cc6d1c519..df76e84f4 100644 --- a/src/cc65/coptmisc.h +++ b/src/cc65/coptmisc.h @@ -102,7 +102,10 @@ unsigned OptAXOps (CodeSeg* S); */ unsigned OptAXLoad (CodeSeg* S); -/* Merge adjacent calls to incax/ldaxi into ldy/ldaxidx */ +/* Merge jsr incax[1-8]/jsr ldaxi into ldy/jsr ldaxidx */ + +unsigned OptAXLoad2 (CodeSeg* S); +/* Merge ldy/jsr incaxy/jsr ldaxi into ldy/jsr ldaxidx */ unsigned OptGotoSPAdj (CodeSeg* S); /* Optimize SP adjustment for forward 'goto' */ diff --git a/test/val/bug2205.c b/test/val/bug2205.c index 1b5458249..0ca78e9b1 100644 --- a/test/val/bug2205.c +++ b/test/val/bug2205.c @@ -3,18 +3,23 @@ struct Object { int a; - int data[10]; + int data[20]; }; struct Object object_data = { 0x0102, {0x0304, 0x0506, 0x0708, 0x090A, 0x0B0C, 0x0D0E, 0x0F10, 0x1112, - 0x1314, 0x1516}}; + 0x1314, 0x1516, 0x1718, + 0x1920, 0x2122, 0x2324, + 0x2526, 0x2728, 0x2930, + 0x3132, 0x3334, 0x3536}}; TEST { struct Object *o = &object_data; ASSERT_IsTrue(o->a == 0x0102, "Wrong value for a"); ASSERT_IsTrue(o->data[2] == 0x0708, "Wrong value for data[2]"); + ASSERT_IsTrue(o->data[8] == 0x1314, "Wrong value for data[8]"); + ASSERT_IsTrue(o->data[19] == 0x3536, "Wrong value for data[19]"); } ENDTEST