]> git.sur5r.net Git - cc65/commitdiff
Track usage of the sreg and several other zero page registers and remove
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 24 Sep 2001 22:36:35 +0000 (22:36 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 24 Sep 2001 22:36:35 +0000 (22:36 +0000)
unused stores into these registers.
Because of this, the old code using regsave does no longer work. Started
to rewrite it.

git-svn-id: svn://svn.cc65.org/cc65/trunk@966 b7a2c559-68d2-44c3-8de9-860c34a00d81

12 files changed:
src/cc65/codeent.c
src/cc65/codegen.c
src/cc65/codeinfo.c
src/cc65/codeinfo.h
src/cc65/codeopt.c
src/cc65/codeseg.c
src/cc65/coptind.c
src/cc65/coptind.h
src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/declare.c
src/cc65/expr.c

index 6b487adba1541862fe4900773c013428b65c4eef..e37d079f50a16df7edef3b5dc7400062069a075f 100644 (file)
@@ -412,6 +412,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
        case OP65_ASL:
            if (E->AM == AM65_ACC && In->RegA >= 0) {
                Out->RegA = (In->RegA << 1) & 0xFF;
+           } else if (E->AM == AM65_ZP) {
+               if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) {
+                   Out->SRegLo = (In->SRegLo << 1) & 0xFF;
+               } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
+                   Out->SRegHi = (In->SRegHi << 1) & 0xFF;
+               }
            }
            break;
 
@@ -471,25 +477,31 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
 
        case OP65_DEA:
            if (In->RegA >= 0) {
-               Out->RegA = In->RegA - 1;
+               Out->RegA = (In->RegA - 1) & 0xFF;
            }
            break;
 
        case OP65_DEC:
            if (E->AM == AM65_ACC && In->RegA >= 0) {
-               Out->RegA = In->RegA - 1;
+               Out->RegA = (In->RegA - 1) & 0xFF;
+           } else if (E->AM == AM65_ZP) {
+               if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) {
+                   Out->SRegLo = (In->SRegLo - 1) & 0xFF;
+               } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
+                   Out->SRegHi = (In->SRegHi - 1) & 0xFF;
+               }
            }
            break;
 
        case OP65_DEX:
                    if (In->RegX >= 0) {
-               Out->RegX = In->RegX - 1;
+               Out->RegX = (In->RegX - 1) & 0xFF;
            }
            break;
 
        case OP65_DEY:
                    if (In->RegY >= 0) {
-               Out->RegY = In->RegY - 1;
+               Out->RegY = (In->RegY - 1) & 0xFF;
            }
            break;
 
@@ -505,25 +517,31 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
 
        case OP65_INA:
            if (In->RegA >= 0) {
-               Out->RegA = In->RegA + 1;
+               Out->RegA = (In->RegA + 1) & 0xFF;
            }
            break;
 
        case OP65_INC:
            if (E->AM == AM65_ACC && In->RegA >= 0) {
-               Out->RegA = In->RegA + 1;
+               Out->RegA = (In->RegA + 1) & 0xFF;
+           } else if (E->AM == AM65_ZP) {
+               if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) {
+                   Out->SRegLo = (In->SRegLo + 1) & 0xFF;
+               } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
+                   Out->SRegHi = (In->SRegHi + 1) & 0xFF;
+               }
            }
            break;
 
        case OP65_INX:
            if (In->RegX >= 0) {
-               Out->RegX = In->RegX + 1;
+               Out->RegX = (In->RegX + 1) & 0xFF;
            }
            break;
 
        case OP65_INY:
            if (In->RegY >= 0) {
-               Out->RegY = In->RegY + 1;
+               Out->RegY = (In->RegY + 1) & 0xFF;
            }
            break;
 
@@ -560,6 +578,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            if (Chg & REG_Y) {
                Out->RegY = -1;
            }
+            if (Chg & REG_SREG_LO) {
+               Out->SRegLo = -1;
+           }
+           if (Chg & REG_SREG_HI) {
+               Out->SRegHi = -1;
+           }
            break;
 
        case OP65_JVC:
@@ -570,25 +594,49 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
 
        case OP65_LDA:
            if (CE_KnownImm (E)) {
-               Out->RegA = (unsigned char) E->Num;
+               Out->RegA = (unsigned char) E->Num;
+           } else if (E->AM == AM65_ZP) {
+               if (E->Use & REG_SREG_LO) {
+                   Out->RegA = In->SRegLo;
+               } else if (E->Use & REG_SREG_HI) {
+                   Out->RegA = In->SRegHi;
+               } else {
+                   Out->RegA = -1;
+               }
            } else {
-               /* A is now unknown */
-               Out->RegA = -1;
+               /* A is now unknown */
+               Out->RegA = -1;
            }
            break;
 
        case OP65_LDX:
            if (CE_KnownImm (E)) {
-               Out->RegX = (unsigned char) E->Num;
+               Out->RegX = (unsigned char) E->Num;
+           } else if (E->AM == AM65_ZP) {
+               if (E->Use & REG_SREG_LO) {
+                   Out->RegX = In->SRegLo;
+               } else if (E->Use & REG_SREG_HI) {
+                   Out->RegX = In->SRegHi;
+               } else {
+                   Out->RegX = -1;
+               }
            } else {
-               /* X is now unknown */
-               Out->RegX = -1;
+               /* X is now unknown */
+               Out->RegX = -1;
            }
            break;
 
        case OP65_LDY:
            if (CE_KnownImm (E)) {
-               Out->RegY = (unsigned char) E->Num;
+               Out->RegY = (unsigned char) E->Num;
+           } else if (E->AM == AM65_ZP) {
+               if (E->Use & REG_SREG_LO) {
+                   Out->RegY = In->SRegLo;
+               } else if (E->Use & REG_SREG_HI) {
+                   Out->RegY = In->SRegHi;
+               } else {
+                   Out->RegY = -1;
+               }
            } else {
                /* Y is now unknown */
                Out->RegY = -1;
@@ -598,6 +646,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
        case OP65_LSR:
            if (E->AM == AM65_ACC && In->RegA >= 0) {
                Out->RegA = (In->RegA >> 1) & 0xFF;
+           } else if (E->AM == AM65_ZP) {
+               if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) {
+                   Out->SRegLo = (In->SRegLo >> 1) & 0xFF;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = (In->SRegHi >> 1) & 0xFF;
+               }
            }
            break;
 
