1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-05 21:29:03 +00:00

First support for STZ

git-svn-id: svn://svn.cc65.org/cc65/trunk@1187 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-03-11 06:29:54 +00:00
parent d814a9a6fb
commit f38852df82
9 changed files with 170 additions and 45 deletions

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 */

View File

@ -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 &&

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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