Add unroll pragma for simple loops

This commit is contained in:
drmortalwombat 2022-06-30 09:33:11 +02:00
parent 350403121d
commit fdcaf54666
15 changed files with 1052 additions and 24 deletions

View File

@ -106,6 +106,12 @@ inline int lmul8f8s(int x, int y)
return (int)(lmul16s(x, y) >> 8); 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) int lmul4f12s(int x, int y)
{ {
__asm __asm

View File

@ -10,12 +10,16 @@ __native long lmul16s(int x, int y)
// Multiply two 12.4 fixpoint numbers and return a 12.4 fixpoint result // Multiply two 12.4 fixpoint numbers and return a 12.4 fixpoint result
inline int lmul12f4s(int x, int y); inline int lmul12f4s(int x, int y);
// Multiply two 8.8 fixpoint numbers and return an 8.8 fixpoint result // Multiply two 8.8 fixpoint numbers and return an 8.8 fixpoint result
inline int lmul8f8s(int x, int y); inline int lmul8f8s(int x, int y);
// Multiply two 4.12 fixpoint numbers and return a 12.4 fixpoint result // Multiply two 4.12 fixpoint numbers and return a 12.4 fixpoint result
__native int lmul4f12s(int x, int y) __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 // Divide a 32bit unsigned number by a 16bit number and return a 16bit number
__native unsigned ldiv16u(unsigned long x, unsigned y) __native unsigned ldiv16u(unsigned long x, unsigned y)

View File

@ -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) Expression* Expression::LogicInvertExpression(void)
{ {
if (mType == EX_LOGICAL_NOT) if (mType == EX_LOGICAL_NOT)

View File

@ -164,6 +164,8 @@ public:
Expression* LogicInvertExpression(void); Expression* LogicInvertExpression(void);
Expression* ConstantFold(Errors * errors); Expression* ConstantFold(Errors * errors);
bool IsSame(const Expression* exp) const;
}; };
class Declaration class Declaration

View File

@ -6875,6 +6875,103 @@ bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray&
return changed; 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 InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps)
{ {
bool changed = false; bool changed = false;
@ -7142,6 +7239,22 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
} }
} }
break; 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 #endif
} }
@ -9922,6 +10035,19 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
ains->mSrc[0].mTemp = -1; ains->mSrc[0].mTemp = -1;
ains->mSrc[0].mIntConst = indexStep[ins->mSrc[0].mTemp]; 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); indexins.Push(ains);
} }
} }
@ -11515,6 +11641,25 @@ void InterCodeProcedure::PromoteSimpleLocalsToTemp(InterMemory paramMemory, int
mEntryBlock->CompactInstructions(); 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) void InterCodeProcedure::SimplifyIntegerNumeric(FastNumberSet& activeSet)
{ {
GrowingInstructionPtrArray silvalues(nullptr); GrowingInstructionPtrArray silvalues(nullptr);
@ -11738,6 +11883,8 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("interval compare"); DisassembleDebug("interval compare");
MergeIndexedLoadStore();
BuildDataFlowSets(); BuildDataFlowSets();
ResetVisited(); ResetVisited();
@ -11760,6 +11907,10 @@ void InterCodeProcedure::Close(void)
BuildDataFlowSets(); BuildDataFlowSets();
RenameTemporaries();
BuildDataFlowSets();
ResetEntryBlocks(); ResetEntryBlocks();
ResetVisited(); ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr); mEntryBlock->CollectEntryBlocks(nullptr);

View File

@ -428,6 +428,7 @@ public:
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars); void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars);
bool EliminateDeadBranches(void); bool EliminateDeadBranches(void);
bool MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue);
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps); bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
bool EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue); bool EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue);
@ -563,6 +564,7 @@ protected:
void PushSinglePathResultInstructions(void); void PushSinglePathResultInstructions(void);
void PromoteSimpleLocalsToTemp(InterMemory paramMemory, int nlocals, int nparams); void PromoteSimpleLocalsToTemp(InterMemory paramMemory, int nlocals, int nparams);
void SimplifyIntegerNumeric(FastNumberSet& activeSet); void SimplifyIntegerNumeric(FastNumberSet& activeSet);
void MergeIndexedLoadStore(void);
void EliminateAliasValues(); void EliminateAliasValues();
void LoadStoreForwarding(InterMemory paramMemory); void LoadStoreForwarding(InterMemory paramMemory);

