Fix the check for CPU flags being used after an instruction that gets removed.
Previously only the next instruction was checked for usage of the CPU flags but this fails for certain code.
This commit is contained in:
@@ -560,11 +560,8 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
|
|||||||
*Use = REG_NONE;
|
*Use = REG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Will destroy all registers */
|
/* Will destroy all registers and processor flags */
|
||||||
*Chg = REG_ALL;
|
*Chg = (REG_ALL | PSTATE_ALL);
|
||||||
|
|
||||||
/* and will destroy all processor flags */
|
|
||||||
*Chg |= PSTATE_ALL;
|
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
return FNCLS_GLOBAL;
|
return FNCLS_GLOBAL;
|
||||||
@@ -577,8 +574,7 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
|
|||||||
** are used mostly in inline assembly anyway.
|
** are used mostly in inline assembly anyway.
|
||||||
*/
|
*/
|
||||||
*Use = REG_ALL;
|
*Use = REG_ALL;
|
||||||
*Chg = REG_ALL;
|
*Chg = (REG_ALL | PSTATE_ALL);
|
||||||
*Chg |= PSTATE_ALL;
|
|
||||||
return FNCLS_NUMERIC;
|
return FNCLS_NUMERIC;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -605,8 +601,7 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
|
|||||||
fprintf (stderr, "No info about internal function '%s'\n", Name);
|
fprintf (stderr, "No info about internal function '%s'\n", Name);
|
||||||
}
|
}
|
||||||
*Use = REG_ALL;
|
*Use = REG_ALL;
|
||||||
*Chg = REG_ALL;
|
*Chg = (REG_ALL | PSTATE_ALL);
|
||||||
*Chg |= PSTATE_ALL;
|
|
||||||
}
|
}
|
||||||
return FNCLS_BUILTIN;
|
return FNCLS_BUILTIN;
|
||||||
}
|
}
|
||||||
@@ -615,8 +610,7 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
|
|||||||
** registers and processor flags are changed
|
** registers and processor flags are changed
|
||||||
*/
|
*/
|
||||||
*Use = REG_EAXY;
|
*Use = REG_EAXY;
|
||||||
*Chg = REG_ALL;
|
*Chg = (REG_ALL | PSTATE_ALL);
|
||||||
*Chg |= PSTATE_ALL;
|
|
||||||
|
|
||||||
return FNCLS_UNKNOWN;
|
return FNCLS_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -899,6 +893,14 @@ int RegEAXUsed (struct CodeSeg* S, unsigned Index)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int LoadFlagsUsed (struct CodeSeg* S, unsigned Index)
|
||||||
|
/* Check if one of the flags set by a register load (Z and N) are used. */
|
||||||
|
{
|
||||||
|
return (GetRegInfo (S, Index, PSTATE_ZN) & PSTATE_ZN) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned GetKnownReg (unsigned Use, const RegContents* RC)
|
unsigned GetKnownReg (unsigned Use, const RegContents* RC)
|
||||||
/* Return the register or zero page location from the set in Use, thats
|
/* 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
|
** contents are known. If Use does not contain any register, or if the
|
||||||
|
|||||||
@@ -201,6 +201,9 @@ int RegAXUsed (struct CodeSeg* S, unsigned Index);
|
|||||||
int RegEAXUsed (struct CodeSeg* S, unsigned Index);
|
int RegEAXUsed (struct CodeSeg* S, unsigned Index);
|
||||||
/* Check if any of the four bytes in EAX are used. */
|
/* Check if any of the four bytes in EAX are used. */
|
||||||
|
|
||||||
|
int LoadFlagsUsed (struct CodeSeg* S, unsigned Index);
|
||||||
|
/* Check if one of the flags set by a register load (Z and N) are used. */
|
||||||
|
|
||||||
unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
|
unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
|
||||||
/* Return the register or zero page location from the set in Use, thats
|
/* 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
|
** contents are known. If Use does not contain any register, or if the
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ static short ZPRegVal (unsigned short Use, const RegContents* RC)
|
|||||||
|
|
||||||
|
|
||||||
unsigned OptUnusedLoads (CodeSeg* S)
|
unsigned OptUnusedLoads (CodeSeg* S)
|
||||||
/* Remove loads of or operations with registers where the value loaded or
|
/* Remove loads of or operations with registers where the value loaded or
|
||||||
** produced is not used later.
|
** produced is not used later.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned Changes = 0;
|
unsigned Changes = 0;
|
||||||
@@ -173,7 +173,7 @@ unsigned OptUnusedLoads (CodeSeg* S)
|
|||||||
E->OPC == OP65_ORA;
|
E->OPC == OP65_ORA;
|
||||||
|
|
||||||
/* Check for the necessary preconditions */
|
/* Check for the necessary preconditions */
|
||||||
if (IsOp && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) {
|
if (IsOp && (N = CS_GetNextEntry (S, I)) != 0 && !LoadFlagsUsed (S, I+1)) {
|
||||||
|
|
||||||
/* Check which sort of load or transfer it is */
|
/* Check which sort of load or transfer it is */
|
||||||
unsigned R;
|
unsigned R;
|
||||||
|
|||||||
@@ -788,8 +788,7 @@ unsigned OptBinOps (CodeSeg* S)
|
|||||||
** The instruction can be removed if the flags aren't
|
** The instruction can be removed if the flags aren't
|
||||||
** used later.
|
** used later.
|
||||||
*/
|
*/
|
||||||
CodeEntry* N = CS_GetNextEntry (S, I);
|
if (!LoadFlagsUsed (S, I+1)) {
|
||||||
if (N && !CE_UseLoadFlags (N)) {
|
|
||||||
Delete = 1;
|
Delete = 1;
|
||||||
}
|
}
|
||||||
} else if (Operand >= 0) {
|
} else if (Operand >= 0) {
|
||||||
@@ -822,8 +821,7 @@ unsigned OptBinOps (CodeSeg* S)
|
|||||||
** The instruction can be removed if the flags aren't
|
** The instruction can be removed if the flags aren't
|
||||||
** used later.
|
** used later.
|
||||||
*/
|
*/
|
||||||
CodeEntry* N = CS_GetNextEntry (S, I);
|
if (!LoadFlagsUsed (S, I+1)) {
|
||||||
if (N && !CE_UseLoadFlags (N)) {
|
|
||||||
Delete = 1;
|
Delete = 1;
|
||||||
}
|
}
|
||||||
} else if (Operand >= 0) {
|
} else if (Operand >= 0) {
|
||||||
@@ -861,8 +859,7 @@ unsigned OptBinOps (CodeSeg* S)
|
|||||||
** The instruction can be removed if the flags aren't
|
** The instruction can be removed if the flags aren't
|
||||||
** used later.
|
** used later.
|
||||||
*/
|
*/
|
||||||
CodeEntry* N = CS_GetNextEntry (S, I);
|
if (!LoadFlagsUsed (S, I+1)) {
|
||||||
if (N && !CE_UseLoadFlags (N)) {
|
|
||||||
Delete = 1;
|
Delete = 1;
|
||||||
}
|
}
|
||||||
} else if (Operand == 0xFF) {
|
} else if (Operand == 0xFF) {
|
||||||
|
|||||||
Reference in New Issue
Block a user