Improve XY usage in 16 bit arithmetic
This commit is contained in:
parent
5435e1c930
commit
6014018f4e
|
@ -37,6 +37,22 @@ void NativeRegisterData::ResetMask(void)
|
||||||
mMask = 0;
|
mMask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeRegisterData::SameData(const NativeCodeInstruction& ins) const
|
||||||
|
{
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
||||||
|
return mMode == NRDM_ZERO_PAGE && mValue == ins.mAddress;
|
||||||
|
else if (ins.mMode == ASMIM_ABSOLUTE)
|
||||||
|
return mMode == NRDM_ABSOLUTE && mValue == ins.mAddress && mLinkerObject == ins.mLinkerObject && mFlags == ins.mFlags;
|
||||||
|
else if (ins.mMode == ASMIM_ABSOLUTE_X)
|
||||||
|
return mMode == NRDM_ABSOLUTE_X && mValue == ins.mAddress && mLinkerObject == ins.mLinkerObject && mFlags == ins.mFlags;
|
||||||
|
else if (ins.mMode == ASMIM_ABSOLUTE_Y)
|
||||||
|
return mMode == NRDM_ABSOLUTE_Y && mValue == ins.mAddress && mLinkerObject == ins.mLinkerObject && mFlags == ins.mFlags;
|
||||||
|
else if (ins.mMode == ASMIM_INDIRECT_Y)
|
||||||
|
return mMode == NRDM_INDIRECT_Y && mValue == ins.mAddress;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeRegisterData::SameData(const NativeRegisterData& d) const
|
bool NativeRegisterData::SameData(const NativeRegisterData& d) const
|
||||||
{
|
{
|
||||||
if (mMode != d.mMode)
|
if (mMode != d.mMode)
|
||||||
|
@ -2777,24 +2793,42 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASMIT_TXA:
|
case ASMIT_TXA:
|
||||||
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
if (data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_X]) && !(mLive & LIVE_CPU_REG_Z))
|
||||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
mType = ASMIT_NOP;
|
||||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
mMode = ASMIM_IMPLIED;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data.mRegs[CPU_REG_Z].Reset();
|
{
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
||||||
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||||
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.mRegs[CPU_REG_Z].Reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_TYA:
|
case ASMIT_TYA:
|
||||||
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
if (data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_Y]) && !(mLive & LIVE_CPU_REG_Z))
|
||||||
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
mType = ASMIT_NOP;
|
||||||
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
mMode = ASMIM_IMPLIED;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data.mRegs[CPU_REG_Z].Reset();
|
{
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
||||||
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||||
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.mRegs[CPU_REG_Z].Reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_TAX:
|
case ASMIT_TAX:
|
||||||
data.ResetX();
|
data.ResetX();
|
||||||
|
@ -2899,6 +2933,22 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
mAddress = data.mRegs[CPU_REG_A].mValue;
|
mAddress = data.mRegs[CPU_REG_A].mValue;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
|
else if (data.mRegs[CPU_REG_X].SameData(*this))
|
||||||
|
{
|
||||||
|
mType = ASMIT_TXA;
|
||||||
|
mMode = ASMIM_IMPLIED;
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (data.mRegs[CPU_REG_Y].SameData(*this))
|
||||||
|
{
|
||||||
|
mType = ASMIT_TYA;
|
||||||
|
mMode = ASMIM_IMPLIED;
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
else if (data.mRegs[CPU_REG_X].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_X].mValue == mAddress)
|
else if (data.mRegs[CPU_REG_X].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_X].mValue == mAddress)
|
||||||
{
|
{
|
||||||
mType = ASMIT_TXA;
|
mType = ASMIT_TXA;
|
||||||
|
@ -2906,7 +2956,6 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
else if (data.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_Y].mValue == mAddress)
|
else if (data.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_Y].mValue == mAddress)
|
||||||
{
|
{
|
||||||
mType = ASMIT_TYA;
|
mType = ASMIT_TYA;
|
||||||
|
@ -3233,6 +3282,20 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
}
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
else if (data.mRegs[CPU_REG_X].SameData(*this))
|
||||||
|
{
|
||||||
|
mType = ASMIT_TXA;
|
||||||
|
mMode = ASMIM_IMPLIED;
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (data.mRegs[CPU_REG_Y].SameData(*this))
|
||||||
|
{
|
||||||
|
mType = ASMIT_TYA;
|
||||||
|
mMode = ASMIM_IMPLIED;
|
||||||
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_A].mMode = NRDM_INDIRECT_Y;
|
data.mRegs[CPU_REG_A].mMode = NRDM_INDIRECT_Y;
|
||||||
|
@ -12706,6 +12769,39 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if 1
|
||||||
|
if (i + 4 < mIns.Size() &&
|
||||||
|
mIns[i + 0].mType == ASMIT_TAX &&
|
||||||
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0x00 &&
|
||||||
|
mIns[i + 2].mType == ASMIT_ROL && mIns[i + 2].mMode == ASMIM_IMPLIED &&
|
||||||
|
mIns[i + 3].mType == ASMIT_TAY &&
|
||||||
|
mIns[i + 4].mType == ASMIT_TXA && !(mIns[i + 4].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* rblock = proc->AllocateBlock();
|
||||||
|
|
||||||
|
rblock->mTrueJump = mTrueJump;
|
||||||
|
rblock->mFalseJump = mFalseJump;
|
||||||
|
rblock->mBranch = mBranch;
|
||||||
|
|
||||||
|
for (int j = i + 5; j < mIns.Size(); j++)
|
||||||
|
rblock->mIns.Push(mIns[j]);
|
||||||
|
mIns.SetSize(i);
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
||||||
|
|
||||||
|
mTrueJump = iblock;
|
||||||
|
mFalseJump = rblock;
|
||||||
|
mBranch = ASMIT_BCS;
|
||||||
|
|
||||||
|
iblock->mIns.Push(NativeCodeInstruction(ASMIT_INY));
|
||||||
|
|
||||||
|
iblock->Close(rblock, nullptr, ASMIT_JMP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
if (i + 3 < mIns.Size() &&
|
if (i + 3 < mIns.Size() &&
|
||||||
mIns[i + 0].ChangesAccuAndFlag() &&
|
mIns[i + 0].ChangesAccuAndFlag() &&
|
||||||
|
@ -12982,6 +13078,64 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
mBranch = ASMIT_BCC;
|
mBranch = ASMIT_BCC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_TYA &&
|
||||||
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
|
||||||
|
mIns[i + 2].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STY, mIns[i + 2].mMode) &&
|
||||||
|
!(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
|
||||||
|
|
||||||
|
fblock->mTrueJump = mTrueJump;
|
||||||
|
fblock->mFalseJump = mFalseJump;
|
||||||
|
fblock->mBranch = mBranch;
|
||||||
|
|
||||||
|
for (int j = i + 2; j < mIns.Size(); j++)
|
||||||
|
fblock->mIns.Push(mIns[j]);
|
||||||
|
mIns.SetSize(i);
|
||||||
|
|
||||||
|
fblock->mIns[0].mType = ASMIT_STY;
|
||||||
|
|
||||||
|
iblock->mIns.Push(NativeCodeInstruction(ASMIT_INY));
|
||||||
|
iblock->mTrueJump = fblock;
|
||||||
|
iblock->mBranch = ASMIT_JMP;
|
||||||
|
|
||||||
|
mTrueJump = fblock;
|
||||||
|
mFalseJump = iblock;
|
||||||
|
mBranch = ASMIT_BCC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_TXA &&
|
||||||
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
|
||||||
|
mIns[i + 2].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 2].mMode) &&
|
||||||
|
!(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
|
||||||
|
|
||||||
|
fblock->mTrueJump = mTrueJump;
|
||||||
|
fblock->mFalseJump = mFalseJump;
|
||||||
|
fblock->mBranch = mBranch;
|
||||||
|
|
||||||
|
for (int j = i + 2; j < mIns.Size(); j++)
|
||||||
|
fblock->mIns.Push(mIns[j]);
|
||||||
|
mIns.SetSize(i);
|
||||||
|
|
||||||
|
fblock->mIns[0].mType = ASMIT_STX;
|
||||||
|
|
||||||
|
iblock->mIns.Push(NativeCodeInstruction(ASMIT_INX));
|
||||||
|
iblock->mTrueJump = fblock;
|
||||||
|
iblock->mBranch = ASMIT_JMP;
|
||||||
|
|
||||||
|
mTrueJump = fblock;
|
||||||
|
mFalseJump = iblock;
|
||||||
|
mBranch = ASMIT_BCC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
else if (mIns[i + 0].mType == ASMIT_TYA &&
|
else if (mIns[i + 0].mType == ASMIT_TYA &&
|
||||||
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
|
||||||
mIns[i + 2].mType == ASMIT_TAY &&
|
mIns[i + 2].mType == ASMIT_TAY &&
|
||||||
|
@ -18144,6 +18298,56 @@ bool NativeCodeBasicBlock::CombineImmediateADCUp(int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CombineImmediateADCUpX(int at)
|
||||||
|
{
|
||||||
|
int i = at;
|
||||||
|
while (i > 3)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
if (mIns[i].mType == ASMIT_TAX)
|
||||||
|
{
|
||||||
|
if (!(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
|
||||||
|
{
|
||||||
|
if (mIns[i - 3].mType == ASMIT_CLC &&
|
||||||
|
mIns[i - 2].mType == ASMIT_LDA &&
|
||||||
|
mIns[i - 1].mType == ASMIT_ADC && (mIns[i - 1].mMode == ASMIM_IMMEDIATE || mIns[i - 1].mMode == ASMIM_IMMEDIATE_ADDRESS))
|
||||||
|
{
|
||||||
|
int val = mIns[at + 1].mAddress;
|
||||||
|
mIns[at + 1].CopyMode(mIns[i - 1]);
|
||||||
|
if (mIns[at + 1].mFlags & NCIF_UPPER)
|
||||||
|
mIns[at + 1].mAddress += val * 256;
|
||||||
|
else
|
||||||
|
mIns[at + 1].mAddress += val;
|
||||||
|
mIns[i - 1].mType = ASMIT_NOP; mIns[i - 1].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i - 3].mType = ASMIT_NOP; mIns[i - 3].mMode = ASMIM_IMPLIED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if
|
||||||
|
(mIns[i - 2].mType == ASMIT_CLC &&
|
||||||
|
mIns[i - 1].mType == ASMIT_ADC && (mIns[i - 1].mMode == ASMIM_IMMEDIATE || mIns[i - 1].mMode == ASMIM_IMMEDIATE_ADDRESS))
|
||||||
|
{
|
||||||
|
int val = mIns[at + 1].mAddress;
|
||||||
|
mIns[at + 1].CopyMode(mIns[i - 1]);
|
||||||
|
if (mIns[at + 1].mFlags & NCIF_UPPER)
|
||||||
|
mIns[at + 1].mAddress += val * 256;
|
||||||
|
else
|
||||||
|
mIns[at + 1].mAddress += val;
|
||||||
|
mIns[i - 2].mType = ASMIT_NOP; mIns[i - 2].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i - 1].mType = ASMIT_NOP; mIns[i - 1].mMode = ASMIM_IMPLIED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIns[i].ReferencesXReg())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::MoveASLMemUp(int at)
|
bool NativeCodeBasicBlock::MoveASLMemUp(int at)
|
||||||
{
|
{
|
||||||
int j = at;
|
int j = at;
|
||||||
|
@ -22455,6 +22659,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
if (CombineImmediateADCUp(i))
|
if (CombineImmediateADCUp(i))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
else if (mIns[i].mType == ASMIT_TXA && !(mIns[i].mLive & LIVE_CPU_REG_X) &&
|
||||||
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
if (CombineImmediateADCUpX(i))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckLive();
|
CheckLive();
|
||||||
|
@ -23983,6 +24193,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mType = ASMIT_LDA;
|
mIns[i + 0].mType = ASMIT_LDA;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
|
||||||
|
mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
int val = mIns[i + 0].mAddress;
|
||||||
|
mIns[i + 0].CopyMode(mIns[i + 1]);
|
||||||
|
mIns[i + 1].mMode = ASMIM_IMMEDIATE;
|
||||||
|
mIns[i + 1].mAddress = val;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
|
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
|
||||||
{
|
{
|
||||||
const NativeCodeInstruction* ains, *iins;
|
const NativeCodeInstruction* ains, *iins;
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct NativeRegisterData
|
||||||
void ResetMask(void);
|
void ResetMask(void);
|
||||||
|
|
||||||
bool SameData(const NativeRegisterData& d) const;
|
bool SameData(const NativeRegisterData& d) const;
|
||||||
|
bool SameData(const NativeCodeInstruction& ins) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NativeRegisterDataSet
|
struct NativeRegisterDataSet
|
||||||
|
@ -320,6 +321,7 @@ public:
|
||||||
bool ReplaceXRegWithYReg(int start, int end);
|
bool ReplaceXRegWithYReg(int start, int end);
|
||||||
bool MoveASLMemUp(int start);
|
bool MoveASLMemUp(int start);
|
||||||
bool CombineImmediateADCUp(int at);
|
bool CombineImmediateADCUp(int at);
|
||||||
|
bool CombineImmediateADCUpX(int at);
|
||||||
|
|
||||||
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
|
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
|
||||||
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
|
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
|
||||||
|
|
Loading…
Reference in New Issue