From: uz Date: Mon, 14 Sep 2009 22:02:48 +0000 (+0000) Subject: Improved the code that checks for memory accesses. The old code didn't detect X-Git-Tag: V2.13.0rc1~82 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=52a368adc163f9a87e77a617c44c1b2666138072;p=cc65 Improved the code that checks for memory accesses. The old code didn't detect certain accesses. git-svn-id: svn://svn.cc65.org/cc65/trunk@4174 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 578a72c7f..2dd0aaa54 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -51,27 +51,67 @@ -static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const char* Arg) -/* Checks a range of code entries if there are any memory accesses to Arg. - * Note: This function is not 100% safe, because there is more than one way - * to express a memory location ("foo" and "foo+0" comes to mind) and there - * may be other accesses through pointers. For the code generated by cc65 and - * for the purpose of the caller (OptPushPop) it is assumed to be safe enough - * however. - */ +static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const CodeEntry* N) +/* Checks a range of code entries if there are any memory accesses to N->Arg */ { + /* Get the length of the argument */ + unsigned NLen = strlen (N->Arg); + + /* What to check for? */ + enum { + None = 0x00, + Base = 0x01, /* Check for location without "+1" */ + Word = 0x02, /* Check for location with "+1" added */ + } What = None; + + + /* If the argument of N is a zero page location that ends with "+1", we + * must also check for word accesses to the location without +1. + */ + if (N->AM == AM65_ZP && NLen > 2 && strcmp (N->Arg + NLen - 2, "+1") == 0) { + What |= Base; + } + + /* If the argument is zero page indirect, we must also check for accesses + * to "arg+1" + */ + if (N->AM == AM65_ZP_INDY || N->AM == AM65_ZPX_IND || N->AM == AM65_ZP_IND) { + What |= Word; + } + /* Walk over all code entries */ while (From <= To) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, From); - /* For simplicity, we just check if there is an argument and if this - * argument equals Arg. + /* Check if there is an argument and if this argument equals Arg in + * some variants. */ - if (E->Arg && strcmp (E->Arg, Arg) == 0) { - /* Found an access */ - return 1; + if (E->Arg[0] != '\0') { + + unsigned ELen; + + if (strcmp (E->Arg, N->Arg) == 0) { + /* Found an access */ + return 1; + } + + ELen = strlen (E->Arg); + if ((What & Base) != 0) { + if (ELen == NLen - 2 && strncmp (E->Arg, N->Arg, NLen-2) == 0) { + /* Found an access */ + return 1; + } + } + + if ((What & Word) != 0) { + if (ELen == NLen + 2 && strncmp (E->Arg, N->Arg, NLen) == 0 && + E->Arg[NLen] == '+' && E->Arg[NLen+1] == '1') { + /* Found an access */ + return 1; + } + } } /* Next entry */ @@ -1480,7 +1520,7 @@ unsigned OptTransfers3 (CodeSeg* S) StoreEntry->AM == AM65_ZP) && (StoreEntry->AM != AM65_ZP || (StoreEntry->Chg & UsedRegs) == 0) && - !MemAccess (S, Xfer+1, Store-1, StoreEntry->Arg)) { + !MemAccess (S, Xfer+1, Store-1, StoreEntry)) { /* Generate the replacement store insn */ CodeEntry* X = 0; @@ -1645,7 +1685,7 @@ unsigned OptTransfers4 (CodeSeg* S) (LoadEntry->AM == AM65_ABS || LoadEntry->AM == AM65_ZP || LoadEntry->AM == AM65_IMM) && - !MemAccess (S, Load+1, Xfer-1, LoadEntry->Arg)) { + !MemAccess (S, Load+1, Xfer-1, LoadEntry)) { /* Generate the replacement load insn */ CodeEntry* X = 0; @@ -1794,7 +1834,7 @@ unsigned OptPushPop (CodeSeg* S) */ if (E->OPC == OP65_STA && !RegAUsed (S, I+1) && - !MemAccess (S, Push+1, Pop-1, E->Arg)) { + !MemAccess (S, Push+1, Pop-1, E)) { /* Insert a STA after the PHA */ X = NewCodeEntry (E->OPC, E->AM, E->Arg, E->JumpTo, E->LI);