Improved optimizations
git-svn-id: svn://svn.cc65.org/cc65/trunk@2613 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -2772,7 +2772,7 @@ void g_or (unsigned flags, unsigned long val)
|
|||||||
|
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
if (flags & CF_FORCECHAR) {
|
if (flags & CF_FORCECHAR) {
|
||||||
if ((val & 0xFF) != 0xFF) {
|
if ((val & 0xFF) != 0) {
|
||||||
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -2781,14 +2781,24 @@ void g_or (unsigned flags, unsigned long val)
|
|||||||
|
|
||||||
case CF_INT:
|
case CF_INT:
|
||||||
if (val <= 0xFF) {
|
if (val <= 0xFF) {
|
||||||
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
if ((val & 0xFF) != 0) {
|
||||||
|
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
} else if ((val & 0xFF00) == 0xFF00) {
|
||||||
|
if ((val & 0xFF) != 0) {
|
||||||
|
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
||||||
|
}
|
||||||
|
ldxconst (0xFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CF_LONG:
|
case CF_LONG:
|
||||||
if (val <= 0xFF) {
|
if (val <= 0xFF) {
|
||||||
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
if ((val & 0xFF) != 0) {
|
||||||
|
AddCodeLine ("ora #$%02X", (unsigned char)val);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2881,68 +2891,70 @@ void g_xor (unsigned flags, unsigned long val)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_and (unsigned flags, unsigned long val)
|
void g_and (unsigned Flags, unsigned long Val)
|
||||||
/* Primary = TOS & Primary */
|
/* Primary = TOS & Primary */
|
||||||
{
|
{
|
||||||
static char* ops [12] = {
|
static char* ops [12] = {
|
||||||
0, "tosanda0", "tosandax",
|
0, "tosanda0", "tosandax",
|
||||||
0, "tosanda0", "tosandax",
|
0, "tosanda0", "tosandax",
|
||||||
0, 0, "tosandeax",
|
0, 0, "tosandeax",
|
||||||
0, 0, "tosandeax",
|
0, 0, "tosandeax",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* If the right hand side is const, the lhs is not on stack but still
|
/* If the right hand side is const, the lhs is not on stack but still
|
||||||
* in the primary register.
|
* in the primary register.
|
||||||
*/
|
*/
|
||||||
if (flags & CF_CONST) {
|
if (Flags & CF_CONST) {
|
||||||
|
|
||||||
switch (flags & CF_TYPE) {
|
switch (Flags & CF_TYPE) {
|
||||||
|
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
if (flags & CF_FORCECHAR) {
|
if (Flags & CF_FORCECHAR) {
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)val);
|
if ((Val & 0xFF) != 0xFF) {
|
||||||
return;
|
AddCodeLine ("and #$%02X", (unsigned char)Val);
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
return;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
case CF_INT:
|
case CF_INT:
|
||||||
if ((val & 0xFFFF) != 0xFFFF) {
|
if ((Val & 0xFFFF) != 0xFFFF) {
|
||||||
if (val <= 0xFF) {
|
if (Val <= 0xFF) {
|
||||||
ldxconst (0);
|
ldxconst (0);
|
||||||
if (val == 0) {
|
if (Val == 0) {
|
||||||
ldaconst (0);
|
ldaconst (0);
|
||||||
} else if (val != 0xFF) {
|
} else if (Val != 0xFF) {
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)val);
|
AddCodeLine ("and #$%02X", (unsigned char)Val);
|
||||||
}
|
}
|
||||||
} else if ((val & 0xFF00) == 0xFF00) {
|
} else if ((Val & 0xFF00) == 0xFF00) {
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)val);
|
AddCodeLine ("and #$%02X", (unsigned char)Val);
|
||||||
} else if ((val & 0x00FF) == 0x0000) {
|
} else if ((Val & 0x00FF) == 0x0000) {
|
||||||
AddCodeLine ("txa");
|
AddCodeLine ("txa");
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
|
AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
|
||||||
AddCodeLine ("tax");
|
AddCodeLine ("tax");
|
||||||
ldaconst (0);
|
ldaconst (0);
|
||||||
} else {
|
} else {
|
||||||
AddCodeLine ("tay");
|
AddCodeLine ("tay");
|
||||||
AddCodeLine ("txa");
|
AddCodeLine ("txa");
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
|
AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
|
||||||
AddCodeLine ("tax");
|
AddCodeLine ("tax");
|
||||||
AddCodeLine ("tya");
|
AddCodeLine ("tya");
|
||||||
if ((val & 0x00FF) != 0x00FF) {
|
if ((Val & 0x00FF) != 0x00FF) {
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)val);
|
AddCodeLine ("and #$%02X", (unsigned char)Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CF_LONG:
|
case CF_LONG:
|
||||||
if (val <= 0xFF) {
|
if (Val <= 0xFF) {
|
||||||
ldxconst (0);
|
ldxconst (0);
|
||||||
AddCodeLine ("stx sreg+1");
|
AddCodeLine ("stx sreg+1");
|
||||||
AddCodeLine ("stx sreg");
|
AddCodeLine ("stx sreg");
|
||||||
if ((val & 0xFF) != 0xFF) {
|
if ((Val & 0xFF) != 0xFF) {
|
||||||
AddCodeLine ("and #$%02X", (unsigned char)val);
|
AddCodeLine ("and #$%02X", (unsigned char)Val);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (val == 0xFF00) {
|
} else if (Val == 0xFF00) {
|
||||||
ldaconst (0);
|
ldaconst (0);
|
||||||
AddCodeLine ("sta sreg+1");
|
AddCodeLine ("sta sreg+1");
|
||||||
AddCodeLine ("sta sreg");
|
AddCodeLine ("sta sreg");
|
||||||
@@ -2951,19 +2963,19 @@ void g_and (unsigned flags, unsigned long val)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
typeerror (flags);
|
typeerror (Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we go here, we didn't emit code. Push the lhs on stack and fall
|
/* If we go here, we didn't emit code. Push the lhs on stack and fall
|
||||||
* into the normal, non-optimized stuff. Note: The standard stuff will
|
* into the normal, non-optimized stuff. Note: The standard stuff will
|
||||||
* always work with ints.
|
* always work with ints.
|
||||||
*/
|
*/
|
||||||
flags &= ~CF_FORCECHAR;
|
Flags &= ~CF_FORCECHAR;
|
||||||
g_push (flags & ~CF_CONST, 0);
|
g_push (Flags & ~CF_CONST, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use long way over the stack */
|
/* Use long way over the stack */
|
||||||
oper (flags, val, ops);
|
oper (Flags, Val, ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1315,6 +1315,9 @@ unsigned OptPrecalc (CodeSeg* S)
|
|||||||
/* Get a pointer to the output registers of the insn */
|
/* Get a pointer to the output registers of the insn */
|
||||||
const RegContents* Out = &E->RI->Out;
|
const RegContents* Out = &E->RI->Out;
|
||||||
|
|
||||||
|
/* Argument for LDA and flag */
|
||||||
|
const char* Arg = 0;
|
||||||
|
|
||||||
/* Handle the different instructions */
|
/* Handle the different instructions */
|
||||||
switch (E->OPC) {
|
switch (E->OPC) {
|
||||||
|
|
||||||
@@ -1328,19 +1331,35 @@ unsigned OptPrecalc (CodeSeg* S)
|
|||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case OP65_ADC:
|
case OP65_ADC:
|
||||||
case OP65_AND:
|
|
||||||
case OP65_ASL:
|
case OP65_ASL:
|
||||||
case OP65_EOR:
|
case OP65_EOR:
|
||||||
case OP65_LSR:
|
case OP65_LSR:
|
||||||
case OP65_ORA:
|
|
||||||
case OP65_SBC:
|
case OP65_SBC:
|
||||||
if (RegValIsKnown (Out->RegA)) {
|
if (RegValIsKnown (Out->RegA)) {
|
||||||
/* Accu AND zp with known contents */
|
/* Accu AND zp with known contents */
|
||||||
const char* Arg = MakeHexArg (Out->RegA);
|
Arg = MakeHexArg (Out->RegA);
|
||||||
CodeEntry* X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
|
}
|
||||||
CS_InsertEntry (S, X, I+1);
|
break;
|
||||||
|
|
||||||
|
case OP65_AND:
|
||||||
|
if (CE_KnownImm (E) && E->Num == 0xFF) {
|
||||||
|
/* AND with 0xFF, remove */
|
||||||
CS_DelEntry (S, I);
|
CS_DelEntry (S, I);
|
||||||
++Changes;
|
++Changes;
|
||||||
|
} else if (RegValIsKnown (Out->RegA)) {
|
||||||
|
/* Accu AND zp with known contents */
|
||||||
|
Arg = MakeHexArg (Out->RegA);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OP65_ORA:
|
||||||
|
if (CE_KnownImm (E) && E->Num == 0x00) {
|
||||||
|
/* ORA with zero, remove */
|
||||||
|
CS_DelEntry (S, I);
|
||||||
|
++Changes;
|
||||||
|
} else if (RegValIsKnown (Out->RegA)) {
|
||||||
|
/* Accu AND zp with known contents */
|
||||||
|
Arg = MakeHexArg (Out->RegA);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1349,6 +1368,14 @@ unsigned OptPrecalc (CodeSeg* S)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if we have to replace the insn by LDA */
|
||||||
|
if (Arg) {
|
||||||
|
CodeEntry* X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
|
||||||
|
CS_InsertEntry (S, X, I+1);
|
||||||
|
CS_DelEntry (S, I);
|
||||||
|
++Changes;
|
||||||
|
}
|
||||||
|
|
||||||
/* Next entry */
|
/* Next entry */
|
||||||
++I;
|
++I;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -552,9 +552,10 @@ static unsigned Opt_tosorax (StackOpData* D)
|
|||||||
if (RegValIsKnown (D->PushEntry->RI->In.RegX) &&
|
if (RegValIsKnown (D->PushEntry->RI->In.RegX) &&
|
||||||
RegValIsKnown (D->OpEntry->RI->In.RegX)) {
|
RegValIsKnown (D->OpEntry->RI->In.RegX)) {
|
||||||
/* Both values known, precalculate the result */
|
/* Both values known, precalculate the result */
|
||||||
const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX | D->OpEntry->RI->In.RegX);
|
unsigned char Result = D->PushEntry->RI->In.RegX | D->OpEntry->RI->In.RegX;
|
||||||
X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
|
const char* Arg = MakeHexArg (Result);
|
||||||
InsertEntry (D, X, D->IP++);
|
X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
|
||||||
|
InsertEntry (D, X, D->IP++);
|
||||||
} else if (D->PushEntry->RI->In.RegX != 0) {
|
} else if (D->PushEntry->RI->In.RegX != 0) {
|
||||||
/* High byte is unknown */
|
/* High byte is unknown */
|
||||||
AddOpHigh (D, OP65_ORA);
|
AddOpHigh (D, OP65_ORA);
|
||||||
|
|||||||
Reference in New Issue
Block a user