Skip to content

Commit

Permalink
Improve XY usage in 16 bit arithmetic
Browse files Browse the repository at this point in the history
  • Loading branch information
drmortalwombat committed Aug 27, 2022
1 parent 5435e1c commit 6014018
Show file tree
Hide file tree
Showing 2 changed files with 235 additions and 11 deletions.
244 changes: 233 additions & 11 deletions oscar64/NativeCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ void NativeRegisterData::ResetMask(void)
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
{
if (mMode != d.mMode)
Expand Down Expand Up @@ -2777,24 +2793,42 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
break;

case ASMIT_TXA:
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
if (data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_X]) && !(mLive & LIVE_CPU_REG_Z))
{
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true;
}
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;
case ASMIT_TYA:
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
if (data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_Y]) && !(mLive & LIVE_CPU_REG_Z))
{
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true;
}
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;
case ASMIT_TAX:
data.ResetX();
Expand Down Expand Up @@ -2899,14 +2933,29 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
mAddress = data.mRegs[CPU_REG_A].mValue;
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)
{
mType = ASMIT_TXA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
changed = true;
}
#if 1
else if (data.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_Y].mValue == mAddress)
{
mType = ASMIT_TYA;
Expand Down Expand Up @@ -3233,6 +3282,20 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
}
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
{
data.mRegs[CPU_REG_A].mMode = NRDM_INDIRECT_Y;
Expand Down Expand Up @@ -12706,6 +12769,39 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
break;
}
#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 (i + 3 < mIns.Size() &&
mIns[i + 0].ChangesAccuAndFlag() &&
Expand Down Expand Up @@ -12982,6 +13078,64 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
mBranch = ASMIT_BCC;
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 &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
mIns[i + 2].mType == ASMIT_TAY &&
Expand Down Expand Up @@ -18144,6 +18298,56 @@ bool NativeCodeBasicBlock::CombineImmediateADCUp(int at)
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)
{
int j = at;
Expand Down Expand Up @@ -22455,6 +22659,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
if (CombineImmediateADCUp(i))
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();
Expand Down Expand Up @@ -23983,6 +24193,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 0].mType = ASMIT_LDA;
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)
{
const NativeCodeInstruction* ains, *iins;
Expand Down
2 changes: 2 additions & 0 deletions oscar64/NativeCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct NativeRegisterData
void ResetMask(void);

bool SameData(const NativeRegisterData& d) const;
bool SameData(const NativeCodeInstruction& ins) const;
};

struct NativeRegisterDataSet
Expand Down Expand Up @@ -320,6 +321,7 @@ class NativeCodeBasicBlock
bool ReplaceXRegWithYReg(int start, int end);
bool MoveASLMemUp(int start);
bool CombineImmediateADCUp(int at);
bool CombineImmediateADCUpX(int at);

bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
Expand Down

0 comments on commit 6014018

Please sign in to comment.