View File

@ -901,8 +901,18 @@ bool NativeCodeInstruction::ChangesZeroPage(int address) const
{ {
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END) if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
return true; 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; return false;
@ -941,6 +951,9 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const
} }
else else
{ {
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
return true;
if (mLinkerObject) if (mLinkerObject)
{ {
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++) 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)) if (!(mFlags & NCIF_RUNTIME) || (mFlags & NCIF_FEXEC))
{ {
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++) if (mLinkerObject && mLinkerObject->mProc)
data.ResetZeroPage(i); {
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++) for(int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
data.ResetZeroPage(i); data.ResetZeroPage(i);
} }
@ -7166,6 +7188,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int shift = ins->mSrc[0].mIntConst & 31; int shift = ins->mSrc[0].mIntConst & 31;
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
int nregs = 4;
if (shift >= 24) if (shift >= 24)
{ {
@ -7177,6 +7200,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg; sreg = treg;
shift -= 24; shift -= 24;
nregs = 1;
} }
else if (shift >= 16) else if (shift >= 16)
{ {
@ -7189,6 +7213,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg; sreg = treg;
shift -= 16; shift -= 16;
nregs = 2;
} }
else if (shift >= 8) else if (shift >= 8)
{ {
@ -7203,6 +7228,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg; sreg = treg;
shift -= 8; shift -= 8;
nregs = 3;
} }
if (shift == 0) 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_LDA, ASMIM_ZERO_PAGE, sreg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 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_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)); mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, shift));
this->Close(lblock, nullptr, ASMIT_JMP); this->Close(lblock, nullptr, ASMIT_JMP);
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2)); for(int i=nregs -1; i>0 ; i--)
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1)); lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1));
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
// 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->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
lblock->Close(lblock, eblock, ASMIT_BNE); 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; 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) 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) 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) if (mEntryBlocks.Size() > 2)
{ {
@ -14388,6 +14454,41 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i
return flags != 0; 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 && else if (mIns[j + 0].mType == ASMIT_CLC &&
mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE && 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 && 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; 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) bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int& breg)
{ {
int j = at - 6; int j = at - 6;
@ -15713,6 +15867,30 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
return false; 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) bool NativeCodeBasicBlock::ReplaceZeroPageUp(int at)
{ {
int i = at - 1; int i = at - 1;
@ -15749,6 +15927,374 @@ bool NativeCodeBasicBlock::ReplaceZeroPageUp(int at)
return false; 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) 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)) if (!(ins.mFlags & NCIF_RUNTIME) || (ins.mFlags & NCIF_FEXEC))
{ {
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++) if (ins.mLinkerObject && ins.mLinkerObject->mProc)
mNDataSet.ResetZeroPage(i); {
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++) for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
mNDataSet.ResetZeroPage(i); mNDataSet.ResetZeroPage(i);
} }
@ -20388,6 +20943,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
CheckLive(); CheckLive();
#endif #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 #endif
CheckLive(); CheckLive();
@ -23822,7 +24394,17 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true; 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)) if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO))
{ {
int apos, breg; int apos, breg;
@ -25267,6 +25849,12 @@ void NativeCodeProcedure::Optimize(void)
NativeRegisterDataSet data; NativeRegisterDataSet data;
if (mEntryBlock->ValueForwarding(data, step > 0, step == 7)) if (mEntryBlock->ValueForwarding(data, step > 0, step == 7))
changed = true; changed = true;
else
{
ResetVisited();
if (mEntryBlock->Propagate16BitSum())
changed = true;
}
} while (changed); } while (changed);
#endif #endif
@ -25330,6 +25918,16 @@ void NativeCodeProcedure::Optimize(void)
} }
#endif #endif
#if 1
if (step > 4 && !changed)
{
ResetVisited();
if (mEntryBlock->ShortcutCrossBlockMoves(this))
changed = true;
}
#endif
#if 1 #if 1
if (step > 2 && !changed) if (step > 2 && !changed)
{ {

View File

@ -7,6 +7,7 @@
class NativeCodeProcedure; class NativeCodeProcedure;
class NativeCodeBasicBlock; class NativeCodeBasicBlock;
class NativeCodeGenerator; class NativeCodeGenerator;
class NativeCodeInstruction;
enum NativeRegisterDataMode enum NativeRegisterDataMode
{ {
@ -46,6 +47,14 @@ struct NativeRegisterDataSet
void IntersectMask(const NativeRegisterDataSet& set); 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_LOWER = 0x00000001;
static const uint32 NCIF_UPPER = 0x00000002; 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 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 FindExternAddressSumY(int at, int reg, int& breg, int& ireg);
bool FindPageStartAddress(int at, int reg, int& addr); 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 MoveStoreXUp(int at);
bool MoveLoadXUp(int at); bool MoveLoadXUp(int at);
bool MoveStoreYUp(int at); bool MoveStoreYUp(int at);
@ -286,10 +297,14 @@ public:
bool MoveAddHighByteDown(int at); bool MoveAddHighByteDown(int at);
bool ReverseLoadCommutativeOpUp(int aload, int aop); bool ReverseLoadCommutativeOpUp(int aload, int aop);
bool ReplaceZeroPageUp(int at); bool ReplaceZeroPageUp(int at);
bool ReplaceZeroPageDown(int at);
bool ReplaceYRegWithXReg(int start, int end); bool ReplaceYRegWithXReg(int start, int end);
bool ReplaceXRegWithYReg(int start, int end); bool ReplaceXRegWithYReg(int start, int end);
bool MoveASLMemUp(int start); 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 CanReplaceYRegWithXReg(int start, int end);
bool CanReplaceXRegWithYReg(int start, int end); bool CanReplaceXRegWithYReg(int start, int end);
@ -324,6 +339,9 @@ public:
bool HasTailSTA(int& addr, int& index) const; bool HasTailSTA(int& addr, int& index) const;
bool PropagateSinglePath(void); bool PropagateSinglePath(void);
bool Check16BitSum(int at, NativeRegisterSum16Info& info);
bool Propagate16BitSum(void);
NativeRegisterDataSet mEntryRegisterDataSet; NativeRegisterDataSet mEntryRegisterDataSet;
void BuildEntryDataSet(const NativeRegisterDataSet& set); void BuildEntryDataSet(const NativeRegisterDataSet& set);

View File

@ -13,6 +13,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
mDataSection = compilationUnits->mSectionData; mDataSection = compilationUnits->mSectionData;
mBSSection = compilationUnits->mSectionBSS; mBSSection = compilationUnits->mSectionBSS;
mUnrollLoop = 0;
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
mCharMap[i] = i; mCharMap[i] = i;
} }
@ -2017,6 +2019,12 @@ Expression* Parser::ParseStatement(void)
{ {
Expression* exp = nullptr; Expression* exp = nullptr;
while (mScanner->mToken == TK_PREP_PRAGMA)
{
mScanner->NextToken();
ParsePragma();
}
if (mScanner->mToken == TK_OPEN_BRACE) if (mScanner->mToken == TK_OPEN_BRACE)
{ {
DeclarationScope* scope = new DeclarationScope(mScope); DeclarationScope* scope = new DeclarationScope(mScope);
@ -2111,12 +2119,16 @@ Expression* Parser::ParseStatement(void)
mScanner->NextToken(); mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_FOR); 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 // Assignment
if (mScanner->mToken != TK_SEMICOLON) if (mScanner->mToken != TK_SEMICOLON)
exp->mLeft->mRight = ParseExpression(); initExp = ParseExpression();
if (mScanner->mToken == TK_SEMICOLON) if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken(); mScanner->NextToken();
else else
@ -2124,7 +2136,8 @@ Expression* Parser::ParseStatement(void)
// Condition // Condition
if (mScanner->mToken != TK_SEMICOLON) if (mScanner->mToken != TK_SEMICOLON)
exp->mLeft->mLeft->mLeft = ParseExpression(); conditionExp = ParseExpression();
if (mScanner->mToken == TK_SEMICOLON) if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken(); mScanner->NextToken();
else else
@ -2132,12 +2145,83 @@ Expression* Parser::ParseStatement(void)
// Iteration // Iteration
if (mScanner->mToken != TK_CLOSE_PARENTHESIS) if (mScanner->mToken != TK_CLOSE_PARENTHESIS)
exp->mLeft->mLeft->mRight = ParseExpression(); iterateExp = ParseExpression();
if (mScanner->mToken == TK_CLOSE_PARENTHESIS) if (mScanner->mToken == TK_CLOSE_PARENTHESIS)
mScanner->NextToken(); mScanner->NextToken();
else else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "')' expected"); 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; mScope = mScope->mParent;
} }
@ -3574,6 +3658,26 @@ void Parser::ParsePragma(void)
ConsumeToken(TK_CLOSE_PARENTHESIS); 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 else
{ {
mScanner->NextToken(); mScanner->NextToken();

View File

@ -24,6 +24,7 @@ protected:
bool ConsumeTokenIf(Token token); bool ConsumeTokenIf(Token token);
char mCharMap[256]; char mCharMap[256];
int mUnrollLoop;
uint8* ParseStringLiteral(int msize); uint8* ParseStringLiteral(int msize);

View File

@ -640,6 +640,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_BFAE73A1432845AB83CAA44F3A7EC9C3"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_C239EFB1C3A646809AD2740ABDE747B0" "MsmKey" = "8:_C239EFB1C3A646809AD2740ABDE747B0"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -3051,6 +3057,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "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" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C239EFB1C3A646809AD2740ABDE747B0"
{ {
"SourcePath" = "8:..\\include\\c64\\types.h" "SourcePath" = "8:..\\include\\c64\\types.h"
@ -4128,7 +4154,7 @@
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{4AC1A78B-6BCA-4D2F-A54D-DEA5F627B017}" "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}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"

View File

@ -3,4 +3,5 @@
../../bin/oscar64 mbhires.c -n ../../bin/oscar64 mbhires.c -n
../../bin/oscar64 mbmulti.c -n ../../bin/oscar64 mbmulti.c -n
../../bin/oscar64 mbmulti3d.c -n ../../bin/oscar64 mbmulti3d.c -n
../../bin/oscar64 mbfixed.c -n -O3

View File

@ -2,4 +2,4 @@ call ..\..\bin\oscar64 mbtext.c -n
call ..\..\bin\oscar64 mbhires.c -n call ..\..\bin\oscar64 mbhires.c -n
call ..\..\bin\oscar64 mbmulti.c -n call ..\..\bin\oscar64 mbmulti.c -n
call ..\..\bin\oscar64 mbmulti3d.c -n call ..\..\bin\oscar64 mbmulti3d.c -n
call ..\..\bin\oscar64 mbfixed.c -n -O3

100
samples/fractals/mbfixed.c Normal file
View File

@ -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;
}

View File

@ -251,7 +251,7 @@ int main(void)
dy += ay; dy += ay;
// New force // New force
if ((rand() & 127) == 0) if ((rand() & 63) == 0)
{ {
ax = (rand() & 63) - 32; ax = (rand() & 63) - 32;
ay = (rand() & 63) - 32; ay = (rand() & 63) - 32;