diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 7cca0bd78..bf568565b 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (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 */ @@ -420,6 +420,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { Out->SRegHi = (In->SRegHi << 1) & 0xFF; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -492,6 +495,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { Out->SRegHi = (In->SRegHi - 1) & 0xFF; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -532,6 +538,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { Out->SRegHi = (In->SRegHi + 1) & 0xFF; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -654,6 +663,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if (E->Chg & REG_SREG_HI) { Out->SRegHi = (In->SRegHi >> 1) & 0xFF; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -707,6 +719,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if (E->Chg & REG_SREG_HI) { Out->SRegHi = -1; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -719,6 +734,9 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if (E->Chg & REG_SREG_HI) { Out->SRegHi = -1; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -749,27 +767,49 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else if (E->Chg & REG_SREG_HI) { Out->SRegHi = In->RegA; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } 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; - } + if (E->Chg & REG_SREG_LO) { + Out->SRegLo = In->RegX; + } else if (E->Chg & REG_SREG_HI) { + Out->SRegHi = In->RegX; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } 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; - } - } + if (E->Chg & REG_SREG_LO) { + Out->SRegLo = In->RegY; + } else if (E->Chg & REG_SREG_HI) { + Out->SRegHi = In->RegY; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } + break; + + case OP65_STZ: + if (E->AM == AM65_ZP) { + if (E->Chg & REG_SREG_LO) { + Out->SRegLo = 0; + } else if (E->Chg & REG_SREG_HI) { + Out->SRegHi = 0; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } break; case OP65_TAX: diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 9bf94bbd0..a964f7482 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1278,7 +1278,7 @@ static unsigned OptSize2 (CodeSeg* S) X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); } else if (Val == E->RI->In.RegA) { X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI); - } + } } break; @@ -1351,6 +1351,7 @@ struct OptFunc { /* A list of all the function descriptions */ static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 40, 0, 0, 0, 0, 0 }; @@ -1406,6 +1407,7 @@ static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, static OptFunc* OptFuncs[] = { &DOpt65C02BitOps, &DOpt65C02Ind, + &DOpt65C02Stores, &DOptAdd1, &DOptAdd2, &DOptAdd3, @@ -1775,17 +1777,17 @@ static unsigned RunOptGroup3 (CodeSeg* S) static unsigned RunOptGroup4 (CodeSeg* S) /* 65C02 specific optimizations. */ { - unsigned C; unsigned Changes = 0; if (CPU >= CPU_65C02) { Changes += RunOptFunc (S, &DOpt65C02BitOps, 1); - /* Replace (zp),y by (zp) if Y is zero. If we have changes, run register - * load optimization again, since loads of Y may have become unnecessary. - */ - C = RunOptFunc (S, &DOpt65C02Ind, 1); - Changes += C; - if (C) { + Changes += RunOptFunc (S, &DOpt65C02Ind, 1); + Changes += RunOptFunc (S, &DOpt65C02Stores, 1); + if (Changes) { + /* The 65C02 replacement codes do often make the use of a register + * value unnecessary, so if we have changes, run another load + * removal pass. + */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); } } diff --git a/src/cc65/coptc02.c b/src/cc65/coptc02.c index b7f765c63..816f92c52 100644 --- a/src/cc65/coptc02.c +++ b/src/cc65/coptc02.c @@ -146,26 +146,73 @@ unsigned Opt65C02BitOps (CodeSeg* S) /* LDA #XX */ sprintf (Buf, "$%02X", (int) ((~L[1]->Num) & 0xFF)); X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI); - CS_InsertEntry (S, X, I); + CS_InsertEntry (S, X, I+3); /* TRB */ X = NewCodeEntry (OP65_TRB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); - CS_InsertEntry (S, X, I+1); + CS_InsertEntry (S, X, I+4); } else { /* LDA #XX */ sprintf (Buf, "$%02X", (int) L[1]->Num); X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI); - CS_InsertEntry (S, X, I); + CS_InsertEntry (S, X, I+3); - /* TRB */ + /* TSB */ X = NewCodeEntry (OP65_TSB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); - CS_InsertEntry (S, X, I+1); + CS_InsertEntry (S, X, I+4); } /* Delete the old stuff */ - CS_DelEntries (S, I+2, 3); + CS_DelEntries (S, I, 3); + + /* We had changes */ + ++Changes; + } + + /* Next entry */ + ++I; + + } + + /* Free register info */ + CS_FreeRegInfo (S); + + /* Return the number of changes made */ + return Changes; +} + + + +unsigned Opt65C02Stores (CodeSeg* S) +/* Use STZ where possible */ +{ + unsigned Changes = 0; + unsigned I; + + /* Generate register info for this step */ + CS_GenRegInfo (S); + + /* Walk over the entries */ + I = 0; + while (I < CS_GetEntryCount (S)) { + + /* Get next entry */ + CodeEntry* E = CS_GetEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OP65_STA && + (E->AM == AM65_ZP || E->AM == AM65_ABS || + E->AM == AM65_ZPX || E->AM == AM65_ABSX ) && + E->RI->In.RegA == 0) { + + /* Replace by STZ */ + CodeEntry* X = NewCodeEntry (OP65_STZ, E->AM, E->Arg, 0, E->LI); + CS_InsertEntry (S, X, I+1); + + /* Delete the old stuff */ + CS_DelEntry (S, I); /* We had changes */ ++Changes; diff --git a/src/cc65/coptc02.h b/src/cc65/coptc02.h index 743efb971..309e4578a 100644 --- a/src/cc65/coptc02.h +++ b/src/cc65/coptc02.h @@ -55,6 +55,9 @@ unsigned Opt65C02Ind (CodeSeg* S); unsigned Opt65C02BitOps (CodeSeg* S); /* Use special bit op instructions of the C02 */ +unsigned Opt65C02Stores (CodeSeg* S); +/* Use STZ where possible */ + /* End of coptc02.h */ diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 605c70317..c68918363 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -850,12 +850,12 @@ unsigned OptDupLoads (CodeSeg* S) * location does already contain the value to be stored, * remove the store. */ - if (In->RegX >= 0 && /* Value of A is known */ + 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->RegX == In->SRegLo) || /* Value identical */ + In->RegY == In->SRegLo) || /* Value identical */ ((E->Chg & REG_SREG_HI) != 0 && /* Store into sreg+1 */ - In->RegX == In->SRegHi))) { /* Value identical */ + In->RegY == 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 @@ -866,15 +866,28 @@ unsigned OptDupLoads (CodeSeg* S) */ } else if (In->RegY >= 0) { if (In->RegY == In->RegA) { - CE_ReplaceOPC (E, OP65_STA); + CE_ReplaceOPC (E, OP65_STA); } else if (In->RegY == In->RegX && - E->AM != AM65_ABSX && - E->AM != AM65_ZPX) { + E->AM != AM65_ABSX && + E->AM != AM65_ZPX) { CE_ReplaceOPC (E, OP65_STX); } } break; + case OP65_STZ: + /* If we store into a known zero page location, and this + * location does already contain the value to be stored, + * 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)) { + Delete = 1; + } + } + break; + case OP65_TAX: if (In->RegA >= 0 && In->RegA == In->RegX && diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 6704bef3b..d55a5371f 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -513,6 +513,13 @@ const OPCDesc OPCTable[OPCODE_COUNT] = { REG_NONE, /* chg */ OF_STORE /* flags */ }, + { OP65_STZ, /* opcode */ + "stz", /* mnemonic */ + 0, /* size */ + REG_NONE, /* use */ + REG_NONE, /* chg */ + OF_STORE /* flags */ + }, { OP65_TAX, /* opcode */ "tax", /* mnemonic */ 1, /* size */ @@ -777,7 +784,7 @@ bc_t GetBranchCond (opc_t OPC) case OP65_JPL: return BC_PL; case OP65_JVC: return BC_VC; case OP65_JVS: return BC_VS; - default: + default: Internal ("GetBranchCond: Invalid opcode: %d", OPC); return 0; } @@ -805,4 +812,4 @@ bc_t GetInverseCond (bc_t BC) - + diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index ec798db22..89a7c4117 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -118,6 +118,7 @@ typedef enum { OP65_STA, OP65_STX, OP65_STY, + OP65_STZ, OP65_TAX, OP65_TAY, OP65_TRB, diff --git a/src/cc65/reginfo.c b/src/cc65/reginfo.c index c8a6d094b..ab60e7315 100644 --- a/src/cc65/reginfo.c +++ b/src/cc65/reginfo.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -59,6 +59,15 @@ void RC_Invalidate (RegContents* C) +void RC_InvalidateZP (RegContents* C) +/* Invalidate all ZP registers */ +{ + C->SRegLo = -1; + C->SRegHi = -1; +} + + + RegInfo* NewRegInfo (const RegContents* RC) /* Allocate a new register info, initialize and return it. If RC is not * a NULL pointer, it is used to initialize both, the input and output diff --git a/src/cc65/reginfo.h b/src/cc65/reginfo.h index bcf760b16..aac4c7c81 100644 --- a/src/cc65/reginfo.h +++ b/src/cc65/reginfo.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@cc65.org */ +/* (C) 2001-2002 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -78,6 +78,9 @@ struct RegInfo { void RC_Invalidate (RegContents* C); /* Invalidate all registers */ +void RC_InvalidateZP (RegContents* C); +/* Invalidate all ZP registers */ + RegInfo* NewRegInfo (const RegContents* RC); /* Allocate a new register info, initialize and return it. If RC is not * a NULL pointer, it is used to initialize both, the input and output