mirror of
https://github.com/cc65/cc65.git
synced 2025-04-08 19:38:55 +00:00
Merge pull request #2240 from acqn/BitwiseOpt
[cc65] New TOS optimization steps for 8-bit subtraction and bitwise operations
This commit is contained in:
commit
a8d00bfaae
@ -1105,6 +1105,62 @@ static unsigned Opt_tosxorax (StackOpData* D)
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tosbitwise (StackOpData* D, opc_t OPC)
|
||||
/* Optimize the tosandax/tosorax/tosxorax sequence. */
|
||||
{
|
||||
CodeEntry* X;
|
||||
|
||||
|
||||
/* Inline the bitwise operation */
|
||||
D->IP = D->OpIndex+1;
|
||||
|
||||
/* Backup lhs if necessary */
|
||||
if ((D->Rhs.A.Flags & LI_DIRECT) == 0) {
|
||||
if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
|
||||
/* Just reload lhs */
|
||||
X = NewCodeEntry (OPC, D->Lhs.A.LoadEntry->AM, D->Lhs.A.LoadEntry->Arg, 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
} else {
|
||||
/* Backup lhs */
|
||||
X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPLo, 0, D->PushEntry->LI);
|
||||
InsertEntry (D, X, D->PushIndex+1);
|
||||
/* Add code for low operand */
|
||||
X = NewCodeEntry (OPC, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
}
|
||||
} else {
|
||||
/* Add code for low operand */
|
||||
X = NewCodeEntry (OPC, D->Rhs.A.LoadEntry->AM, D->Rhs.A.LoadEntry->Arg, 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
/* Rhs load entries may be removed */
|
||||
D->Rhs.A.Flags |= LI_REMOVE;
|
||||
}
|
||||
|
||||
/* Do high-byte operation only when its result is used */
|
||||
if ((GetRegInfo (D->Code, D->IP, REG_X) & REG_X) != 0) {
|
||||
/* Replace the high-byte load with 0 for EOR, or just leave it alone */
|
||||
if (OPC == OP65_EOR) {
|
||||
X = NewCodeEntry (OP65_LDX, AM65_IMM, MakeHexArg (0), 0, D->Rhs.X.ChgEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
D->Rhs.X.Flags |= LI_REMOVE;
|
||||
} else {
|
||||
D->Rhs.X.Flags |= LI_DONT_REMOVE;
|
||||
}
|
||||
} else {
|
||||
/* Rhs load entries may be removed */
|
||||
D->Rhs.X.Flags |= LI_REMOVE;
|
||||
}
|
||||
|
||||
/* Remove the push and the call to the tossubax function */
|
||||
RemoveRemainders (D);
|
||||
|
||||
/* We changed the sequence */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
|
||||
/* Optimize the TOS compare sequence with a bool transformer */
|
||||
{
|
||||
@ -1177,6 +1233,14 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tosand (StackOpData* D)
|
||||
/* Optimize the tosandax sequence. */
|
||||
{
|
||||
return Opt_a_tosbitwise (D, OP65_AND);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_toseq (StackOpData* D)
|
||||
/* Optimize the toseqax sequence */
|
||||
{
|
||||
@ -1292,6 +1356,66 @@ static unsigned Opt_a_tosne (StackOpData* D)
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tosor (StackOpData* D)
|
||||
/* Optimize the tosorax sequence. */
|
||||
{
|
||||
return Opt_a_tosbitwise (D, OP65_ORA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tossub (StackOpData* D)
|
||||
/* Optimize the tossubax sequence. */
|
||||
{
|
||||
CodeEntry* X;
|
||||
|
||||
|
||||
/* Inline the sbc */
|
||||
D->IP = D->OpIndex+1;
|
||||
|
||||
/* Must be true because of OP_RHS_LOAD */
|
||||
CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0);
|
||||
|
||||
/* sec */
|
||||
X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
/* Add code for low operand */
|
||||
AddOpLow (D, OP65_SBC, &D->Rhs);
|
||||
|
||||
/* Do sign-extension as high-byte operation only when its result is used */
|
||||
if ((GetRegInfo (D->Code, D->IP, REG_X) & REG_X) != 0) {
|
||||
CodeLabel* L;
|
||||
CodeEntry* N;
|
||||
|
||||
X = NewCodeEntry (OP65_LDX, AM65_IMM, MakeHexArg (0), 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
/* Add sign extension - N is unused now */
|
||||
N = CS_GetEntry (D->Code, D->IP);
|
||||
CHECK (N != 0);
|
||||
L = CS_GenLabel (D->Code, N);
|
||||
|
||||
X = NewCodeEntry (OP65_BCS, AM65_BRA, L->Name, L, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, D->OpEntry->LI);
|
||||
InsertEntry (D, X, D->IP++);
|
||||
}
|
||||
|
||||
/* Rhs load entries must be removed */
|
||||
D->Rhs.X.Flags |= LI_REMOVE;
|
||||
D->Rhs.A.Flags |= LI_REMOVE;
|
||||
|
||||
/* Remove the push and the call to the tossubax function */
|
||||
RemoveRemainders (D);
|
||||
|
||||
/* We changed the sequence */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tosuge (StackOpData* D)
|
||||
/* Optimize the tosgeax and tosugeax sequences */
|
||||
{
|
||||
@ -1324,6 +1448,14 @@ static unsigned Opt_a_tosult (StackOpData* D)
|
||||
|
||||
|
||||
|
||||
static unsigned Opt_a_tosxor (StackOpData* D)
|
||||
/* Optimize the tosxorax sequence. */
|
||||
{
|
||||
return Opt_a_tosbitwise (D, OP65_EOR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -1356,6 +1488,7 @@ static const OptFuncDesc FuncTable[] = {
|
||||
};
|
||||
|
||||
static const OptFuncDesc FuncRegATable[] = {
|
||||
{ "tosandax", Opt_a_tosand, REG_NONE, OP_NONE },
|
||||
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
||||
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||
@ -1363,10 +1496,13 @@ static const OptFuncDesc FuncRegATable[] = {
|
||||
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
||||
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
|
||||
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
|
||||
{ "tosorax", Opt_a_tosor, REG_NONE, OP_NONE },
|
||||
{ "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||
{ "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
||||
{ "tosultax", Opt_a_tosult, REG_NONE, OP_NONE },
|
||||
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_NONE },
|
||||
};
|
||||
|
||||
#define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))
|
||||
|
Loading…
x
Reference in New Issue
Block a user