diff --git a/include/c64/sprites.c b/include/c64/sprites.c index aaa7572..b88bc9d 100644 --- a/include/c64/sprites.c +++ b/include/c64/sprites.c @@ -69,6 +69,21 @@ void spr_move(char sp, int xpos, int ypos) vic.spr_msbx &= ~(1 << sp); } +void spr_move16(char sp, int xpos, int ypos) +{ + __assume (sp < 8); + + if (ypos < 0 || ypos >= 256 || xpos < 0 || xpos >= 512) + ypos = 0; + + vic.spr_pos[sp].y = ypos; + vic.spr_pos[sp].x = xpos & 0xff; + if (xpos & 0x100) + vic.spr_msbx |= 1 << sp; + else + vic.spr_msbx &= ~(1 << sp); +} + void spr_image(char sp, char image) { __assume (sp < 8); diff --git a/include/c64/sprites.h b/include/c64/sprites.h index 433b7d7..d0d1a1e 100644 --- a/include/c64/sprites.h +++ b/include/c64/sprites.h @@ -15,10 +15,13 @@ void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, boo inline void spr_show(char sp, bool show); -// move a sprite the +// move a sprite to the given position, only uses 8 bit y and 9 bit x inline void spr_move(char sp, int xpos, int ypos); +// move a sprite to the given position +void spr_move16(char sp, int xpos, int ypos); + // change the image of a sprite inline void spr_image(char sp, char image); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index b9daee3..f8fb96f 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -22,6 +22,7 @@ enum ErrorID EWARN_SYNTAX, EWARN_NOT_INTERRUPT_SAFE, EWARN_BOOL_SHORTCUT, + EWARN_OPTIMIZER_LOCKED, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 4171b0d..cd97d66 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -372,10 +372,27 @@ void ValueSet::FlushCallAliases(const GrowingInstructionPtrArray& tvalue, const } } -static bool CollidingMem(const InterOperand& op1, const InterOperand& op2) +static bool CollidingMem(const InterOperand& op1, const InterOperand& op2, const GrowingVariableArray& staticVars) { if (op1.mMemory != op2.mMemory) - return op1.mMemory == IM_INDIRECT || op2.mMemory == IM_INDIRECT; + { + if (op1.mMemory == IM_INDIRECT) + { + if (op2.mMemory == IM_GLOBAL) + return staticVars[op2.mVarIndex]->mAliased; + else + return true; + } + else if (op2.mMemory == IM_INDIRECT) + { + if (op1.mMemory == IM_GLOBAL) + return staticVars[op1.mVarIndex]->mAliased; + else + return true; + } + else + return false; + } switch (op1.mMemory) { @@ -400,12 +417,12 @@ static bool CollidingMem(const InterOperand& op1, const InterOperand& op2) } } -static bool CollidingMem(const InterOperand& op, const InterInstruction* ins) +static bool CollidingMem(const InterOperand& op, const InterInstruction* ins, const GrowingVariableArray& staticVars) { if (ins->mCode == IC_LOAD) - return CollidingMem(op, ins->mSrc[0]); + return CollidingMem(op, ins->mSrc[0], staticVars); else if (ins->mCode == IC_STORE) - return CollidingMem(op, ins->mSrc[1]); + return CollidingMem(op, ins->mSrc[1], staticVars); else return false; } @@ -3558,7 +3575,8 @@ void InterInstruction::Disassemble(FILE* file) InterCodeBasicBlock::InterCodeBasicBlock(void) : mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mMergeAValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mLoopPrefix(nullptr), mDominator(nullptr), - mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mReverseValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr) + mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), + mReverseValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr), mMemoryValueSize(0), mEntryMemoryValueSize(0) { mInPath = false; mLoopHead = false; @@ -4583,7 +4601,7 @@ void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, } } -bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps) +bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars) { bool changed = false; @@ -4635,8 +4653,8 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray j = 0; for(int k=0; kmSrc[0], ins->mSrc[1]) && - !CollidingMem(ltemps[k]->mSrc[1], ins->mSrc[1])) + if (!CollidingMem(ltemps[k]->mSrc[0], ins->mSrc[1], staticVars) && + !CollidingMem(ltemps[k]->mSrc[1], ins->mSrc[1], staticVars)) { ltemps[j++] = ltemps[k]; } @@ -4657,8 +4675,8 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray j = 0; for (int k = 0; k < ltemps.Size(); k++) { - if (!CollidingMem(ltemps[k]->mSrc[0], ins->mSrc[1]) && - !CollidingMem(ltemps[k]->mSrc[1], ins->mSrc[1])) + if (!CollidingMem(ltemps[k]->mSrc[0], ins->mSrc[1], staticVars) && + !CollidingMem(ltemps[k]->mSrc[1], ins->mSrc[1], staticVars)) { ltemps[j++] = ltemps[k]; } @@ -4670,9 +4688,9 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray } - if (mTrueJump && mTrueJump->PropagateVariableCopy(ltemps)) + if (mTrueJump && mTrueJump->PropagateVariableCopy(ltemps, staticVars)) changed = true; - if (mFalseJump && mFalseJump->PropagateVariableCopy(ltemps)) + if (mFalseJump && mFalseJump->PropagateVariableCopy(ltemps, staticVars)) changed = true; } @@ -4985,6 +5003,15 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial) if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size()) return changed; + if (mTrueJump && !mFalseJump) + { + for (int i = 0; i < mEntryMemoryValueSize.Size(); i++) + { + if (mEntryMemoryValueSize[i] != mTrueJump->mMemoryValueSize[i]) + changed = true; + } + } + if (!mVisited || changed) { mVisited = true; @@ -4994,6 +5021,7 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial) mEntryValueRange = mLocalValueRange; UpdateLocalIntegerRangeSets(); + } if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets(initial)) @@ -5547,27 +5575,33 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) #if 1 mReverseValueRange.SetSize(mLocalValueRange.Size()); - GrowingArray msize(0); - msize.SetSize(mLocalValueRange.Size()); for (int i = 0; i < mReverseValueRange.Size(); i++) mReverseValueRange[i].Reset(); + if (mTrueJump && !mFalseJump) + { + for (int i = 0; i < mMemoryValueSize.Size(); i++) + { + mEntryMemoryValueSize[i] = mMemoryValueSize[i] = mTrueJump->mMemoryValueSize[i]; + } + } + for (int i = sz - 1; i >= 0; i--) { InterInstruction* ins(mInstructions[i]); if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT && ins->mSrc[0].mTemp >= 0) - msize[ins->mSrc[0].mTemp] = int64max(msize[ins->mSrc[0].mTemp], ins->mSrc[0].mIntConst + InterTypeSize[ins->mDst.mType]); + mMemoryValueSize[ins->mSrc[0].mTemp] = int64max(mMemoryValueSize[ins->mSrc[0].mTemp], ins->mSrc[0].mIntConst + InterTypeSize[ins->mDst.mType]); else if (ins->mCode == IC_STORE && ins->mSrc[1].mMemory == IM_INDIRECT && ins->mSrc[1].mTemp >= 0) - msize[ins->mSrc[1].mTemp] = int64max(msize[ins->mSrc[1].mTemp], ins->mSrc[1].mIntConst + InterTypeSize[ins->mSrc[0].mType]); + mMemoryValueSize[ins->mSrc[1].mTemp] = int64max(mMemoryValueSize[ins->mSrc[1].mTemp], ins->mSrc[1].mIntConst + InterTypeSize[ins->mSrc[0].mType]); else if (ins->mCode == IC_COPY) { if (ins->mSrc[0].mMemory == IM_INDIRECT && ins->mSrc[0].mTemp >= 0) - msize[ins->mSrc[0].mTemp] = ins->mConst.mOperandSize; + mMemoryValueSize[ins->mSrc[0].mTemp] = ins->mConst.mOperandSize; if (ins->mSrc[1].mMemory == IM_INDIRECT && ins->mSrc[1].mTemp >= 0) - msize[ins->mSrc[1].mTemp] = ins->mConst.mOperandSize; + mMemoryValueSize[ins->mSrc[1].mTemp] = ins->mConst.mOperandSize; } - else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory != IM_INDIRECT && ins->mSrc[0].mTemp >= 0 && msize[ins->mDst.mTemp] > 0) + else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory != IM_INDIRECT && ins->mSrc[0].mTemp >= 0 && mMemoryValueSize[ins->mDst.mTemp] > 0) { int asize = 0; if (ins->mSrc[1].mMemory == IM_GLOBAL) @@ -5576,7 +5610,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) if (asize > 0) { mReverseValueRange[ins->mSrc[0].mTemp].LimitMin(0); - mReverseValueRange[ins->mSrc[0].mTemp].LimitMax(asize - msize[ins->mDst.mTemp]); + mReverseValueRange[ins->mSrc[0].mTemp].LimitMax(asize - mMemoryValueSize[ins->mDst.mTemp]); } } @@ -5588,6 +5622,16 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) switch (ins->mCode) { + case IC_CONVERSION_OPERATOR: + switch (ins->mOperator) + { + case IA_EXT8TO16U: + case IA_EXT8TO16S: + if (ins->mSrc[0].mTemp >= 0) + mReverseValueRange[ins->mSrc[0].mTemp].Limit(vr); + break; + } + break; case IC_BINARY_OPERATOR: switch (ins->mOperator) { @@ -5666,15 +5710,15 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) break; case IC_LEA: - if (ins->mSrc[1].mMemory == IM_INDIRECT && msize[ins->mDst.mTemp] > 0) + if (ins->mSrc[1].mMemory == IM_INDIRECT && mMemoryValueSize[ins->mDst.mTemp] > 0) { if (ins->mSrc[0].mTemp < 0) { - msize[ins->mSrc[1].mTemp] = msize[ins->mDst.mTemp] - ins->mSrc[0].mIntConst; + mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mIntConst; } else if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND) { - msize[ins->mSrc[1].mTemp] = msize[ins->mDst.mTemp] - ins->mSrc[0].mRange.mMinValue; + mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mRange.mMinValue; } } break; @@ -5689,7 +5733,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) } if (ins->mDst.mTemp >= 0) - msize[ins->mDst.mTemp] = 0; + mMemoryValueSize[ins->mDst.mTemp] = 0; } #endif @@ -5916,6 +5960,8 @@ void InterCodeBasicBlock::BuildLocalIntegerRangeSets(int num) mTrueValueRange.SetSize(num, true); mFalseValueRange.SetSize(num, true); mLocalValueRange.SetSize(num, true); + mMemoryValueSize.SetSize(num, true); + mEntryMemoryValueSize.SetSize(num, true); UpdateLocalIntegerRangeSets(); @@ -6330,7 +6376,6 @@ void InterCodeBasicBlock::PerformTempForwarding(TempForwardingTable& forwardingT bool InterCodeBasicBlock::BuildGlobalRequiredTempSet(NumberSet& fromRequiredTemps) { bool revisit = false; - int i; if (!mVisited) { @@ -6575,7 +6620,6 @@ void InterCodeBasicBlock::BuildGlobalProvidedVariableSet(const GrowingVariableAr bool InterCodeBasicBlock::BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars, const GrowingVariableArray& params, NumberSet& fromRequiredParams, InterMemory paramMemory) { bool revisit = false; - int i; if (!mVisited) { @@ -7451,7 +7495,7 @@ static int Find(GrowingIntArray& table, int i) return j; } -bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& tvalue) +bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars) { bool changed = false; @@ -7551,7 +7595,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& j = 0; while (j < mLoadStoreInstructions.Size()) { - if (!CollidingMem(ins->mSrc[1], mLoadStoreInstructions[j])) + if (!CollidingMem(ins->mSrc[1], mLoadStoreInstructions[j], staticVars)) mLoadStoreInstructions[k++] = mLoadStoreInstructions[j]; j++; } @@ -7608,9 +7652,9 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& mLoadStoreInstructions.Push(nins); } - if (mTrueJump && mTrueJump->LoadStoreForwarding(mLoadStoreInstructions)) + if (mTrueJump && mTrueJump->LoadStoreForwarding(mLoadStoreInstructions, staticVars)) changed = true; - if (mFalseJump && mFalseJump->LoadStoreForwarding(mLoadStoreInstructions)) + if (mFalseJump && mFalseJump->LoadStoreForwarding(mLoadStoreInstructions, staticVars)) changed = true; } @@ -9175,7 +9219,7 @@ void InterCodeBasicBlock::SingleBlockLoopUnrolling(void) } -void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedParams) +void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars) { if (!mVisited) { @@ -9206,7 +9250,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa { // Find the last store that overlaps the load int j = mInstructions.Size() - 1; - while (j > i && !(mInstructions[j]->mCode == IC_STORE && CollidingMem(ins->mSrc[0], mInstructions[j]->mSrc[1]))) + while (j > i && !(mInstructions[j]->mCode == IC_STORE && CollidingMem(ins->mSrc[0], mInstructions[j]->mSrc[1], staticVars))) j--; if (j > i) @@ -9295,7 +9339,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa for (int j = 0; j < mInstructions.Size(); j++) { InterInstruction* sins = mInstructions[j]; - if (sins->mCode == IC_STORE) + if (sins->mCode == IC_STORE && CollidingMem(ins->mSrc[0], sins->mSrc[1], staticVars)) { if (sins->mSrc[1].mTemp >= 0) { @@ -9319,7 +9363,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa ins->mInvariant = false; } } - else if (CollidingMem(ins->mSrc[0], sins->mSrc[1])) + else if (CollidingMem(ins->mSrc[0], sins->mSrc[1], staticVars)) { ins->mInvariant = false; } @@ -9708,9 +9752,9 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa } if (mTrueJump) - mTrueJump->SingleBlockLoopOptimisation(aliasedParams); + mTrueJump->SingleBlockLoopOptimisation(aliasedParams, staticVars); if (mFalseJump) - mFalseJump->SingleBlockLoopOptimisation(aliasedParams); + mFalseJump->SingleBlockLoopOptimisation(aliasedParams, staticVars); } } @@ -11190,7 +11234,7 @@ void InterCodeProcedure::Close(void) RemoveUnusedInstructions(); ResetVisited(); - mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet); + mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); DisassembleDebug("single block loop opt"); @@ -11280,7 +11324,7 @@ void InterCodeProcedure::Close(void) { GrowingInstructionPtrArray cipa(nullptr); ResetVisited(); - changed = mEntryBlock->PropagateVariableCopy(cipa); + changed = mEntryBlock->PropagateVariableCopy(cipa, mModule->mGlobalVars); RemoveUnusedStoreInstructions(paramMemory); } while (changed); @@ -11290,7 +11334,7 @@ void InterCodeProcedure::Close(void) do { GrowingInstructionPtrArray gipa(nullptr); ResetVisited(); - changed = mEntryBlock->LoadStoreForwarding(gipa); + changed = mEntryBlock->LoadStoreForwarding(gipa, mModule->mGlobalVars); DisassembleDebug("Load/Store forwardingX"); @@ -11492,7 +11536,7 @@ void InterCodeProcedure::Close(void) do { GrowingInstructionPtrArray gipa(nullptr); ResetVisited(); - changed = mEntryBlock->LoadStoreForwarding(gipa); + changed = mEntryBlock->LoadStoreForwarding(gipa, mModule->mGlobalVars); RemoveUnusedStoreInstructions(paramMemory); @@ -11510,7 +11554,7 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); ResetVisited(); - mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet); + mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); DisassembleDebug("single block loop opt 2"); @@ -11538,7 +11582,7 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); ResetVisited(); - mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet); + mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); DisassembleDebug("single block loop opt 3"); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 30b9213..75a5ec4 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -355,6 +355,7 @@ public: GrowingInstructionArray mLoadStoreInstructions; GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange, mReverseValueRange; + GrowingArray mMemoryValueSize, mEntryMemoryValueSize; GrowingArray mEntryBlocks, mLoopPathBlocks; @@ -383,7 +384,7 @@ public: void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps); bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); - bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps); + bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars); void BuildLocalTempSets(int num); void BuildGlobalProvidedTempSet(NumberSet fromProvidedTemps); @@ -412,7 +413,7 @@ public: GrowingIntArray mEntryRenameTable; GrowingIntArray mExitRenameTable; - bool LoadStoreForwarding(const GrowingInstructionPtrArray& tvalue); + bool LoadStoreForwarding(const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars); void LocalRenameRegister(const GrowingIntArray& renameTable, int& num); void BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable); @@ -464,7 +465,7 @@ public: bool MergeCommonPathInstructions(void); void PeepholeOptimization(const GrowingVariableArray& staticVars); - void SingleBlockLoopOptimisation(const NumberSet& aliasedParams); + void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); void SingleBlockLoopUnrolling(void); bool CollectLoopBody(InterCodeBasicBlock* head, GrowingArray & body); void CollectLoopPath(const GrowingArray& body, GrowingArray& path); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index e0be57a..b6220a9 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -2944,7 +2944,9 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE) { #if 1 - if (data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode == NRDM_UNKNOWN && mAddress >= BC_REG_FPARAMS && mAddress < BC_REG_FPARAMS_END) + if (data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode == NRDM_UNKNOWN && + (mAddress >= BC_REG_FPARAMS && mAddress < BC_REG_FPARAMS_END) && + !(data.mRegs[CPU_REG_A].mValue >= BC_REG_FPARAMS && data.mRegs[CPU_REG_A].mValue < BC_REG_FPARAMS_END)) { data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode = NRDM_ZERO_PAGE; data.mRegs[data.mRegs[CPU_REG_A].mValue].mValue = mAddress; @@ -9670,7 +9672,7 @@ void NativeCodeBasicBlock::LoadStoreOpAbsolute2D(InterCodeProcedure* proc, const } else { - for (int i = 0; i < InterTypeSize[mins->mSrc[0].mType]; i++) + for (int i = 0; i < InterTypeSize[mins->mDst.mType]; i++) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, lins1->mSrc[1].mIntConst + i, lins1->mSrc[1].mLinkerObject)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[mins->mDst.mTemp] + i)); @@ -16442,6 +16444,33 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo mNDataSet.mRegs[CPU_REG_C].Reset(); mNDataSet.mRegs[CPU_REG_Z].Reset(); + bool loopx = false, loopy = false; + int loopya, loopxa; + + if (mIns.Size() > 2) + { + int sz = mIns.Size(); + + if ((mIns[sz - 2].mType == ASMIT_LDY || mIns[sz - 2].mType == ASMIT_STY) && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE) + { + if (mNDataSet.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && mIns[sz - 2].mAddress == mNDataSet.mRegs[CPU_REG_Y].mValue || + mNDataSet.mRegs[CPU_REG_Y].SameData(mNDataSet.mRegs[mIns[sz - 2].mAddress])) + { + loopya = mIns[sz - 2].mAddress; + loopy = true; + } + } + else if ((mIns[sz - 2].mType == ASMIT_LDX || mIns[sz - 2].mType == ASMIT_STX) && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE) + { + if (mNDataSet.mRegs[CPU_REG_X].mMode == NRDM_ZERO_PAGE && mIns[sz - 2].mAddress == mNDataSet.mRegs[CPU_REG_X].mValue || + mNDataSet.mRegs[CPU_REG_X].SameData(mNDataSet.mRegs[mIns[sz - 2].mAddress])) + { + loopxa = mIns[sz - 2].mAddress; + loopx = true; + } + } + } + // Single block loop for (int i = 0; i < mIns.Size(); i++) { @@ -16452,6 +16481,7 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo mNDataSet.mRegs[CPU_REG_X].Reset(); if (ins.ChangesYReg()) mNDataSet.mRegs[CPU_REG_Y].Reset(); + if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress()) mNDataSet.ResetZeroPage(ins.mAddress); if (ins.mType == ASMIT_JSR) @@ -16476,6 +16506,19 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo // break; } } + + if (loopy) + { + mNDataSet.mRegs[CPU_REG_Y].mMode = NRDM_ZERO_PAGE; + mNDataSet.mRegs[CPU_REG_Y].mValue = loopya; + } + if (loopx) + { + mNDataSet.mRegs[CPU_REG_X].mMode = NRDM_ZERO_PAGE; + mNDataSet.mRegs[CPU_REG_X].mValue = loopxa; + } + + } else #endif @@ -25108,6 +25151,11 @@ void NativeCodeProcedure::Optimize(void) #endif + if (cnt > 200) + { + changed = false; + mGenerator->mErrors->Error(mInterProc->mLocation, EWARN_OPTIMIZER_LOCKED, "Optimizer locked in infinite loop", mInterProc->mIdent); + } #if 1 if (!changed && step < 8) { diff --git a/samples/memmap/charsetload.d64 b/samples/memmap/charsetload.d64 index ae07601..02a24d0 100644 Binary files a/samples/memmap/charsetload.d64 and b/samples/memmap/charsetload.d64 differ