-static unsigned GetReg (unsigned short Use, const RegContents* RC)
-/* Map the register info in Use plus the validity into in RI into exactly
- * one register.
- */
-{
- if ((Use & REG_A) != 0) {
- return (RC && RC->RegA >= 0)? REG_A : REG_NONE;
- } else if ((Use & REG_X) != 0) {
- return (RC && RC->RegX >= 0)? REG_X : REG_NONE;
- } else if ((Use & REG_Y) != 0) {
- return (RC && RC->RegY >= 0)? REG_Y : REG_NONE;
- } else if ((Use & REG_TMP1) != 0) {
- return (RC && RC->Tmp1 >= 0)? REG_TMP1 : REG_NONE;
- } else if ((Use & REG_SREG_LO) != 0) {
- return (RC && RC->SRegLo >= 0)? REG_SREG_LO : REG_NONE;
- } else if ((Use & REG_SREG_HI) != 0) {
- return (RC && RC->SRegHi >= 0)? REG_SREG_HI : REG_NONE;
- } else {
- return REG_NONE;
- }
-}
-
-
-
/*****************************************************************************/
/* Code */
/*****************************************************************************/
+const char* MakeHexArg (unsigned Num)
+/* Convert Num into a string in the form $XY, suitable for passing it as an
+ * argument to NewCodeEntry, and return a pointer to the string.
+ * BEWARE: The function returns a pointer to a static buffer, so the value is
+ * gone if you call it twice (and apart from that it's not thread and signal
+ * safe).
+ */
+{
+ static char Buf[4];
+ xsprintf (Buf, sizeof (Buf), "$%02X", (char) Num);
+ return Buf;
+}
+
+
+
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
CodeLabel* JumpTo, LineInfo* LI)
/* Create a new code entry, initialize and return it */
if (CE_KnownImm (E)) {
Out->RegA = In->RegA & (short) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegA = In->RegA & In->Tmp1;
break;
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA << 1) & 0xFF;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = (In->Tmp1 << 1) & 0xFF;
break;
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA - 1) & 0xFF;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = (In->Tmp1 - 1) & 0xFF;
break;
if (CE_KnownImm (E)) {
Out->RegA = In->RegA ^ (short) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegA = In->RegA ^ In->Tmp1;
break;
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA + 1) & 0xFF;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = (In->Tmp1 + 1) & 0xFF;
break;
if (CE_KnownImm (E)) {
Out->RegA = (unsigned char) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegA = In->Tmp1;
break;
if (CE_KnownImm (E)) {
Out->RegX = (unsigned char) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegX = In->Tmp1;
break;
if (CE_KnownImm (E)) {
Out->RegY = (unsigned char) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegY = In->Tmp1;
break;
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA >> 1) & 0xFF;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = (In->Tmp1 >> 1) & 0xFF;
break;
if (CE_KnownImm (E)) {
Out->RegA = In->RegA | (short) E->Num;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Use, In)) {
+ switch (GetKnownReg (E->Use, In)) {
case REG_TMP1:
Out->RegA = In->RegA | In->Tmp1;
break;
if (E->AM == AM65_ACC) {
Out->RegA = -1;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = -1;
break;
if (E->AM == AM65_ACC) {
Out->RegA = -1;
} else if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = -1;
break;
case OP65_STA:
if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, 0)) {
+ switch (GetKnownReg (E->Chg, 0)) {
case REG_TMP1:
Out->Tmp1 = In->RegA;
break;
case OP65_STX:
if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, 0)) {
+ switch (GetKnownReg (E->Chg, 0)) {
case REG_TMP1:
Out->Tmp1 = In->RegX;
break;
case OP65_STY:
if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, 0)) {
+ switch (GetKnownReg (E->Chg, 0)) {
case REG_TMP1:
Out->Tmp1 = In->RegY;
break;
case OP65_STZ:
if (E->AM == AM65_ZP) {
- switch (GetReg (E->Chg, 0)) {
+ switch (GetKnownReg (E->Chg, 0)) {
case REG_TMP1:
Out->Tmp1 = 0;
break;
RC_InvalidateZP (Out);
} else if (E->AM == AM65_ZP) {
if (In->RegA >= 0) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 &= ~In->RegA;
break;
break;
}
} else {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = -1;
break;
RC_InvalidateZP (Out);
} else if (E->AM == AM65_ZP) {
if (In->RegA >= 0) {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 |= In->RegA;
break;
break;
}
} else {
- switch (GetReg (E->Chg, In)) {
+ switch (GetKnownReg (E->Chg, In)) {
case REG_TMP1:
Out->Tmp1 = -1;
break;
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2001-2002 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+const char* MakeHexArg (unsigned Num);
+/* Convert Num into a string in the form $XY, suitable for passing it as an
+ * argument to NewCodeEntry, and return a pointer to the string.
+ * BEWARE: The function returns a pointer to a static buffer, so the value is
+ * gone if you call it twice (and apart from that it's not thread and signal
+ * safe).
+ */
+
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
- CodeLabel* JumpTo, LineInfo* LI);
+ CodeLabel* JumpTo, LineInfo* LI);
/* Create a new code entry, initialize and return it */
void FreeCodeEntry (CodeEntry* E);
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
#include "codeseg.h"
#include "datatype.h"
#include "error.h"
+#include "reginfo.h"
#include "symtab.h"
#include "codeinfo.h"
+unsigned GetKnownReg (unsigned Use, const RegContents* RC)
+/* Return the register or zero page location from the set in Use, thats
+ * contents are known. If Use does not contain any register, or if the
+ * register in question does not have a known value, return REG_NONE.
+ */
+{
+ if ((Use & REG_A) != 0) {
+ return (RC && RC->RegA >= 0)? REG_A : REG_NONE;
+ } else if ((Use & REG_X) != 0) {
+ return (RC && RC->RegX >= 0)? REG_X : REG_NONE;
+ } else if ((Use & REG_Y) != 0) {
+ return (RC && RC->RegY >= 0)? REG_Y : REG_NONE;
+ } else if ((Use & REG_TMP1) != 0) {
+ return (RC && RC->Tmp1 >= 0)? REG_TMP1 : REG_NONE;
+ } else if ((Use & REG_SREG_LO) != 0) {
+ return (RC && RC->SRegLo >= 0)? REG_SREG_LO : REG_NONE;
+ } else if ((Use & REG_SREG_HI) != 0) {
+ return (RC && RC->SRegHi >= 0)? REG_SREG_HI : REG_NONE;
+ } else {
+ return REG_NONE;
+ }
+}
+
+
+
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
+/* Forward to struct RegContents */
+struct RegContents;
+
/* Defines for registers. */
#define REG_NONE 0x0000U
#define REG_A 0x0001U
int RegAXUsed (struct CodeSeg* S, unsigned Index);
/* Check if the value in A or(!) the value in X are used. */
+unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
+/* Return the register or zero page location from the set in Use, thats
+ * contents are known. If Use does not contain any register, or if the
+ * register in question does not have a known value, return REG_NONE.
+ */
+
/* End of codeinfo.h */
* txa -> lda #imm
* tay -> ldy #imm
* tya -> lda #imm
- * lda sreg -> lda #imm
- * ldx sreg -> ldx #imm
- * ldy sreg -> ldy #imm
+ * lda zp -> lda #imm
+ * ldx zp -> ldx #imm
+ * ldy zp -> ldy #imm
*
* Provided that the register values are known of course.
*/
I = 0;
while (I < CS_GetEntryCount (S)) {
- char Buf [16];
+ const char* Arg;
- /* Get next entry */
+ /* Get next entry and it's input register values */
CodeEntry* E = CS_GetEntry (S, I);
+ const RegContents* In = &E->RI->In;
/* Assume we have no replacement */
CodeEntry* X = 0;
case OP65_DEX:
if (E->RI->In.RegX >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", (E->RI->In.RegX - 1) & 0xFF);
- X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg ((E->RI->In.RegX - 1) & 0xFF);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_DEY:
if (E->RI->In.RegY >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", (E->RI->In.RegY - 1) & 0xFF);
- X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg ((E->RI->In.RegY - 1) & 0xFF);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_INX:
if (E->RI->In.RegX >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", (E->RI->In.RegX + 1) & 0xFF);
- X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg ((E->RI->In.RegX + 1) & 0xFF);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_INY:
- if (E->RI->In.RegY >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", (E->RI->In.RegY + 1) & 0xFF);
- X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, E->LI);
+ if (E->RI->In.RegY >= 0) {
+ Arg = MakeHexArg ((E->RI->In.RegY + 1) & 0xFF);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_LDA:
if (E->AM == AM65_ZP) {
- if ((E->Use & REG_SREG_LO) != 0 && E->RI->In.SRegLo >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegLo);
- X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, E->LI);
- } else if ((E->Use & REG_SREG_HI) != 0 && E->RI->In.SRegHi >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegHi);
- X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, E->LI);
+ switch (GetKnownReg (E->Use, In)) {
+ case REG_TMP1:
+ Arg = MakeHexArg (In->Tmp1);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_LO:
+ Arg = MakeHexArg (In->SRegLo);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_HI:
+ Arg = MakeHexArg (In->SRegHi);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
+ break;
}
}
break;
case OP65_LDX:
if (E->AM == AM65_ZP) {
- if ((E->Use & REG_SREG_LO) != 0 && E->RI->In.SRegLo >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegLo);
- X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, E->LI);
- } else if ((E->Use & REG_SREG_HI) != 0 && E->RI->In.SRegHi >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegHi);
- X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, E->LI);
+ switch (GetKnownReg (E->Use, In)) {
+ case REG_TMP1:
+ Arg = MakeHexArg (In->Tmp1);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_LO:
+ Arg = MakeHexArg (In->SRegLo);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_HI:
+ Arg = MakeHexArg (In->SRegHi);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
+ break;
}
}
break;
case OP65_LDY:
if (E->AM == AM65_ZP) {
- if ((E->Use & REG_SREG_LO) != 0 && E->RI->In.SRegLo >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegLo);
- X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, E->LI);
- } else if ((E->Use & REG_SREG_HI) != 0 && E->RI->In.SRegHi >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.SRegHi);
- X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, E->LI);
+ switch (GetKnownReg (E->Use, In)) {
+ case REG_TMP1:
+ Arg = MakeHexArg (In->Tmp1);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_LO:
+ Arg = MakeHexArg (In->SRegLo);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
+ break;
+
+ case REG_SREG_HI:
+ Arg = MakeHexArg (In->SRegHi);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
+ break;
}
}
break;
case OP65_TAX:
if (E->RI->In.RegA >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.RegA);
- X = NewCodeEntry (OP65_LDX, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg (In->RegA);
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_TAY:
if (E->RI->In.RegA >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.RegA);
- X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg (In->RegA);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_TXA:
- if (E->RI->In.RegX >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.RegX);
- X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, E->LI);
+ if (E->RI->In.RegX >= 0) {
+ Arg = MakeHexArg (In->RegX);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
}
break;
case OP65_TYA:
if (E->RI->In.RegY >= 0) {
- xsprintf (Buf, sizeof (Buf), "$%02X", E->RI->In.RegY);
- X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, E->LI);
+ Arg = MakeHexArg (In->RegY);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
}
break;
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
+ /* Check if it's a subroutine call */
+ if (E->OPC == OP65_JSR) {
+
+ /* Check for any of the known functions */
+
+
+
+ }
/* Next entry */
++I;
return;
}
- /* Write the file */
+ /* Write a header */
+ fprintf (F,
+ "; Optimizer Total Last Total Last\n"
+ "; Step Runs Runs Chg Chg\n");
+
+
+ /* Write the data */
for (I = 0; I < OPTFUNC_COUNT; ++I) {
- const OptFunc* O = OptFuncs[I];
- fprintf (F,
+ const OptFunc* O = OptFuncs[I];
+ fprintf (F,
"%-20s %6lu %6lu %6lu %6lu\n",
- O->Name,
+ O->Name,
O->TotalRuns,
O->LastRuns,
O->TotalChanges,
+static short RegVal (unsigned short Use, const RegContents* RC)
+/* Return the contents of the given register */
+{
+ if ((Use & REG_A) != 0) {
+ return RC->RegA;
+ } else if ((Use & REG_X) != 0) {
+ return RC->RegX;
+ } else if ((Use & REG_Y) != 0) {
+ return RC->RegY;
+ } else if ((Use & REG_TMP1) != 0) {
+ return RC->Tmp1;
+ } else if ((Use & REG_SREG_LO) != 0) {
+ return RC->SRegLo;
+ } else if ((Use & REG_SREG_HI) != 0) {
+ return RC->SRegHi;
+ } else {
+ return REG_NONE;
+ }
+}
+
+
+
/*****************************************************************************/
/* Replace jumps to RTS by RTS */
/*****************************************************************************/
*/
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 */
+ In->RegA == RegVal (E->Chg, In)) { /* Value identical */
+
Delete = 1;
}
break;
*/
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 */
+ In->RegX == RegVal (E->Chg, In)) { /* Value identical */
+
Delete = 1;
/* If the value in the X register is known and the same as
*/
if (In->RegY >= 0 && /* Value of Y is known */
E->AM == AM65_ZP && /* Store into zp */
- (((E->Chg & REG_SREG_LO) != 0 && /* Store into sreg */
- In->RegY == In->SRegLo) || /* Value identical */
- ((E->Chg & REG_SREG_HI) != 0 && /* Store into sreg+1 */
- In->RegY == In->SRegHi))) { /* Value identical */
+ In->RegX == RegVal (E->Chg, In)) { /* 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
* remove the store.
*/
if (CPU >= CPU_65C02 && E->AM == AM65_ZP) {
- if (((E->Chg & REG_SREG_LO) != 0 && In->SRegLo == 0) ||
- ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi == 0)) {
+ if (RegVal (E->Chg, In) == 0) {
Delete = 1;
}
}