Add carry optimizations

This commit is contained in:
drmortalwombat 2022-01-15 18:09:48 +01:00
parent de920f2418
commit de562fccb6

View File

@ -571,10 +571,14 @@ bool NativeCodeInstruction::LoadsAccu(void) const
bool NativeCodeInstruction::ChangesAccuAndFlag(void) const bool NativeCodeInstruction::ChangesAccuAndFlag(void) const
{ {
return if (mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR || mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
mType == ASMIT_SBC || mType == ASMIT_ADC || mType == ASMIT_JSR; mType == ASMIT_SBC || mType == ASMIT_ADC || mType == ASMIT_JSR)
return true;
else if (mType == ASMIT_LSR || mType == ASMIT_ASL || mType == ASMIT_ROR || mType == ASMIT_ROL)
return mMode == ASMIM_IMPLIED;
else
return false;
} }
bool NativeCodeInstruction::RequiresYReg(void) const bool NativeCodeInstruction::RequiresYReg(void) const
@ -11765,19 +11769,186 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
} }
#if 1 #if 1
if (carryClear || carrySet) i = 0;
j = 0;
int accuVal = 0, accuMask = 0;
while (i < mIns.Size())
{ {
int i = 0; bool skip = false;
while (i < mIns.Size() && !mIns[i].ChangesCarry()) switch (mIns[i].mType)
{
case ASMIT_CLC:
if (carryClear)
skip = true;
else
{
carryClear = true;
carrySet = false;
}
break;
case ASMIT_SEC:
if (carrySet)
skip = true;
else
{
carryClear = false;
carrySet = true;
}
break;
case ASMIT_ADC:
case ASMIT_SBC:
accuMask = 0;
case ASMIT_CMP:
carryClear = false;
carrySet = false;
break;
case ASMIT_AND:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
{
int clear = mIns[i].mAddress ^ 0xff;
if (!(mIns[i].mLive & CPU_REG_Z) && !(clear & (accuMask ^ 0xff)) && !(accuVal & clear))
skip = true;
accuVal = 0;
accuMask = clear;
}
else
accuMask = 0;
break;
case ASMIT_ORA:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
{
accuVal = 0xff;
accuMask = mIns[i].mAddress;
}
else
accuMask = 0;
break;
case ASMIT_LDA:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
{
accuVal = mIns[i].mAddress;
accuMask = 0xff;
}
else
accuMask = 0x00;
break;
case ASMIT_ASL:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x80))
{
accuVal <<= 1;
accuMask = ((accuMask << 1) | 1) & 0xff;
if (accuVal & 0x100)
{
carryClear = false;
carrySet = true;
}
else
{
carryClear = true;
carrySet = false;
}
accuVal &= 0xff;
}
else
{
carryClear = false;
carrySet = false;
}
break;
case ASMIT_LSR:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x01))
{
accuMask = (accuMask >> 1) | 0x80;
if (accuVal & 0x01)
{
carryClear = false;
carrySet = true;
}
else
{
carryClear = true;
carrySet = false;
}
accuVal >>= 1;
}
else
{
carryClear = false;
carrySet = false;
}
break;
case ASMIT_ROL:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x80))
{
accuVal <<= 1;
accuMask = (accuMask << 1) & 0xff;
if (accuVal & 0x100)
{
carryClear = false;
carrySet = true;
}
else
{
carryClear = true;
carrySet = false;
}
accuVal &= 0xff;
}
else
{
carryClear = false;
carrySet = false;
}
break;
case ASMIT_ROR:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x01))
{
accuMask = (accuMask >> 1);
if (accuVal & 0x01)
{
carryClear = false;
carrySet = true;
}
else
{
carryClear = true;
carrySet = false;
}
accuVal >>= 1;
}
else
{
carryClear = false;
carrySet = false;
}
break;
default:
if (mIns[i].ChangesCarry())
{
carryClear = false;
carrySet = false;
}
if (mIns[i].ChangesAccu())
accuMask = 0;
}
if (!skip)
{
if (i != j)
mIns[j] = mIns[i];
j++;
}
i++; i++;
if (i < mIns.Size())
{
if (mIns[i].mType == ASMIT_CLC && carryClear)
mIns.Remove(i);
else if (mIns[i].mType == ASMIT_SEC && carrySet)
mIns.Remove(i);
}
} }
mIns.SetSize(j);
#endif #endif
if (mTrueJump) if (mTrueJump)
mTrueJump->BlockSizeReduction(); mTrueJump->BlockSizeReduction();
@ -13805,6 +13976,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#endif #endif
} }
if (i + 5 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mFlags & NCIF_VOLATILE) &&
mIns[i + 3].mType == ASMIT_TXA &&
mIns[i + 4].mType == ASMIT_LDY && mIns[i + 4].mMode == ASMIM_IMMEDIATE &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_INDIRECT_Y && mIns[i + 2].mAddress == mIns[i + 5].mAddress &&
!(mIns[i + 5].mFlags & NCIF_VOLATILE) && !(mIns[i + 5].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_Z)))
{
mIns[i + 3] = mIns[i + 0];
mIns[i + 0].mType = ASMIT_TXA; mIns[i + 0].mMode = ASMIM_IMPLIED;
int a = mIns[i + 1].mAddress; mIns[i + 1].mAddress = mIns[i + 4].mAddress; mIns[i + 4].mAddress = a;
progress = true;
}
}
#if 1 #if 1
if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y) if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
{ {