@@ -634,56 +688,93 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
        case OP65_PLP:
            break;
 
-       case OP65_PLX:
-           Out->RegX = -1;
-           break;
+       case OP65_PLX:
+           Out->RegX = -1;
+           break;
 
-       case OP65_PLY:
-           Out->RegY = -1;
-           break;
+       case OP65_PLY:
+           Out->RegY = -1;
+           break;
 
-       case OP65_ROL:
-           Out->RegA = -1;
-           break;
+       case OP65_ROL:
+           if (E->AM == AM65_ACC) {
+               Out->RegA = -1;
+           } else if (E->AM == AM65_ZP) {
+               if (E->Chg & REG_SREG_LO) {
+                   Out->SRegLo = -1;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = -1;
+               }
+           }
+           break;
 
-       case OP65_ROR:
-           Out->RegA = -1;
-           break;
+       case OP65_ROR:
+           if (E->AM == AM65_ACC) {
+               Out->RegA = -1;
+           } else if (E->AM == AM65_ZP) {
+               if (E->Chg & REG_SREG_LO) {
+                   Out->SRegLo = -1;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = -1;
+               }
+           }
+           break;
 
-       case OP65_RTI:
-           break;
+       case OP65_RTI:
+           break;
 
-       case OP65_RTS:
-           break;
+       case OP65_RTS:
+           break;
 
-       case OP65_SBC:
-           /* We don't know the value of the carry bit */
-           Out->RegA = -1;
-           break;
+       case OP65_SBC:
+           /* We don't know the value of the carry bit */
+           Out->RegA = -1;
+           break;
 
-       case OP65_SEC:
-           break;
+       case OP65_SEC:
+           break;
 
-       case OP65_SED:
-           break;
+       case OP65_SED:
+           break;
 
-       case OP65_SEI:
-           break;
+       case OP65_SEI:
+           break;
 
-       case OP65_STA:
+       case OP65_STA:
+           if (E->AM == AM65_ZP) {
+               if (E->Chg & REG_SREG_LO) {
+                   Out->SRegLo = In->RegA;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = In->RegA;
+               }
+           }
            break;
 
        case OP65_STX:
+           if (E->AM == AM65_ZP) {
+               if (E->Chg & REG_SREG_LO) {
+                   Out->SRegLo = In->RegX;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = In->RegX;
+               }
+           }
            break;
 
        case OP65_STY:
+           if (E->AM == AM65_ZP) {
+               if (E->Chg & REG_SREG_LO) {
+                   Out->SRegLo = In->RegY;
+               } else if (E->Chg & REG_SREG_HI) {
+                   Out->SRegHi = In->RegY;
+               }
+           }
            break;
 
        case OP65_TAX:
            Out->RegX = In->RegA;
            break;
 
-       case OP65_TAY:
+       case OP65_TAY:       
            Out->RegY = In->RegA;
            break;
 
@@ -725,21 +816,22 @@ static char* RegInfoDesc (unsigned U, char* Buf)
 {
     Buf[0] = '\0';
 
-    strcat (Buf, U & REG_SREG? "E" : "_");
-    strcat (Buf, U & REG_A?    "A" : "_");
-    strcat (Buf, U & REG_X?    "X" : "_");
-    strcat (Buf, U & REG_Y?    "Y" : "_");
-    strcat (Buf, U & REG_SP?   "S" : "_");
-    strcat (Buf, U & REG_TMP1? "T1" : "__");
-    strcat (Buf, U & REG_TMP2? "T2" : "__");
-    strcat (Buf, U & REG_TMP3? "T3" : "__");
-    strcat (Buf, U & REG_TMP4? "T4" : "__");
-    strcat (Buf, U & REG_PTR1? "1" : "_");
-    strcat (Buf, U & REG_PTR2? "2" : "_");
-    strcat (Buf, U & REG_PTR3? "3" : "_");
-    strcat (Buf, U & REG_PTR4? "4" : "_");
-    strcat (Buf, U & REG_SAVE? "V"  : "_");
-    strcat (Buf, U & REG_BANK? "B" : "_");
+    strcat (Buf, U & REG_SREG_HI? "H" : "_");
+    strcat (Buf, U & REG_SREG_LO? "L" : "_");
+    strcat (Buf, U & REG_A?       "A" : "_");
+    strcat (Buf, U & REG_X?       "X" : "_");
+    strcat (Buf, U & REG_Y?       "Y" : "_");
+    strcat (Buf, U & REG_SP?      "S" : "_");
+    strcat (Buf, U & REG_TMP1?    "T1" : "__");
+    strcat (Buf, U & REG_TMP2?    "T2" : "__");
+    strcat (Buf, U & REG_TMP3?    "T3" : "__");
+    strcat (Buf, U & REG_TMP4?    "T4" : "__");
+    strcat (Buf, U & REG_PTR1?    "1" : "_");
+    strcat (Buf, U & REG_PTR2?    "2" : "_");
+    strcat (Buf, U & REG_PTR3?    "3" : "_");
+    strcat (Buf, U & REG_PTR4?    "4" : "_");
+    strcat (Buf, U & REG_SAVE?    "V"  : "_");
+    strcat (Buf, U & REG_BANK?    "B" : "_");
 
     return Buf;
 }
