Add unroll pragma for simple loops
This commit is contained in:
parent
350403121d
commit
fdcaf54666
|
@ -106,6 +106,12 @@ inline int lmul8f8s(int x, int y)
|
|||
return (int)(lmul16s(x, y) >> 8);
|
||||
}
|
||||
|
||||
inline unsigned long lsqr4f12s(int x)
|
||||
{
|
||||
if (x < 0) x = -x;
|
||||
return lmul16u(x, x);
|
||||
}
|
||||
|
||||
int lmul4f12s(int x, int y)
|
||||
{
|
||||
__asm
|
||||
|
|
|
@ -10,12 +10,16 @@ __native long lmul16s(int x, int y)
|
|||
// Multiply two 12.4 fixpoint numbers and return a 12.4 fixpoint result
|
||||
inline int lmul12f4s(int x, int y);
|
||||
|
||||
|
||||
// Multiply two 8.8 fixpoint numbers and return an 8.8 fixpoint result
|
||||
inline int lmul8f8s(int x, int y);
|
||||
|
||||
// Multiply two 4.12 fixpoint numbers and return a 12.4 fixpoint result
|
||||
__native int lmul4f12s(int x, int y)
|
||||
|
||||
// Square of a 4.12 sigend fixpoint number and return an 8.24 fixpoint result
|
||||
inline unsigned long lsqr4f12s(int x);
|
||||
|
||||
// Divide a 32bit unsigned number by a 16bit number and return a 16bit number
|
||||
__native unsigned ldiv16u(unsigned long x, unsigned y)
|
||||
|
||||
|
|
|
@ -94,6 +94,21 @@ Expression::~Expression(void)
|
|||
|
||||
}
|
||||
|
||||
bool Expression::IsSame(const Expression* exp) const
|
||||
{
|
||||
if (!exp || mType != exp->mType)
|
||||
return false;
|
||||
|
||||
switch (mType)
|
||||
{
|
||||
case EX_VARIABLE:
|
||||
return mDecValue == exp->mDecValue;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Expression* Expression::LogicInvertExpression(void)
|
||||
{
|
||||
if (mType == EX_LOGICAL_NOT)
|
||||
|
|
|
@ -164,6 +164,8 @@ public:
|
|||
|
||||
Expression* LogicInvertExpression(void);
|
||||
Expression* ConstantFold(Errors * errors);
|
||||
|
||||
bool IsSame(const Expression* exp) const;
|
||||
};
|
||||
|
||||
class Declaration
|
||||
|
|
|
@ -6875,6 +6875,103 @@ bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray&
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
GrowingInstructionPtrArray ltvalue(tvalue);
|
||||
|
||||
if (mNumEntries > 1)
|
||||
ltvalue.Clear();
|
||||
|
||||
mVisited = true;
|
||||
|
||||
// Move lea to front
|
||||
|
||||
for (int i = 0; i < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
|
||||
if (ins->mCode == IC_LEA)
|
||||
{
|
||||
int j = i;
|
||||
while (j > 0 && CanBypassUp(ins, mInstructions[j - 1]))
|
||||
{
|
||||
mInstructions[j] = mInstructions[j - 1];
|
||||
j--;
|
||||
}
|
||||
mInstructions[j] = ins;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
|
||||
if (ins->mCode == IC_STORE || ins->mCode == IC_LOAD)
|
||||
{
|
||||
int pi = ins->mCode == IC_LOAD ? 0 : 1;
|
||||
|
||||
if (ins->mSrc[pi].mTemp >= 0 && ltvalue[ins->mSrc[pi].mTemp])
|
||||
{
|
||||
InterInstruction* lins = ltvalue[ins->mSrc[pi].mTemp];
|
||||
|
||||
if (lins->mSrc[0].mTemp >= 0)
|
||||
{
|
||||
InterInstruction* bins = lins;
|
||||
|
||||
for (int j = 0; j < ltvalue.Size(); j++)
|
||||
{
|
||||
InterInstruction* cins = ltvalue[j];
|
||||
if (cins &&
|
||||
cins->mSrc[0].mTemp == bins->mSrc[0].mTemp &&
|
||||
cins->mSrc[1].mTemp < 0 && bins->mSrc[1].mTemp < 0 &&
|
||||
cins->mSrc[1].mMemory == bins->mSrc[1].mMemory &&
|
||||
cins->mSrc[1].mVarIndex == bins->mSrc[1].mVarIndex &&
|
||||
cins->mSrc[1].mIntConst < bins->mSrc[1].mIntConst &&
|
||||
cins->mSrc[1].mMemory != IM_ABSOLUTE)
|
||||
|
||||
bins = cins;
|
||||
}
|
||||
|
||||
if (bins != lins && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst < 252)
|
||||
{
|
||||
ins->mSrc[pi].mTemp = bins->mDst.mTemp;
|
||||
ins->mSrc[pi].mIntConst += lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dtemp = ins->mDst.mTemp;
|
||||
|
||||
if (dtemp >= 0)
|
||||
{
|
||||
|
||||
for (int i = 0; i < ltvalue.Size(); i++)
|
||||
{
|
||||
if (ltvalue[i] && ltvalue[i]->ReferencesTemp(dtemp))
|
||||
ltvalue[i] = nullptr;
|
||||
}
|
||||
|
||||
if (!ins->UsesTemp(dtemp))
|
||||
ltvalue[dtemp] = ins;
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->MergeIndexedLoadStore(ltvalue))
|
||||
changed = true;
|
||||
|
||||
if (mFalseJump && mFalseJump->MergeIndexedLoadStore(ltvalue))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps)
|
||||
{
|
||||
bool changed = false;
|
||||
|
@ -7142,6 +7239,22 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
|
|||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if 1
|
||||
case IC_LOAD:
|
||||
if (ins->mSrc[0].mTemp >= 0 && ltvalue[ins->mSrc[0].mTemp])
|
||||
{
|
||||
InterInstruction* pins = ltvalue[ins->mSrc[0].mTemp];
|
||||
|
||||
if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
ins->mSrc[0].Forward(pins->mSrc[1]);
|
||||
pins->mSrc[1].mFinal = false;
|
||||
ins->mSrc[0].mIntConst += pins->mSrc[0].mIntConst;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -9922,6 +10035,19 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
|||
ains->mSrc[0].mTemp = -1;
|
||||
ains->mSrc[0].mIntConst = indexStep[ins->mSrc[0].mTemp];
|
||||
|
||||
if (tailBlock->mEntryRequiredTemps[ains->mDst.mTemp])
|
||||
{
|
||||
InterInstruction* dins = new InterInstruction();
|
||||
dins->mCode = IC_LEA;
|
||||
dins->mDst = ins->mDst;
|
||||
dins->mSrc[1] = ins->mDst;
|
||||
dins->mSrc[1].mMemory = IM_INDIRECT;
|
||||
dins->mSrc[1].mIntConst = 0;
|
||||
dins->mSrc[0].mType = IT_INT16;
|
||||
dins->mSrc[0].mTemp = -1;
|
||||
dins->mSrc[0].mIntConst = - indexStep[ins->mSrc[0].mTemp];
|
||||
tailBlock->mInstructions.Insert(0, dins);
|
||||
}
|
||||
indexins.Push(ains);
|
||||
}
|
||||
}
|
||||
|
@ -11515,6 +11641,25 @@ void InterCodeProcedure::PromoteSimpleLocalsToTemp(InterMemory paramMemory, int
|
|||
mEntryBlock->CompactInstructions();
|
||||
}
|
||||
|
||||
void InterCodeProcedure::MergeIndexedLoadStore(void)
|
||||
{
|
||||
GrowingInstructionPtrArray silvalues(nullptr);
|
||||
|
||||
do
|
||||
{
|
||||
BuildDataFlowSets();
|
||||
|
||||
TempForwarding();
|
||||
RemoveUnusedInstructions();
|
||||
|
||||
silvalues.SetSize(mTemporaries.Size(), true);
|
||||
|
||||
ResetVisited();
|
||||
} while (mEntryBlock->MergeIndexedLoadStore(silvalues));
|
||||
|
||||
DisassembleDebug("MergeIndexedLoadStore");
|
||||
}
|
||||
|
||||
void InterCodeProcedure::SimplifyIntegerNumeric(FastNumberSet& activeSet)
|
||||
{
|
||||
GrowingInstructionPtrArray silvalues(nullptr);
|
||||
|
@ -11738,6 +11883,8 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
DisassembleDebug("interval compare");
|
||||
|
||||
MergeIndexedLoadStore();
|
||||
|
||||
BuildDataFlowSets();
|
||||
|
||||
ResetVisited();
|
||||
|
@ -11760,6 +11907,10 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
BuildDataFlowSets();
|
||||
|
||||
RenameTemporaries();
|
||||
|
||||
BuildDataFlowSets();
|
||||
|
||||
ResetEntryBlocks();
|
||||
ResetVisited();
|
||||
mEntryBlock->CollectEntryBlocks(nullptr);
|
||||
|
|
|
@ -428,6 +428,7 @@ public:
|
|||
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars);
|
||||
bool EliminateDeadBranches(void);
|
||||
|
||||
bool MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue);
|
||||
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
|
||||
bool EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue);
|
||||
|
||||
|
@ -563,6 +564,7 @@ protected:
|
|||
void PushSinglePathResultInstructions(void);
|
||||
void PromoteSimpleLocalsToTemp(InterMemory paramMemory, int nlocals, int nparams);
|
||||
void SimplifyIntegerNumeric(FastNumberSet& activeSet);
|
||||
void MergeIndexedLoadStore(void);
|
||||
void EliminateAliasValues();
|
||||
void LoadStoreForwarding(InterMemory paramMemory);
|
||||
|
||||
|
|
|
@ -901,8 +901,18 @@ bool NativeCodeInstruction::ChangesZeroPage(int address) const
|
|||
{
|
||||
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
|
||||
return true;
|
||||
if (address >= BC_REG_TMP && address < BC_REG_TMP_SAVED)
|
||||
return true;
|
||||
|
||||
if (mLinkerObject && mLinkerObject->mProc)
|
||||
{
|
||||
if (address >= BC_REG_TMP && address < BC_REG_TMP + mLinkerObject->mProc->mCallerSavedTemps)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (address >= BC_REG_TMP && address < BC_REG_TMP_SAVED)
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -941,6 +951,9 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const
|
|||
}
|
||||
else
|
||||
{
|
||||
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
|
||||
return true;
|
||||
|
||||
if (mLinkerObject)
|
||||
{
|
||||
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++)
|
||||
|
@ -2293,8 +2306,17 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
|
||||
if (!(mFlags & NCIF_RUNTIME) || (mFlags & NCIF_FEXEC))
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
|
||||
data.ResetZeroPage(i);
|
||||
if (mLinkerObject && mLinkerObject->mProc)
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP + mLinkerObject->mProc->mCallerSavedTemps; i++)
|
||||
data.ResetZeroPage(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
|
||||
data.ResetZeroPage(i);
|
||||
}
|
||||
|
||||
for(int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
|
||||
data.ResetZeroPage(i);
|
||||
}
|
||||
|
@ -7166,6 +7188,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
int shift = ins->mSrc[0].mIntConst & 31;
|
||||
|
||||
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
int nregs = 4;
|
||||
|
||||
if (shift >= 24)
|
||||
{
|
||||
|
@ -7177,6 +7200,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
sreg = treg;
|
||||
shift -= 24;
|
||||
nregs = 1;
|
||||
}
|
||||
else if (shift >= 16)
|
||||
{
|
||||
|
@ -7189,6 +7213,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
sreg = treg;
|
||||
shift -= 16;
|
||||
nregs = 2;
|
||||
}
|
||||
else if (shift >= 8)
|
||||
{
|
||||
|
@ -7203,6 +7228,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
sreg = treg;
|
||||
shift -= 8;
|
||||
nregs = 3;
|
||||
}
|
||||
|
||||
if (shift == 0)
|
||||
|
@ -7258,21 +7284,24 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
}
|
||||
else
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1));
|
||||
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
||||
this->Close(lblock, nullptr, ASMIT_JMP);
|
||||
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
||||
for(int i=nregs -1; i>0 ; i--)
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1));
|
||||
|
||||
// lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
||||
// lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
||||
lblock->Close(lblock, eblock, ASMIT_BNE);
|
||||
|
||||
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
||||
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + nregs - 1));
|
||||
return eblock;
|
||||
}
|
||||
}
|
||||
|
@ -12339,7 +12368,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
|||
}
|
||||
}
|
||||
|
||||
if (mFalseJump->mNumEntries == 1 && mTrueJump->mNumEntries == 2 && mFalseJump->mIns.Size() == 0)
|
||||
if (mFalseJump->mNumEntries == 1/* && mTrueJump->mNumEntries == 2*/ && mFalseJump->mIns.Size() == 0)
|
||||
{
|
||||
if (mFalseJump->mBranch == ASMIT_BCC)
|
||||
{
|
||||
|
@ -12393,7 +12422,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
|||
}
|
||||
}
|
||||
|
||||
if (mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 2 && mTrueJump->mIns.Size() == 0)
|
||||
if (mTrueJump->mNumEntries == 1/* && mFalseJump->mNumEntries == 2*/ && mTrueJump->mIns.Size() == 0)
|
||||
{
|
||||
if (mTrueJump->mBranch == ASMIT_BCC)
|
||||
{
|
||||
|
@ -13351,6 +13380,43 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mEntryBlocks.Size() >= 1)
|
||||
{
|
||||
NativeCodeBasicBlock* eb = mEntryBlocks[0];
|
||||
|
||||
if (eb->mIns.Size())
|
||||
{
|
||||
NativeCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
||||
if (ins.mType == ASMIT_STA && ins.mMode == ASMIM_ZERO_PAGE &&
|
||||
(eb->mBranch == ASMIT_JMP ||
|
||||
eb->mTrueJump == this && eb->mFalseJump && !eb->mFalseJump->mEntryRequiredRegs[ins.mAddress] ||
|
||||
eb->mFalseJump == this && eb->mTrueJump && !eb->mTrueJump->mEntryRequiredRegs[ins.mAddress]))
|
||||
{
|
||||
int i = 1;
|
||||
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mIns.Size() > 0 && mEntryBlocks[i]->mIns.Last().IsSame(ins) &&
|
||||
(mEntryBlocks[i]->mBranch == ASMIT_JMP ||
|
||||
mEntryBlocks[i]->mTrueJump == this && mEntryBlocks[i]->mFalseJump && !mEntryBlocks[i]->mFalseJump->mEntryRequiredRegs[ins.mAddress] ||
|
||||
mEntryBlocks[i]->mFalseJump == this && mEntryBlocks[i]->mTrueJump && !mEntryBlocks[i]->mTrueJump->mEntryRequiredRegs[ins.mAddress]))
|
||||
i++;
|
||||
if (i == mEntryBlocks.Size())
|
||||
{
|
||||
mEntryRequiredRegs += CPU_REG_A;
|
||||
mEntryRequiredRegs -= ins.mAddress;
|
||||
|
||||
mIns.Insert(0, ins);
|
||||
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||
{
|
||||
NativeCodeBasicBlock* meb = mEntryBlocks[i];
|
||||
meb->mExitRequiredRegs += CPU_REG_A;
|
||||
meb->mIns.SetSize(meb->mIns.Size() - 1);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mEntryBlocks.Size() > 2)
|
||||
{
|
||||
|
@ -14388,6 +14454,41 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i
|
|||
|
||||
return flags != 0;
|
||||
}
|
||||
else if (
|
||||
mIns[j + 1].mType == ASMIT_CLC &&
|
||||
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_LOWER) && mIns[j + 2].mLinkerObject &&
|
||||
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
||||
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE && mIns[j + 4].mAddress == 0 &&
|
||||
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 5].mFlags & NCIF_UPPER) && mIns[j + 5].mLinkerObject == mIns[j + 2].mLinkerObject &&
|
||||
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
||||
{
|
||||
ains = &(mIns[j + 2]);
|
||||
iins = nullptr;
|
||||
apos = j + 1;
|
||||
|
||||
if (!direct)
|
||||
return false;
|
||||
|
||||
flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive;
|
||||
|
||||
if (mIns[j + 0].mType == ASMIT_TAX)
|
||||
flags |= LIVE_CPU_REG_X;
|
||||
if (mIns[j + 0].mType == ASMIT_TAY)
|
||||
flags |= LIVE_CPU_REG_Y;
|
||||
|
||||
int k = j + 7;
|
||||
while (k < at)
|
||||
{
|
||||
assert(!(flags & LIVE_CPU_REG_Y) || mIns[k].mType != ASMIT_TYA);
|
||||
if (mIns[k].ChangesYReg())
|
||||
flags &= ~LIVE_CPU_REG_Y;
|
||||
if (mIns[k].ChangesXReg())
|
||||
flags &= ~LIVE_CPU_REG_X;
|
||||
k++;
|
||||
}
|
||||
|
||||
return flags != 0;
|
||||
}
|
||||
else if (mIns[j + 0].mType == ASMIT_CLC &&
|
||||
mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_IMMEDIATE &&
|
||||
|
@ -15093,6 +15194,59 @@ bool NativeCodeBasicBlock::PatchAddressSumY(int at, int reg, int apos, int breg,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::FindBypassAddressSumY(int at, int reg, int& apos, int& breg)
|
||||
{
|
||||
int j = at - 6;
|
||||
while (j >= 0)
|
||||
{
|
||||
if (
|
||||
mIns[j + 0].mType == ASMIT_CLC &&
|
||||
mIns[j + 1].mType == ASMIT_ADC && mIns[j + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[j + 2].mType == ASMIT_STA && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && mIns[j + 2].mAddress == reg &&
|
||||
mIns[j + 3].mType == ASMIT_LDA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == mIns[j + 1].mAddress + 1 &&
|
||||
mIns[j + 4].mType == ASMIT_ADC && mIns[j + 4].mMode == ASMIM_IMMEDIATE && mIns[j + 4].mAddress == 0 &&
|
||||
mIns[j + 5].mType == ASMIT_STA && mIns[j + 5].mMode == ASMIM_ZERO_PAGE && mIns[j + 5].mAddress == reg + 1)
|
||||
{
|
||||
breg = mIns[j + 1].mAddress;
|
||||
int k = j + 6;
|
||||
while (k < at)
|
||||
{
|
||||
if (mIns[k].ChangesZeroPage(breg) || mIns[k].ChangesZeroPage(breg + 1))
|
||||
return false;
|
||||
|
||||
k++;
|
||||
}
|
||||
|
||||
apos = j;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mIns[j + 5].ReferencesZeroPage(reg) || mIns[j + 5].ReferencesZeroPage(reg + 1))
|
||||
return false;
|
||||
|
||||
j--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::PatchBypassAddressSumY(int at, int reg, int apos, int breg)
|
||||
{
|
||||
mIns[apos + 0].mType = ASMIT_NOP; mIns[apos + 0].mMode = ASMIM_IMPLIED;
|
||||
mIns[apos + 1].mType = ASMIT_NOP; mIns[apos + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[apos + 3].mType = ASMIT_NOP; mIns[apos + 3].mMode = ASMIM_IMPLIED;
|
||||
mIns[apos + 4].mType = ASMIT_NOP; mIns[apos + 4].mMode = ASMIM_IMPLIED;
|
||||
mIns[apos + 5].mType = ASMIT_NOP; mIns[apos + 5].mMode = ASMIM_IMPLIED;
|
||||
|
||||
mIns[at + 0].mMode = ASMIM_ZERO_PAGE;
|
||||
mIns[at + 0].mAddress = reg;
|
||||
mIns[at + 1].mAddress = breg;
|
||||
mIns[at + 1].mLive |= LIVE_MEM;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int& breg)
|
||||
{
|
||||
int j = at - 6;
|
||||
|
@ -15713,6 +15867,30 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::ReplaceZeroPageDown(int at)
|
||||
{
|
||||
int i = at + 2;
|
||||
while (i < mIns.Size())
|
||||
{
|
||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[at].mAddress)
|
||||
{
|
||||
mIns[at + 1].mLive |= mIns[i].mLive;
|
||||
mIns.Insert(i + 1, mIns[at + 1]);
|
||||
mIns.Remove(at, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mIns[i].ChangesZeroPage(mIns[at].mAddress))
|
||||
return false;
|
||||
if (mIns[i].ReferencesZeroPage(mIns[at + 1].mAddress))
|
||||
return false;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::ReplaceZeroPageUp(int at)
|
||||
{
|
||||
int i = at - 1;
|
||||
|
@ -15749,6 +15927,374 @@ bool NativeCodeBasicBlock::ReplaceZeroPageUp(int at)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction& lins, const NativeCodeInstruction& sins)
|
||||
{
|
||||
if (!mPatched)
|
||||
{
|
||||
mPatched = true;
|
||||
|
||||
if (at == -2)
|
||||
{
|
||||
for (int i = 0; i < mIns.Size(); i++)
|
||||
{
|
||||
if (mIns[i].ChangesZeroPage(lins.mAddress))
|
||||
return false;
|
||||
if (mIns[i].ReferencesZeroPage(sins.mAddress))
|
||||
return false;
|
||||
}
|
||||
|
||||
at = mIns.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (at == -1)
|
||||
at = mIns.Size();
|
||||
|
||||
int i = at;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == lins.mAddress)
|
||||
{
|
||||
while (i < at)
|
||||
{
|
||||
if (mIns[i].mAddress == lins.mAddress)
|
||||
mIns[i].mAddress = sins.mAddress;
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mIns[i].ChangesZeroPage(lins.mAddress))
|
||||
return false;
|
||||
else if (mIns[i].mMode == ASMIM_ZERO_PAGE && !mIns[i].ChangesAddress() && mIns[i].mAddress == lins.mAddress)
|
||||
;
|
||||
else if (mIns[i].ReferencesZeroPage(sins.mAddress))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int pat = -1;
|
||||
NativeCodeBasicBlock* eb = nullptr;
|
||||
|
||||
if (mEntryBlocks.Size() == 1 || mEntryBlocks.Size() == 2 && mEntryBlocks[1] == this)
|
||||
{
|
||||
eb = mEntryBlocks[0];
|
||||
if (!eb->mFalseJump)
|
||||
;
|
||||
else if (eb->mTrueJump == eb || eb->mFalseJump == eb)
|
||||
pat = -2;
|
||||
else if (eb->mFalseJump->mPatched && eb->mTrueJump->mPatched)
|
||||
;
|
||||
else if (
|
||||
eb->mTrueJump == this && !eb->mFalseJump->mEntryRequiredRegs[lins.mAddress] && !eb->mFalseJump->mEntryRequiredRegs[sins.mAddress] ||
|
||||
eb->mFalseJump == this && !eb->mTrueJump->mEntryRequiredRegs[lins.mAddress] && !eb->mTrueJump->mEntryRequiredRegs[sins.mAddress])
|
||||
;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (mEntryBlocks.Size() == 2)
|
||||
{
|
||||
NativeCodeBasicBlock* eb0 = mEntryBlocks[0];
|
||||
NativeCodeBasicBlock* eb1 = mEntryBlocks[1];
|
||||
|
||||
if (eb0->mEntryBlocks.Size() == 1 && eb0->mEntryBlocks[0] == eb1)
|
||||
eb = eb0;
|
||||
else if (eb1->mEntryBlocks.Size() == 1 && eb1->mEntryBlocks[0] == eb0)
|
||||
eb = eb1;
|
||||
else
|
||||
return false;
|
||||
|
||||
pat = -2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (!eb->MoveZeroPageCrossBlockUp(pat, lins, sins))
|
||||
return false;
|
||||
|
||||
for(int i=0; i<at; i++)
|
||||
{
|
||||
if (mIns[i].mAddress == lins.mAddress)
|
||||
mIns[i].mAddress = sins.mAddress;
|
||||
}
|
||||
|
||||
mEntryRequiredRegs += lins.mAddress;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NativeCodeBasicBlock::ShortcutCrossBlockMoves(NativeCodeProcedure* proc)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (!mLoopHead)
|
||||
{
|
||||
int i = 0;
|
||||
while (i + 1 < mIns.Size())
|
||||
{
|
||||
if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 0].mLive & LIVE_MEM) &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
|
||||
{
|
||||
proc->ResetPatched();
|
||||
if (MoveZeroPageCrossBlockUp(i, mIns[i + 0], mIns[i + 1]))
|
||||
{
|
||||
changed = true;
|
||||
mIns.Remove(i, 2);
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
CheckLive();
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->ShortcutCrossBlockMoves(proc))
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->ShortcutCrossBlockMoves(proc))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::Check16BitSum(int at, NativeRegisterSum16Info& info)
|
||||
{
|
||||
if (at + 6 < mIns.Size())
|
||||
{
|
||||
if (mIns[at + 0].mType == ASMIT_CLC &&
|
||||
mIns[at + 1].mType == ASMIT_LDA &&
|
||||
mIns[at + 2].mType == ASMIT_ADC &&
|
||||
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[at + 4].mType == ASMIT_LDA &&
|
||||
mIns[at + 5].mType == ASMIT_ADC &&
|
||||
mIns[at + 6].mType == ASMIT_STA && mIns[at + 6].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
info.mDstL = &(mIns[at + 3]);
|
||||
info.mDstH = &(mIns[at + 6]);
|
||||
|
||||
if (mIns[at + 2].mMode == ASMIM_ZERO_PAGE && (mIns[at + 5].mMode == ASMIM_ZERO_PAGE || mIns[at + 5].mMode == ASMIM_IMMEDIATE && mIns[at + 5].mAddress == 0))
|
||||
{
|
||||
if (mIns[at + 1].mMode == ASMIM_IMMEDIATE && mIns[at + 4].mMode == ASMIM_IMMEDIATE)
|
||||
{
|
||||
info.mAddress = (mIns[at + 1].mAddress & 0xff) + (mIns[at + 4].mAddress << 8);
|
||||
info.mLinkerObject = nullptr;
|
||||
info.mSrcL = &(mIns[at + 2]);
|
||||
info.mSrcH = &(mIns[at + 5]);
|
||||
info.mAddL = &(mIns[at + 1]);
|
||||
info.mAddH = &(mIns[at + 4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (mIns[at + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 1].mLinkerObject == mIns[at + 4].mLinkerObject && mIns[at + 1].mAddress == mIns[at + 4].mAddress)
|
||||
{
|
||||
info.mAddress = mIns[at + 1].mAddress;
|
||||
info.mLinkerObject = mIns[at + 1].mLinkerObject;
|
||||
info.mSrcL = &(mIns[at + 2]);
|
||||
info.mSrcH = &(mIns[at + 5]);
|
||||
info.mAddL = &(mIns[at + 1]);
|
||||
info.mAddH = &(mIns[at + 4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (mIns[at + 1].mMode == ASMIM_ZERO_PAGE && (mIns[at + 4].mMode == ASMIM_ZERO_PAGE || mIns[at + 4].mMode == ASMIM_IMMEDIATE && mIns[at + 4].mAddress == 0))
|
||||
{
|
||||
if (mIns[at + 2].mMode == ASMIM_IMMEDIATE && mIns[at + 5].mMode == ASMIM_IMMEDIATE)
|
||||
{
|
||||
info.mAddress = (mIns[at + 2].mAddress & 0xff) + (mIns[at + 5].mAddress << 8);
|
||||
info.mLinkerObject = nullptr;
|
||||
info.mSrcL = &(mIns[at + 1]);
|
||||
info.mSrcH = &(mIns[at + 4]);
|
||||
info.mAddL = &(mIns[at + 2]);
|
||||
info.mAddH = &(mIns[at + 5]);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (mIns[at + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 5].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 2].mLinkerObject == mIns[at + 5].mLinkerObject && mIns[at + 2].mAddress == mIns[at + 5].mAddress)
|
||||
{
|
||||
info.mAddress = mIns[at + 2].mAddress;
|
||||
info.mLinkerObject = mIns[at + 2].mLinkerObject;
|
||||
info.mSrcL = &(mIns[at + 1]);
|
||||
info.mSrcH = &(mIns[at + 4]);
|
||||
info.mAddL = &(mIns[at + 2]);
|
||||
info.mAddH = &(mIns[at + 5]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mIns[at + 0].mType == ASMIT_LDA &&
|
||||
mIns[at + 1].mType == ASMIT_CLC &&
|
||||
mIns[at + 2].mType == ASMIT_ADC &&
|
||||
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[at + 4].mType == ASMIT_LDA &&
|
||||
mIns[at + 5].mType == ASMIT_ADC &&
|
||||
mIns[at + 6].mType == ASMIT_STA && mIns[at + 6].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
info.mDstL = &(mIns[at + 3]);
|
||||
info.mDstH = &(mIns[at + 6]);
|
||||
|
||||
if (mIns[at + 2].mMode == ASMIM_ZERO_PAGE && mIns[at + 5].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
if (mIns[at + 0].mMode == ASMIM_IMMEDIATE && mIns[at + 4].mMode == ASMIM_IMMEDIATE)
|
||||
{
|
||||
info.mAddress = (mIns[at + 0].mAddress & 0xff) + (mIns[at + 4].mAddress << 8);
|
||||
info.mLinkerObject = nullptr;
|
||||
info.mSrcL = &(mIns[at + 2]);
|
||||
info.mSrcH = &(mIns[at + 5]);
|
||||
info.mAddL = &(mIns[at + 0]);
|
||||
info.mAddH = &(mIns[at + 4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (mIns[at + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 0].mLinkerObject == mIns[at + 4].mLinkerObject && mIns[at + 0].mAddress == mIns[at + 4].mAddress)
|
||||
{
|
||||
info.mAddress = mIns[at + 0].mAddress;
|
||||
info.mLinkerObject = mIns[at + 0].mLinkerObject;
|
||||
info.mSrcL = &(mIns[at + 2]);
|
||||
info.mSrcH = &(mIns[at + 5]);
|
||||
info.mAddL = &(mIns[at + 0]);
|
||||
info.mAddH = &(mIns[at + 4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (mIns[at + 0].mMode == ASMIM_ZERO_PAGE && mIns[at + 4].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
if (mIns[at + 2].mMode == ASMIM_IMMEDIATE && mIns[at + 5].mMode == ASMIM_IMMEDIATE)
|
||||
{
|
||||
info.mAddress = (mIns[at + 2].mAddress & 0xff) + (mIns[at + 5].mAddress << 8);
|
||||
info.mLinkerObject = nullptr;
|
||||
info.mSrcL = &(mIns[at + 0]);
|
||||
info.mSrcH = &(mIns[at + 4]);
|
||||
info.mAddL = &(mIns[at + 2]);
|
||||
info.mAddH = &(mIns[at + 5]);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (mIns[at + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 5].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[at + 2].mLinkerObject == mIns[at + 5].mLinkerObject && mIns[at + 2].mAddress == mIns[at + 5].mAddress)
|
||||
{
|
||||
info.mAddress = mIns[at + 2].mAddress;
|
||||
info.mLinkerObject = mIns[at + 2].mLinkerObject;
|
||||
info.mSrcL = &(mIns[at + 0]);
|
||||
info.mSrcH = &(mIns[at + 4]);
|
||||
info.mAddL = &(mIns[at + 2]);
|
||||
info.mAddH = &(mIns[at + 5]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::Propagate16BitSum(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
GrowingArray<NativeRegisterSum16Info> infos(NativeRegisterSum16Info{});
|
||||
|
||||
for (int i = 0; i < mIns.Size(); i++)
|
||||
{
|
||||
NativeRegisterSum16Info info;
|
||||
|
||||
if (Check16BitSum(i, info))
|
||||
{
|
||||
for (int j = 0; j < infos.Size(); j++)
|
||||
{
|
||||
if (info.mSrcL->mAddress == infos[j].mDstL->mAddress && info.mSrcH->mAddress == infos[j].mDstH->mAddress)
|
||||
{
|
||||
if (!info.mLinkerObject && !infos[j].mLinkerObject)
|
||||
{
|
||||
info.mAddress += infos[j].mAddress;
|
||||
info.mAddL->mAddress = info.mAddress & 0xff;
|
||||
info.mAddH->mAddress = info.mAddress >> 8;
|
||||
info.mSrcL->mAddress = infos[j].mSrcL->mAddress;
|
||||
info.mSrcH->mAddress = infos[j].mSrcH->mAddress;
|
||||
info.mSrcH->mMode = infos[j].mSrcH->mMode;
|
||||
changed = true;
|
||||
}
|
||||
else if (!infos[j].mLinkerObject)
|
||||
{
|
||||
info.mAddress += infos[j].mAddress;
|
||||
info.mAddL->mAddress = info.mAddress;
|
||||
info.mAddH->mAddress = info.mAddress;
|
||||
info.mSrcL->mAddress = infos[j].mSrcL->mAddress;
|
||||
info.mSrcH->mAddress = infos[j].mSrcH->mAddress;
|
||||
info.mSrcH->mMode = infos[j].mSrcH->mMode;
|
||||
changed = true;
|
||||
}
|
||||
else if (!info.mLinkerObject)
|
||||
{
|
||||
info.mAddress += infos[j].mAddress;
|
||||
info.mLinkerObject = infos[j].mLinkerObject;
|
||||
info.mAddL->mAddress = info.mAddress;
|
||||
info.mAddL->mLinkerObject = info.mLinkerObject;
|
||||
info.mAddL->mMode = ASMIM_IMMEDIATE_ADDRESS;
|
||||
info.mAddL->mFlags = NCIF_LOWER;
|
||||
info.mAddH->mAddress = info.mAddress;
|
||||
info.mAddH->mLinkerObject = info.mLinkerObject;
|
||||
info.mAddH->mMode = ASMIM_IMMEDIATE_ADDRESS;
|
||||
info.mAddH->mFlags = NCIF_UPPER;
|
||||
info.mSrcL->mAddress = infos[j].mSrcL->mAddress;
|
||||
info.mSrcH->mAddress = infos[j].mSrcH->mAddress;
|
||||
info.mSrcH->mMode = infos[j].mSrcH->mMode;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.mSrcL->mAddress != info.mDstL->mAddress && (info.mSrcH->mMode == ASMIM_IMMEDIATE || info.mSrcH->mAddress != info.mDstH->mAddress))
|
||||
infos.Push(info);
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
while (j < infos.Size())
|
||||
{
|
||||
if (infos[j].mDstL != &(mIns[i]) && infos[j].mDstH != &(mIns[i]))
|
||||
{
|
||||
if (
|
||||
infos[j].mSrcL->MayBeChangedOnAddress(mIns[i]) ||
|
||||
infos[j].mSrcH->MayBeChangedOnAddress(mIns[i]) ||
|
||||
infos[j].mDstL->MayBeChangedOnAddress(mIns[i]) ||
|
||||
infos[j].mDstH->MayBeChangedOnAddress(mIns[i]))
|
||||
{
|
||||
infos.Remove(j);
|
||||
}
|
||||
else
|
||||
j++;
|
||||
}
|
||||
else
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->Propagate16BitSum())
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->Propagate16BitSum())
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
bool NativeCodeBasicBlock::MoveLoadXUp(int at)
|
||||
{
|
||||
|
@ -16605,8 +17151,17 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
|
|||
|
||||
if (!(ins.mFlags & NCIF_RUNTIME) || (ins.mFlags & NCIF_FEXEC))
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
|
||||
mNDataSet.ResetZeroPage(i);
|
||||
if (ins.mLinkerObject && ins.mLinkerObject->mProc)
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP + ins.mLinkerObject->mProc->mCallerSavedTemps; i++)
|
||||
mNDataSet.ResetZeroPage(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
|
||||
mNDataSet.ResetZeroPage(i);
|
||||
}
|
||||
|
||||
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
|
||||
mNDataSet.ResetZeroPage(i);
|
||||
}
|
||||
|
@ -20388,6 +20943,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
CheckLive();
|
||||
#endif
|
||||
|
||||
if (pass > 1)
|
||||
{
|
||||
#if 1
|
||||
// replace zero page down
|
||||
|
||||
for (int i = 1; i + 1 < mIns.Size(); i++)
|
||||
{
|
||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && (mIns[i + 0].mLive & LIVE_MEM))
|
||||
{
|
||||
if (ReplaceZeroPageDown(i))
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
CheckLive();
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
CheckLive();
|
||||
|
@ -23822,7 +24394,17 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 && !(mIns[i + 1].mLive & (LIVE_MEM | LIVE_CPU_REG_Y)))
|
||||
{
|
||||
int apos, breg;
|
||||
if (FindBypassAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
|
||||
{
|
||||
if (PatchBypassAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO))
|
||||
{
|
||||
int apos, breg;
|
||||
|
@ -25267,6 +25849,12 @@ void NativeCodeProcedure::Optimize(void)
|
|||
NativeRegisterDataSet data;
|
||||
if (mEntryBlock->ValueForwarding(data, step > 0, step == 7))
|
||||
changed = true;
|
||||
else
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->Propagate16BitSum())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
} while (changed);
|
||||
#endif
|
||||
|
@ -25330,6 +25918,16 @@ void NativeCodeProcedure::Optimize(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
if (step > 4 && !changed)
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->ShortcutCrossBlockMoves(this))
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
if (step > 2 && !changed)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
class NativeCodeProcedure;
|
||||
class NativeCodeBasicBlock;
|
||||
class NativeCodeGenerator;
|
||||
class NativeCodeInstruction;
|
||||
|
||||
enum NativeRegisterDataMode
|
||||
{
|
||||
|
@ -46,6 +47,14 @@ struct NativeRegisterDataSet
|
|||
void IntersectMask(const NativeRegisterDataSet& set);
|
||||
};
|
||||
|
||||
struct NativeRegisterSum16Info
|
||||
{
|
||||
NativeCodeInstruction * mSrcL, * mSrcH, * mDstL, * mDstH, * mAddL, * mAddH;
|
||||
|
||||
int mAddress;
|
||||
LinkerObject * mLinkerObject;
|
||||
};
|
||||
|
||||
|
||||
static const uint32 NCIF_LOWER = 0x00000001;
|
||||
static const uint32 NCIF_UPPER = 0x00000002;
|
||||
|
@ -278,6 +287,8 @@ public:
|
|||
bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags, int & addr);
|
||||
bool FindExternAddressSumY(int at, int reg, int& breg, int& ireg);
|
||||
bool FindPageStartAddress(int at, int reg, int& addr);
|
||||
bool FindBypassAddressSumY(int at, int reg, int& apos, int& breg);
|
||||
bool PatchBypassAddressSumY(int at, int reg, int apos, int breg);
|
||||
bool MoveStoreXUp(int at);
|
||||
bool MoveLoadXUp(int at);
|
||||
bool MoveStoreYUp(int at);
|
||||
|
@ -286,10 +297,14 @@ public:
|
|||
bool MoveAddHighByteDown(int at);
|
||||
bool ReverseLoadCommutativeOpUp(int aload, int aop);
|
||||
bool ReplaceZeroPageUp(int at);
|
||||
bool ReplaceZeroPageDown(int at);
|
||||
bool ReplaceYRegWithXReg(int start, int end);
|
||||
bool ReplaceXRegWithYReg(int start, int end);
|
||||
bool MoveASLMemUp(int start);
|
||||
|
||||
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
|
||||
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
|
||||
|
||||
bool CanReplaceYRegWithXReg(int start, int end);
|
||||
bool CanReplaceXRegWithYReg(int start, int end);
|
||||
|
||||
|
@ -324,6 +339,9 @@ public:
|
|||
bool HasTailSTA(int& addr, int& index) const;
|
||||
bool PropagateSinglePath(void);
|
||||
|
||||
bool Check16BitSum(int at, NativeRegisterSum16Info& info);
|
||||
bool Propagate16BitSum(void);
|
||||
|
||||
NativeRegisterDataSet mEntryRegisterDataSet;
|
||||
|
||||
void BuildEntryDataSet(const NativeRegisterDataSet& set);
|
||||
|
|
|
@ -13,6 +13,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
|
|||
mDataSection = compilationUnits->mSectionData;
|
||||
mBSSection = compilationUnits->mSectionBSS;
|
||||
|
||||
mUnrollLoop = 0;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
mCharMap[i] = i;
|
||||
}
|
||||
|
@ -2017,6 +2019,12 @@ Expression* Parser::ParseStatement(void)
|
|||
{
|
||||
Expression* exp = nullptr;
|
||||
|
||||
while (mScanner->mToken == TK_PREP_PRAGMA)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
ParsePragma();
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
{
|
||||
DeclarationScope* scope = new DeclarationScope(mScope);
|
||||
|
@ -2111,12 +2119,16 @@ Expression* Parser::ParseStatement(void)
|
|||
|
||||
mScanner->NextToken();
|
||||
exp = new Expression(mScanner->mLocation, EX_FOR);
|
||||
exp->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
exp->mLeft->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
|
||||
int unrollLoop = mUnrollLoop;
|
||||
mUnrollLoop = 0;
|
||||
|
||||
Expression* initExp = nullptr, * iterateExp = nullptr, * conditionExp = nullptr, * bodyExp = nullptr, * finalExp = nullptr;
|
||||
|
||||
|
||||
// Assignment
|
||||
if (mScanner->mToken != TK_SEMICOLON)
|
||||
exp->mLeft->mRight = ParseExpression();
|
||||
initExp = ParseExpression();
|
||||
if (mScanner->mToken == TK_SEMICOLON)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
|
@ -2124,7 +2136,8 @@ Expression* Parser::ParseStatement(void)
|
|||
|
||||
// Condition
|
||||
if (mScanner->mToken != TK_SEMICOLON)
|
||||
exp->mLeft->mLeft->mLeft = ParseExpression();
|
||||
conditionExp = ParseExpression();
|
||||
|
||||
if (mScanner->mToken == TK_SEMICOLON)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
|
@ -2132,12 +2145,83 @@ Expression* Parser::ParseStatement(void)
|
|||
|
||||
// Iteration
|
||||
if (mScanner->mToken != TK_CLOSE_PARENTHESIS)
|
||||
exp->mLeft->mLeft->mRight = ParseExpression();
|
||||
iterateExp = ParseExpression();
|
||||
if (mScanner->mToken == TK_CLOSE_PARENTHESIS)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "')' expected");
|
||||
exp->mRight = ParseStatement();
|
||||
bodyExp = ParseStatement();
|
||||
|
||||
exp->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
exp->mLeft->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
|
||||
if (unrollLoop > 1 && initExp && iterateExp && conditionExp)
|
||||
{
|
||||
if ((initExp->mType == EX_ASSIGNMENT || initExp->mType == EX_INITIALIZATION) && initExp->mLeft->mType == EX_VARIABLE && initExp->mRight->mType == EX_CONSTANT &&
|
||||
(iterateExp->mType == EX_POSTINCDEC || iterateExp->mType == EX_PREINCDEC) && iterateExp->mLeft->IsSame(initExp->mLeft) &&
|
||||
conditionExp->mType == EX_RELATIONAL && conditionExp->mToken == TK_LESS_THAN && conditionExp->mLeft->IsSame(initExp->mLeft) && conditionExp->mRight->mType == EX_CONSTANT)
|
||||
{
|
||||
if (initExp->mRight->mDecValue->mType == DT_CONST_INTEGER && conditionExp->mRight->mDecValue->mType == DT_CONST_INTEGER)
|
||||
{
|
||||
int startValue = initExp->mRight->mDecValue->mInteger;
|
||||
int endValue = conditionExp->mRight->mDecValue->mInteger;
|
||||
|
||||
int remain = (endValue - startValue) % unrollLoop;
|
||||
endValue -= remain;
|
||||
|
||||
conditionExp->mRight->mDecValue->mInteger = endValue;
|
||||
|
||||
Expression * unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
unrollBody->mLeft = bodyExp;
|
||||
Expression* bexp = unrollBody;
|
||||
if (endValue > startValue)
|
||||
{
|
||||
for (int i = 1; i < unrollLoop; i++)
|
||||
{
|
||||
bexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
bexp = bexp->mRight;
|
||||
bexp->mLeft = iterateExp;
|
||||
bexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
bexp = bexp->mRight;
|
||||
bexp->mLeft = bodyExp;
|
||||
}
|
||||
}
|
||||
|
||||
if (remain)
|
||||
{
|
||||
finalExp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
finalExp->mLeft = bodyExp;
|
||||
Expression* bexp = finalExp;
|
||||
|
||||
for (int i = 1; i < remain; i++)
|
||||
{
|
||||
bexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
bexp = bexp->mRight;
|
||||
bexp->mLeft = iterateExp;
|
||||
bexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
bexp = bexp->mRight;
|
||||
bexp->mLeft = bodyExp;
|
||||
}
|
||||
}
|
||||
|
||||
bodyExp = unrollBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exp->mLeft->mRight = initExp;
|
||||
exp->mLeft->mLeft->mLeft = conditionExp;
|
||||
exp->mLeft->mLeft->mRight = iterateExp;
|
||||
exp->mRight = bodyExp;
|
||||
|
||||
if (finalExp)
|
||||
{
|
||||
Expression* nexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
nexp->mLeft = exp;
|
||||
nexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
nexp->mRight->mLeft = finalExp;
|
||||
exp = nexp;
|
||||
}
|
||||
|
||||
mScope = mScope->mParent;
|
||||
}
|
||||
|
@ -3574,6 +3658,26 @@ void Parser::ParsePragma(void)
|
|||
|
||||
ConsumeToken(TK_CLOSE_PARENTHESIS);
|
||||
}
|
||||
else if (!strcmp(mScanner->mTokenIdent->mString, "unroll"))
|
||||
{
|
||||
mScanner->NextToken();
|
||||
ConsumeToken(TK_OPEN_PARENTHESIS);
|
||||
|
||||
if (mScanner->mToken == TK_INTEGER)
|
||||
{
|
||||
mUnrollLoop = mScanner->mTokenInteger;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else if (mScanner->mToken == TK_IDENT && !strcmp(mScanner->mTokenIdent->mString, "full"))
|
||||
{
|
||||
mUnrollLoop = 0x10000;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer literal expected");
|
||||
|
||||
ConsumeToken(TK_CLOSE_PARENTHESIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
mScanner->NextToken();
|
||||
|
|
|
@ -24,6 +24,7 @@ protected:
|
|||
bool ConsumeTokenIf(Token token);
|
||||
|
||||
char mCharMap[256];
|
||||
int mUnrollLoop;
|
||||
|
||||
uint8* ParseStringLiteral(int msize);
|
||||
|
||||
|
|
|
@ -640,6 +640,12 @@
|
|||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_BFAE73A1432845AB83CAA44F3A7EC9C3"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_C239EFB1C3A646809AD2740ABDE747B0"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
|
@ -3051,6 +3057,26 @@
|
|||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BFAE73A1432845AB83CAA44F3A7EC9C3"
|
||||
{
|
||||
"SourcePath" = "8:..\\samples\\fractals\\mbfixed.c"
|
||||
"TargetName" = "8:mbfixed.c"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_BDDE04AB523C4059AABE326807998F7A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C239EFB1C3A646809AD2740ABDE747B0"
|
||||
{
|
||||
"SourcePath" = "8:..\\include\\c64\\types.h"
|
||||
|
@ -4128,7 +4154,7 @@
|
|||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{4AC1A78B-6BCA-4D2F-A54D-DEA5F627B017}"
|
||||
"PackageCode" = "8:{AA95DD46-0812-483A-92A4-D1A34E57D713}"
|
||||
"PackageCode" = "8:{ED70C89A-F338-434F-9FB2-90C1BD8EB020}"
|
||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||
"AspNetVersion" = "8:2.0.50727.0"
|
||||
"RestartWWWService" = "11:FALSE"
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
../../bin/oscar64 mbhires.c -n
|
||||
../../bin/oscar64 mbmulti.c -n
|
||||
../../bin/oscar64 mbmulti3d.c -n
|
||||
../../bin/oscar64 mbfixed.c -n -O3
|
||||
|
||||
|
|
|
@ -2,4 +2,4 @@ call ..\..\bin\oscar64 mbtext.c -n
|
|||
call ..\..\bin\oscar64 mbhires.c -n
|
||||
call ..\..\bin\oscar64 mbmulti.c -n
|
||||
call ..\..\bin\oscar64 mbmulti3d.c -n
|
||||
|
||||
call ..\..\bin\oscar64 mbfixed.c -n -O3
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
#include <string.h>
|
||||
#include <c64/vic.h>
|
||||
#include <c64/memmap.h>
|
||||
#include <conio.h>
|
||||
#include <fixmath.h>
|
||||
|
||||
// Address of hires buffer and color buffers
|
||||
#define Screen ((char *)0xe000)
|
||||
#define Color ((char *)0xc800)
|
||||
#define Color2 ((char *)0xd800)
|
||||
|
||||
// Bit patters for eight different color pairs
|
||||
char colors[] = {
|
||||
0xff, 0xff,
|
||||
0xee, 0xbb,
|
||||
0xaa, 0xaa,
|
||||
0x88, 0x22,
|
||||
|
||||
0x44, 0x11,
|
||||
0x55, 0x55,
|
||||
0xdd, 0x77,
|
||||
0x33, 0xcc
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Install the IRQ trampoline
|
||||
mmap_trampoline();
|
||||
|
||||
// Turn of the kernal ROM
|
||||
mmap_set(MMAP_NO_ROM);
|
||||
|
||||
// Switch VIC into multicolor bitmap mode
|
||||
vic_setmode(VICM_HIRES_MC, Color, Screen);
|
||||
|
||||
// Clear the screen and set the colors
|
||||
vic.color_back = 0x00;
|
||||
|
||||
memset(Screen, 0, 8000);
|
||||
memset(Color, 0x27, 1000);
|
||||
memset(Color2, 0x03, 1000);
|
||||
|
||||
// Loop over all pixels
|
||||
int py, px;
|
||||
|
||||
for(py=0; py<100; py++)
|
||||
{
|
||||
for(px=0; px<160; px++)
|
||||
{
|
||||
// Value in the complex plane
|
||||
|
||||
// int xz = (int)(((float)px * (3.5 / 160.0) - 2.5) * 4096 + 0.5);
|
||||
// int yz = (int)(((float)py * (2.4 / 100.0) - 1.2) * 4096 + 0.5);
|
||||
|
||||
int xz = lmul8f8s(px, (int)((3.5 / 160.0) * 4096 * 256)) - (int)(2.5 * 4096);
|
||||
int yz = lmul8f8s(py, (int)((2.4 / 100.0) * 4096 * 256)) - (int)(1.2 * 4096);
|
||||
|
||||
// Iterate up to 32 times
|
||||
int x = 0, y = 0;
|
||||
int i;
|
||||
for(i=0; i<32; i++)
|
||||
{
|
||||
unsigned long xq = lsqr4f12s(x), yq = lsqr4f12s(y);
|
||||
|
||||
if (xq + yq >= 0x04000000UL) break;
|
||||
|
||||
int xt = (int)(xq >> 12) - (int)(yq >> 12) + xz;
|
||||
y = 2 * lmul4f12s(x, y) + yz;
|
||||
x = xt;
|
||||
}
|
||||
|
||||
if (i < 32)
|
||||
{
|
||||
// Position on screen
|
||||
char * dp = Screen + 320 * (py >> 2) + 2 * (py & 3) + 2 * (px & ~3);
|
||||
|
||||
// Mask of pixels to change
|
||||
char mask = 0xc0 >> (2 * (px & 3));
|
||||
|
||||
// Get the two color patterns for upper and lower half
|
||||
char c0 = colors[2 * (i & 7)], c1 = colors[2 * (i & 7) + 1];
|
||||
|
||||
// Put the pixels into the image
|
||||
dp[0] |= c0 & mask;
|
||||
dp[1] |= c1 & mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable the kernal
|
||||
mmap_set(MMAP_NO_BASIC);
|
||||
|
||||
// Wait for key press
|
||||
getch();
|
||||
|
||||
// Restore VIC state
|
||||
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -251,7 +251,7 @@ int main(void)
|
|||
dy += ay;
|
||||
|
||||
// New force
|
||||
if ((rand() & 127) == 0)
|
||||
if ((rand() & 63) == 0)
|
||||
{
|
||||
ax = (rand() & 63) - 32;
|
||||
ay = (rand() & 63) - 32;
|
||||
|
|
Loading…
Reference in New Issue