@@ -834,7 +926,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
        char Use [128];
        char Chg [128];
                fprintf (F,
-                        "%*s; USE: %-19s CHG: %-19s SIZE: %u\n",
+                        "%*s; USE: %-20s CHG: %-20s SIZE: %u\n",
                         30-Chars, "",
                 RegInfoDesc (E->Use, Use),
                 RegInfoDesc (E->Chg, Chg),
index 1d537111b17c93f951d6e070c209cbd31b17a717..74a1710d44733371e5675df20aca77d9f6e87b55 100644 (file)
@@ -1011,12 +1011,8 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
                }
            } else {
                if ((Flags & CF_NOKEEP) == 0 || CodeSizeFactor < 160) {
-                   if (Offs) {
-                       ldyconst (Offs);
-                       AddCodeLine ("jsr staxysp");
-                   } else {
-                       AddCodeLine ("jsr stax0sp");
-                   }
+                   ldyconst (Offs);
+                   AddCodeLine ("jsr staxysp");
                } else {
                    if (CPU == CPU_65C02 && Offs == 0) {
                        AddCodeLine ("sta (sp)");
index 3eeb48506bc5b6ae03a9f0d781e0ac9b8237b012..abf8a3bf5bac00aa2c69cd7946e9bc533654fc47 100644 (file)
@@ -172,7 +172,8 @@ static const ZPInfo ZPInfoTable[] = {
     {   7,      "regbank",      REG_BANK        },
     {   7,      "regsave",      REG_SAVE        },
     {   2,      "sp",           REG_SP          },
-    {   4,      "sreg",         REG_SREG        },
+    {   0,      "sreg",         REG_SREG_LO     },
+    {  0,      "sreg+1",       REG_SREG_HI     },
     {   4,      "tmp1",         REG_TMP1        },
     {   4,      "tmp2",         REG_TMP2        },
     {   4,      "tmp3",         REG_TMP3        },
@@ -245,7 +246,7 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
 
     } else {
 
-       /* Search for the function in the list of builtin functions */
+       /* Search for the function in the list of builtin functions */
        const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount,
                                        sizeof(FuncInfo), CompareFuncInfo);
 
@@ -277,12 +278,18 @@ static int CompareZPInfo (const void* Name, const void* Info)
     /* Do the compare. Be careful because of the length (Info may contain
      * more than just the zeropage name).
      */
-    int Res = strncmp (N, E->Name, E->Len);
-    if (Res == 0 && (N[E->Len] != '\0' && N[E->Len] != '+')) {
-       /* Name is actually longer than Info->Name */
-       Res = -1;
+    if (E->Len == 0) {
+       /* Do a full compare */
+       return strcmp (N, E->Name);
+    } else {
+       /* Only compare the first part */
+       int Res = strncmp (N, E->Name, E->Len);
+       if (Res == 0 && (N[E->Len] != '\0' && N[E->Len] != '+')) {
+           /* Name is actually longer than Info->Name */
+           Res = -1;
+       }
+       return Res;
     }
-    return Res;
 }
 
 
@@ -312,22 +319,13 @@ int IsZPName (const char* Name, unsigned short* RegInfo)
 
 
 
-static unsigned GetRegInfo1 (CodeSeg* S,
-                                    CodeEntry* E,
-                                    int Index,
-                                    Collection* Visited,
-                                    unsigned Used,
-                                    unsigned Unused);
-/* Recursively called subfunction for GetRegInfo. */
-
-
-
 static unsigned GetRegInfo2 (CodeSeg* S,
                             CodeEntry* E,
                             int Index,
                             Collection* Visited,
                             unsigned Used,
-                            unsigned Unused)
+                            unsigned Unused,
+                            unsigned Wanted)
 /* Recursively called subfunction for GetRegInfo. */
 {
     /* Follow the instruction flow recording register usage. */
@@ -373,7 +371,7 @@ static unsigned GetRegInfo2 (CodeSeg* S,
        }
 
                /* If we know about all registers now, bail out */
-               if ((Used | Unused) == REG_AXY) {
+               if (((Used | Unused) & Wanted) == Wanted) {
            break;
        }
 
@@ -392,7 +390,7 @@ static unsigned GetRegInfo2 (CodeSeg* S,
 
                /* Unconditional jump */
                E     = E->JumpTo->Owner;
-               Index = -1;             /* Invalidate */
+               Index = -1;             /* Invalidate */
 
            } else {
                /* Jump outside means we're done */
@@ -411,7 +409,7 @@ static unsigned GetRegInfo2 (CodeSeg* S,
                unsigned U1;
                unsigned U2;
 
-               U1 = GetRegInfo1 (S, E->JumpTo->Owner, -1, Visited, Used, Unused);
+               U1 = GetRegInfo2 (S, E->JumpTo->Owner, -1, Visited, Used, Unused, Wanted);
                if (U1 == REG_AXY) {
                    /* All registers used, no need for second call */
                    return REG_AXY;
@@ -422,7 +420,7 @@ static unsigned GetRegInfo2 (CodeSeg* S,
                        if ((E = CS_GetEntry (S, ++Index)) == 0) {
                    Internal ("GetRegInfo2: No next entry!");
                }
-               U2 = GetRegInfo1 (S, E, Index, Visited, Used, Unused);
+                       U2 = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted);
                return U1 | U2;         /* Used in any of the branches */
 
            } else {
@@ -457,14 +455,15 @@ static unsigned GetRegInfo1 (CodeSeg* S,
                             int Index,
                             Collection* Visited,
                             unsigned Used,
-                            unsigned Unused)
+                            unsigned Unused,
+                            unsigned Wanted)
 /* Recursively called subfunction for GetRegInfo. */
 {
     /* Remember the current count of the line collection */
     unsigned Count = CollCount (Visited);
 
     /* Call the worker routine */
-    unsigned R = GetRegInfo2 (S, E, Index, Visited, Used, Unused);
+    unsigned R = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted);
 
     /* Restore the old count, unmarking all new entries */
     unsigned NewCount = CollCount (Visited);
@@ -480,7 +479,7 @@ static unsigned GetRegInfo1 (CodeSeg* S,
 
 
 
-unsigned GetRegInfo (struct CodeSeg* S, unsigned Index)
+unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted)
 /* Determine register usage information for the instructions starting at the
  * given index.
  */
@@ -500,7 +499,7 @@ unsigned GetRegInfo (struct CodeSeg* S, unsigned Index)
     InitCollection (&Visited);
 
     /* Call the recursive subfunction */
-    R = GetRegInfo1 (S, E, Index, &Visited, REG_NONE, REG_NONE);
+    R = GetRegInfo1 (S, E, Index, &Visited, REG_NONE, REG_NONE, Wanted);
 
     /* Delete the line collection */
     DoneCollection (&Visited);
@@ -514,7 +513,7 @@ unsigned GetRegInfo (struct CodeSeg* S, unsigned Index)
 int RegAUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in A is used. */
 {
-    return (GetRegInfo (S, Index) & REG_A) != 0;
+    return (GetRegInfo (S, Index, REG_A) & REG_A) != 0;
 }
 
 
@@ -522,7 +521,7 @@ int RegAUsed (struct CodeSeg* S, unsigned Index)
 int RegXUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in X is used. */
 {
-    return (GetRegInfo (S, Index) & REG_X) != 0;
+    return (GetRegInfo (S, Index, REG_X) & REG_X) != 0;
 }
 
 
@@ -530,7 +529,7 @@ int RegXUsed (struct CodeSeg* S, unsigned Index)
 int RegYUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in Y is used. */
 {
-    return (GetRegInfo (S, Index) & REG_Y) != 0;
+    return (GetRegInfo (S, Index, REG_Y) & REG_Y) != 0;
 }
 
 
index ff4c866e45b14f4dd1a31dc0e3efa5add515bce8..b4df0dd0321ba7c1a66ea4119918d70acf6c46ab 100644 (file)
@@ -59,20 +59,22 @@ struct CodeSeg;
 #define REG_A                  0x0001U
 #define REG_X                  0x0002U
 #define REG_Y                  0x0004U
-#define REG_TMP1               0x0010U
-#define REG_TMP2        0x0020U
-#define REG_TMP3        0x0040U
-#define REG_TMP4        0x0080U
-#define REG_PTR1               0x0100U
-#define REG_PTR2       0x0200U
-#define REG_PTR3       0x0400U
-#define REG_PTR4       0x0800U
-#define REG_SREG       0x1000U
+#define REG_TMP1               0x0008U
+#define REG_TMP2        0x0010U
+#define REG_TMP3        0x0020U
+#define REG_TMP4        0x0040U
+#define REG_PTR1               0x0080U
+#define REG_PTR2       0x0100U
+#define REG_PTR3       0x0200U
+#define REG_PTR4       0x0400U
+#define REG_SREG_LO            0x0800U
+#define REG_SREG_HI     0x1000U
 #define REG_SP          0x2000U
 #define REG_SAVE        0x4000U
 #define REG_BANK        0x8000U
 
 /* Combined register defines */
+#define REG_SREG        (REG_SREG_LO | REG_SREG_HI)
 #define        REG_AX          (REG_A | REG_X)
 #define REG_AY          (REG_A | REG_Y)
 #define REG_XY         (REG_X | REG_Y)
@@ -102,7 +104,7 @@ int IsZPName (const char* Name, unsigned short* RegInfo);
  * zero page location found.
  */
 
-unsigned GetRegInfo (struct CodeSeg* S, unsigned Index);
+unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted);
 /* Determine register usage information for the instructions starting at the
  * given index.
  */
index 7b4928e51c57523484b28609f6723f910848d4fa..7be0efb9c0f6725cf1a6e7f7514f9d0cf249110a 100644 (file)
@@ -697,7 +697,7 @@ static unsigned OptAdd2 (CodeSeg* S)
            L[6]->OPC == OP65_JSR               &&
                    strcmp (L[6]->Arg, "addeqysp") == 0 &&
            !CE_HasLabel (L[6])                 &&
-           (GetRegInfo (S, I+7) & REG_AX) == 0) {
+           (GetRegInfo (S, I+7, REG_AX) & REG_AX) == 0) {
 
            char Buf [20];
            CodeEntry* X;
@@ -2580,6 +2580,7 @@ static OptFunc OptFuncs [] = {
     OptEntry (OptTest1, optMain),
     /* Remove unused loads */
     OptEntry (OptUnusedLoads, optMain),
+    OptEntry (OptUnusedStores, optMain),
     OptEntry (OptDuplicateLoads, optMain),
     OptEntry (OptStoreLoad, optMain),
     OptEntry (OptTransfers, optMain),
index cc4ee7364045097cf91e7b2a67b2d0f49db22fd3..f29c6767e3492145ec3885a8d26f46e9c8cccf21 100644 (file)
@@ -414,8 +414,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
     /* If we have a function given, get the return type of the function.
      * Assume ANY return type besides void will use the A and X registers.
      */
-    RetType = GetFuncReturn (Func->Type);
-    if (S->Func && !IsTypeVoid (RetType)) {
+    if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) {
        if (SizeOf (RetType) == SizeOf (type_long)) {
            S->ExitRegs = REG_EAX;
        } else {
@@ -1059,7 +1058,7 @@ void CS_GenRegInfo (CodeSeg* S)
     RC_Invalidate (&Regs);
     CurrentRegs = &Regs;
 
-    /* First pass. Walk over all insns an note just the changes from one
+    /* First pass. Walk over all insns and note just the changes from one
      * insn to the next one.
      */
     WasJump = 0;
@@ -1115,6 +1114,12 @@ void CS_GenRegInfo (CodeSeg* S)
                if (J->RI->Out2.RegY != Regs.RegY) {
                    Regs.RegY = -1;
                }
+               if (J->RI->Out2.SRegLo != Regs.SRegLo) {
+                   Regs.SRegLo = -1;
+               }
+               if (J->RI->Out2.SRegHi != Regs.SRegHi) {
+                   Regs.SRegHi = -1;
+               }
                ++Entry;
            }
 
index ddd78a325422aff835a071c9ea19cf828be0a7c0..d64262b8f8ee21b09cc7edda6196c7749308fcf1 100644 (file)
@@ -579,7 +579,7 @@ unsigned OptCondBranches (CodeSeg* S)
 
 
 /*****************************************************************************/
-/*                           Remove unused loads                            */
+/*                     Remove unused loads and stores                       */
 /*****************************************************************************/
 
 
@@ -623,7 +623,7 @@ unsigned OptUnusedLoads (CodeSeg* S)
            }
 
            /* Get register usage and check if the register value is used later */
-           if ((GetRegInfo (S, I+1) & R) == 0) {
+           if ((GetRegInfo (S, I+1, R) & R) == 0) {
 
                /* Register value is not used, remove the load */
                CS_DelEntry (S, I);
@@ -646,6 +646,51 @@ NextEntry:
 
 
 
+unsigned OptUnusedStores (CodeSeg* S)
+/* Remove stores into zero page registers that aren't used later */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+       /* Check if it's a register load or transfer insn */
+               if ((E->Info & OF_STORE) != 0    &&
+           E->AM == AM65_ZP             &&
+           (E->Chg & REG_ZP) != 0) {
+
+           /* Check for the zero page location. We know that there cannot be
+            * more than one zero page location involved in the store.
+            */
+           unsigned R = E->Chg & REG_ZP;
+
+           /* Get register usage and check if the register value is used later */
+           if ((GetRegInfo (S, I+1, R) & R) == 0) {
+
+               /* Register value is not used, remove the load */
+               CS_DelEntry (S, I);
+
+               /* Remember, we had changes */
+               ++Changes;
+
+           }
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 unsigned OptDuplicateLoads (CodeSeg* S)
 /* Remove loads of registers where the value loaded is already in the register. */
 {
@@ -667,13 +712,16 @@ unsigned OptDuplicateLoads (CodeSeg* S)
        /* Assume we won't delete the entry */
        int Delete = 0;
 
+               /* Get a pointer to the input registers of the insn */
+       const RegContents* In  = &E->RI->In;
+
        /* Handle the different instructions */
        switch (E->OPC) {
 
            case OP65_LDA:
-               if (E->RI->In.RegA >= 0               && /* Value of A is known */
+                       if (In->RegA >= 0                     && /* Value of A is known */
                            CE_KnownImm (E)                   && /* Value to be loaded is known */
-                           E->RI->In.RegA == (long) E->Num   && /* Both are equal */
+                           In->RegA == (long) 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;
@@ -681,9 +729,9 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
            case OP65_LDX:
-                       if (E->RI->In.RegX >= 0               && /* Value of X is known */
+                       if (In->RegX >= 0                     && /* Value of X is known */
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
-                   E->RI->In.RegX == (long) E->Num   && /* Both are equal */
+                   In->RegX == (long) 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;
@@ -691,32 +739,70 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
            case OP65_LDY:
-                       if (E->RI->In.RegY >= 0               && /* Value of Y is known */
+                       if (In->RegY >= 0                     && /* Value of Y is known */
                    CE_KnownImm (E)                   && /* Value to be loaded is known */
-                   E->RI->In.RegY == (long) E->Num   && /* Both are equal */
+                   In->RegY == (long) 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_STA:
+               /* If we store into a known zero page location, and this
+                * location does already contain the value to be stored,
+                * remove the store.
+                */
+               if (In->RegA >= 0                     && /* Value of A is known */
+                   E->AM == AM65_ZP                  && /* Store into zp */
+                   (((E->Chg & REG_SREG_LO) != 0 &&     /* Store into sreg */
+                     In->RegA == In->SRegLo)       ||   /* Value identical */
+                            ((E->Chg & REG_SREG_HI) != 0 &&     /* Store into sreg+1 */
+                             In->RegA == In->SRegHi))) {        /* Value identical */
+                   Delete = 1;
+               }
+               break;
+
            case OP65_STX:
-               /* If the value in the X register is known and the same as
+               /* If we store into a known zero page location, and this
+                * location does already contain the value to be stored,
+                * remove the store.
+                */
+               if (In->RegX >= 0                     && /* Value of A is known */
+                   E->AM == AM65_ZP                  && /* Store into zp */
+                   (((E->Chg & REG_SREG_LO) != 0 &&     /* Store into sreg */
+                     In->RegX == In->SRegLo)       ||   /* Value identical */
+                            ((E->Chg & REG_SREG_HI) != 0 &&     /* Store into sreg+1 */
+                             In->RegX == In->SRegHi))) {        /* Value identical */
+                   Delete = 1;
+
+               /* 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
                 * optimizer will then remove the load instruction for X
                 * later. STX does support the zeropage,y addressing mode,
                 * so be sure to check for that.
                 */
-                       if (E->RI->In.RegX >= 0               &&
-                   E->RI->In.RegX == E->RI->In.RegA  &&
-                   E->AM != AM65_ABSY                &&
-                   E->AM != AM65_ZPY) {
+                       } else if (In->RegX >= 0              &&
+                          In->RegX == In->RegA       &&
+                          E->AM != AM65_ABSY         &&
+                          E->AM != AM65_ZPY) {
                    /* Use the A register instead */
                            CE_ReplaceOPC (E, OP65_STA);
                }
                break;
 
            case OP65_STY:
+               /* If we store into a known zero page location, and this
+                * location does already contain the value to be stored,
+                * remove the store.
+                */
+               if (In->RegX >= 0                     && /* Value of A is known */
+                   E->AM == AM65_ZP                  && /* Store into zp */
+                   (((E->Chg & REG_SREG_LO) != 0 &&     /* Store into sreg */
+                     In->RegX == In->SRegLo)       ||   /* Value identical */
+                            ((E->Chg & REG_SREG_HI) != 0 &&     /* Store into sreg+1 */
+                             In->RegX == In->SRegHi))) {        /* Value identical */
+                   Delete = 1;
                /* If the value in the Y register is known and the same as
                 * that in the A register, replace the store by a STA. The
                 * optimizer will then remove the load instruction for Y
@@ -724,11 +810,11 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                 * replacement by X, but check for invalid addressing modes
                 * in this case.
                 */
-                       if (E->RI->In.RegY >= 0) {
-                   if (E->RI->In.RegY == E->RI->In.RegA) {
+                       } else if (In->RegY >= 0) {
+                   if (In->RegY == In->RegA) {
                        CE_ReplaceOPC (E, OP65_STA);
-                   } else if (E->RI->In.RegY == E->RI->In.RegX &&
-                              E->AM != AM65_ABSX               &&
+                   } else if (In->RegY == In->RegX   &&
+                              E->AM != AM65_ABSX     &&
                               E->AM != AM65_ZPX) {
                        CE_ReplaceOPC (E, OP65_STX);
                    }
@@ -736,9 +822,9 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
            case OP65_TAX:
-                if (E->RI->In.RegA >= 0                 &&
-                   E->RI->In.RegA == E->RI->In.RegX    &&
-                   (N = CS_GetNextEntry (S, I)) != 0   &&
+                if (In->RegA >= 0                     &&
+                   In->RegA == In->RegX              &&
+                   (N = CS_GetNextEntry (S, I)) != 0 &&
                    (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
                    Delete = 1;
@@ -746,8 +832,8 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
            case OP65_TAY:
-                if (E->RI->In.RegA >= 0                 &&
-                   E->RI->In.RegA == E->RI->In.RegY    &&
+                if (In->RegA >= 0                 &&
+                   In->RegA == In->RegY    &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                    (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
@@ -756,8 +842,8 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
                    case OP65_TXA:
-                if (E->RI->In.RegX >= 0                 &&
-                   E->RI->In.RegX == E->RI->In.RegA    &&
+                if (In->RegX >= 0                 &&
+                   In->RegX == In->RegA    &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                    (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
@@ -766,8 +852,8 @@ unsigned OptDuplicateLoads (CodeSeg* S)
                break;
 
            case OP65_TYA:
-                if (E->RI->In.RegY >= 0                 &&
-                   E->RI->In.RegY == E->RI->In.RegA    &&
+                if (In->RegY >= 0                 &&
+                   In->RegY == In->RegA    &&
                    (N = CS_GetNextEntry (S, I)) != 0   &&
                    (N->Info & OF_FBRA) == 0) {
                    /* Value is identical and not followed by a branch */
index 04530f1941fb6118c2b1339a87e938c9bfa4ae09..746637092bb88a193286ea48454bea0a2af4e971 100644 (file)
@@ -89,6 +89,9 @@ unsigned OptCondBranches (CodeSeg* S);
 unsigned OptUnusedLoads (CodeSeg* S);
 /* Remove loads of registers where the value loaded is not used later. */
 
+unsigned OptUnusedStores (CodeSeg* S);
+/* Remove stores into zero page registers that aren't used later */
+
 unsigned OptDuplicateLoads (CodeSeg* S);
 /* Remove loads of registers where the value loaded is already in the register. */
 
index 4da5470b98b8e84c20ad2860e49a6d5b0aa3b01c..47944b37a4849418dc6bf52142c1e05c3e995509 100644 (file)
@@ -682,22 +682,22 @@ int IsQualVolatile (const type* T)
 
 
 int IsFastCallFunc (const type* T)
-/* Return true if this is a function type with __fastcall__ calling conventions */
+/* Return true if this is a function type or pointer to function with
+ * __fastcall__ calling conventions
+ */
 {
-    FuncDesc* F;
-    CHECK (IsTypeFunc (T));
-    F = (FuncDesc*) DecodePtr (T+1);
+    FuncDesc* F        = GetFuncDesc (T);
     return (F->Flags & FD_FASTCALL) != 0;
 }
 
 
 
 int IsVariadicFunc (const type* T)
-/* Return true if this is a function type with variable parameter list */
+/* Return true if this is a function type or pointer to function type with
+ * variable parameter list
+ */
 {
-    FuncDesc* F;
-    CHECK (IsTypeFunc (T));
-    F = (FuncDesc*) DecodePtr (T+1);
+    FuncDesc* F = GetFuncDesc (T);
     return (F->Flags & FD_VARIADIC) != 0;
 }
 
index b561da26f0bd60fc615934d5ffd13bf960551ea4..beabf2bd86067c40d1bbb34f3a9e9830584de56b 100644 (file)
@@ -287,10 +287,14 @@ int IsQualVolatile (const type* T) attribute ((const));
 /* Return true if the given type has a volatile type qualifier */
 
 int IsFastCallFunc (const type* T) attribute ((const));
-/* Return true if this is a function type with __fastcall__ calling conventions */
+/* Return true if this is a function type or pointer to function with
+ * __fastcall__ calling conventions
+ */
 
 int IsVariadicFunc (const type* T) attribute ((const));
-/* Return true if this is a function type with variable parameter list */
+/* Return true if this is a function type or pointer to function type with
+ * variable parameter list
+ */
 
 int IsTypeFuncPtr (const type* T) attribute ((const));
 /* Return true if this is a function pointer */
index feac79212ea5a21a2a910cac971de40c1529711d..9aabf0eabc9346364403e8d5a7a685d1a6989dc3 100644 (file)
@@ -807,12 +807,12 @@ static void Decl (Declaration* D, unsigned Mode)
        /* Parse the function */
        Decl (D, Mode);
        /* Set the fastcall flag */
-       if (!IsTypeFunc (T)) {
+       if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
            Error ("__fastcall__ modifier applied to non function");
        } else if (IsVariadicFunc (T)) {
            Error ("Cannot apply __fastcall__ to functions with variable parameter list");
        } else {
-           FuncDesc* F = (FuncDesc*) DecodePtr (T+1);
+           FuncDesc* F = GetFuncDesc (T);
                    F->Flags |= FD_FASTCALL;
        }
        return;
index a269359021c7fad151a4e7da5e19776af3326036..ed0b1cf1e345fcfbb659ed6bb5d6ad704e21bb56 100644 (file)
@@ -707,53 +707,122 @@ static unsigned FunctionParamList (FuncDesc* Func)
 
 
 
-static void FunctionCall (ExprDesc* lval)
-/* Perform a function call.  Called from hie11, this routine will
- * either call the named function, or the function pointer in a/x.
- */
+static void FunctionCall (int k, ExprDesc* lval)
+/* Perform a function call. */
 {
-    FuncDesc*    Func;         /* Function descriptor */
-    unsigned     ParamSize;    /* Number of parameter bytes */
-    CodeMark     Mark;
-
+    FuncDesc*    Func;           /* Function descriptor */
+    int           IsFuncPtr;      /* Flag */
+    unsigned     ParamSize;      /* Number of parameter bytes */
+    CodeMark     Mark = 0;       /* Initialize to keep gcc silent */
+    int           PtrOffs = 0;    /* Offset of function pointer on stack */
+    int           IsFastCall = 0; /* True if it's a fast call function */
+    int           PtrOnStack = 0; /* True if a pointer copy is on stack */
 
     /* Get a pointer to the function descriptor from the type string */
     Func = GetFuncDesc (lval->Type);
 
-    /* Initialize vars to keep gcc silent */
-    Mark  = 0;
+    /* Handle function pointers transparently */
+    IsFuncPtr = IsTypeFuncPtr (lval->Type);
+    if (IsFuncPtr) {
 
-    /* Check if this is a function pointer. If so, save it. If not, check for
-     * special known library functions that may be inlined.
-     */
-    if (lval->Flags & E_MEXPR) {
-               /* Function pointer is in primary register, save it */
-               Mark = GetCodePos ();
-               g_save (CF_PTR);
+       /* Check wether it's a fastcall function */
+       IsFastCall = IsFastCallFunc (lval->Type + 1);
+
+       /* Things may be difficult, depending on where the function pointer
+        * resides. If the function pointer is an expression of some sort
+        * (not a local or global variable), we have to evaluate this
+        * expression now and save the result for later. Since calls to
+        * function pointers may be nested, we must save it onto the stack.
+        * For fastcall functions we do also need to place a copy of the
+        * pointer on stack, since we cannot use a/x.
+        */
+       PtrOnStack = IsFastCall || ((lval->Flags & (E_MGLOBAL | E_MLOCAL)) == 0);
+       if (PtrOnStack) {
+
+           /* Not a global or local variable, or a fastcall function. Load
+            * the pointer into the primary and mark it as an expression.
+            */
+           exprhs (CF_NONE, k, lval);
+           lval->Flags |= E_MEXPR;
+
+           /* Remember the code position */
+           Mark = GetCodePos ();
+
+           /* Push the pointer onto the stack and remember the offset */
+           g_push (CF_PTR, 0);
+           PtrOffs = oursp;
+       }
+
+    /* Check for known standard functions and inline them if requested */
     } else if (InlineStdFuncs && IsStdFunc ((const char*) lval->Name)) {
-               /* Inline this function */
+
+       /* Inline this function */
                HandleStdFunc (lval);
                return;
+
     }
 
     /* Parse the parameter list */
     ParamSize = FunctionParamList (Func);
 
-    /* We need the closing bracket here */
+    /* We need the closing paren here */
     ConsumeRParen ();
 
-    /* */
-    if (lval->Flags & E_MEXPR) {
-       /* Function called via pointer: Restore it and call function */
-       if (ParamSize != 0) {
-           g_restore (CF_PTR);
-       } else {
-           /* We had no parameters - remove save code */
-                   RemoveCode (Mark);
+    /* Special handling for function pointers */
+    if (IsFuncPtr) {
+
+       /* If the function is not a fastcall function, load the pointer to
+        * the function into the primary.
+        */
+       if (!IsFastCallFunc (lval->Type)) {
+
+           /* Not a fastcall function - we may use the primary */
+                   if (PtrOnStack) {
+               /* If we have no parameters, the pointer is still in the
+                * primary. Remove the code to push it and correct the
+                * stack pointer.
+                */
+               if (ParamSize == 0) {
+                   RemoveCode (Mark);
+                   pop (CF_PTR);
+                   PtrOnStack = 0;
+               } else {
+                   /* Load from the saved copy */
+                   g_getlocal (CF_PTR, PtrOffs);
+               }
+           } else {
+               /* Load from original location */
+               exprhs (CF_NONE, k, lval);
+           }
+
+           /* Call the function */
+           g_callind (TypeOf (lval->Type), ParamSize);
+
+           /* If we have a pointer on stack, remove it */
+           if (PtrOnStack) {
+               g_space (- (int) sizeofarg (CF_PTR));
+               pop (CF_PTR);
+           }
+
+       } else {
+
+           /* Fastcall function. We cannot use the primary for the function
+            * pointer and must therefore use an offset to the stack location.
+            * Since fastcall functions may never be variadic, we can use the
+            * index register for this purpose.
+            */
+           Error ("Not implemented");
+           pop (CF_PTR);
        }
-       g_callind (TypeOf (lval->Type), ParamSize);
+
+       /* Skip T_PTR */            
+       ++lval->Type;
+
     } else {
+
+       /* Normal function */
                g_call (TypeOf (lval->Type), (const char*) lval->Name, ParamSize);
+
     }
 }
 
@@ -829,7 +898,7 @@ static int primary (ExprDesc* lval)
 
            /* Check for legal symbol types */
                    if ((Sym->Flags & SC_CONST) == SC_CONST) {
-               /* Enum or some other numeric constant */
+               /* Enum or some other numeric constant */
                lval->Flags = E_MCONST;
                lval->ConstVal = Sym->V.ConstVal;
                return 0;
@@ -840,19 +909,19 @@ static int primary (ExprDesc* lval)
                lval->ConstVal = 0;
            } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
                /* Local variable. If this is a parameter for a variadic
-                * function, we have to add some address calculations, and the
-                * address is not const.
-                */
+                * function, we have to add some address calculations, and the
+                * address is not const.
+                */
                        if ((Sym->Flags & SC_PARAM) == SC_PARAM && IsVariadic (CurrentFunc)) {
-                   /* Variadic parameter */
-                   g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc));
-                   lval->Flags = E_MEXPR;
-                   lval->ConstVal = 0;
-               } else {
-                   /* Normal parameter */
-                   lval->Flags = E_MLOCAL | E_TLOFFS;
-                   lval->ConstVal = Sym->V.Offs;
-               }
+                   /* Variadic parameter */
+                   g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc));
+                   lval->Flags = E_MEXPR;
+                   lval->ConstVal = 0;
+               } else {
+                   /* Normal parameter */
+                   lval->Flags = E_MLOCAL | E_TLOFFS;
+                   lval->ConstVal = Sym->V.Offs;
+               }
            } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
                /* Static variable */
                if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) {
@@ -1253,16 +1322,17 @@ static int hie11 (ExprDesc *lval)
            /* Function call. Skip the opening parenthesis */
            NextToken ();
            tptr = lval->Type;
-           if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
-               if (IsTypeFuncPtr (tptr)) {
-                   /* Pointer to function. Handle transparently */
-                   exprhs (CF_NONE, k, lval);  /* Function pointer to A/X */
-                   ++lval->Type;               /* Skip T_PTR */
-                   lval->Flags |= E_MEXPR;
-               }
-               FunctionCall (lval);
+           if (IsTypeFunc (lval->Type) || IsTypeFuncPtr (lval->Type)) {
+
+               /* Call the function */
+               FunctionCall (k, lval);
+
+               /* Result is in the primary register */
                lval->Flags = E_MEXPR;
-               lval->Type += DECODE_SIZE + 1;          /* Set to result */
+
+               /* Set to result */
+               lval->Type = GetFuncReturn (lval->Type);
+
            } else {
                Error ("Illegal function call");
            }