diff --git a/include/audio/sidfx.c b/include/audio/sidfx.c index bd10ee8..0b63078 100644 --- a/include/audio/sidfx.c +++ b/include/audio/sidfx.c @@ -72,10 +72,10 @@ inline void sidfx_loop_ch(byte ch) sid.voices[ch].ctrl = 0; sid.voices[ch].attdec = 0; sid.voices[ch].susrel = 0; - channels[ch].state = SIDFX_RESET_1; + channels[ch].state = SIDFX_READY; break; case SIDFX_RESET_1: - sid.voices[ch].ctrl = SID_CTRL_TEST; +// sid.voices[ch].ctrl = SID_CTRL_TEST; channels[ch].state = SIDFX_READY; break; case SIDFX_READY: diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d5e7d9d..c60e0af 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -11034,6 +11034,12 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_MUL && ins->mDst.mType == IT_INT16 && spareTemps + 1 < tvalid.Size()) { InterInstruction* mi0 = ltvalue[ins->mSrc[0].mTemp], * mi1 = ltvalue[ins->mSrc[1].mTemp]; + InterInstruction* mci0 = nullptr; + InterInstruction* mci1 = nullptr; + if (mi0 && mi0->mCode == IC_CONVERSION_OPERATOR) + mci0 = ltvalue[mi0->mSrc[0].mTemp]; + if (mi1 && mi1->mCode == IC_CONVERSION_OPERATOR) + mci1 = ltvalue[mi1->mSrc[0].mTemp]; if (mi0 && mi1 && mi1->mCode == IC_CONSTANT && mi0->mCode == IC_BINARY_OPERATOR && mi0->mOperator == IA_ADD) { @@ -11178,6 +11184,41 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra ins->mSrc[0].mTemp = cai->mDst.mTemp; } } +#endif +#if 1 + else if (mi0 && mci1 && mci1->mCode == IC_RELATIONAL_OPERATOR) + { + InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT); + cai->mDst.mTemp = spareTemps++; + cai->mDst.mType = ins->mDst.mType; + cai->mConst.mIntConst = 0; + cai->mConst.mFloatConst = 0; + mInstructions.Insert(i, cai); + + ins->mCode = IC_SELECT; + ins->mNumOperands = 3; + ins->mSrc[2] = mci1->mDst; + ins->mSrc[1] = ins->mSrc[0]; + ins->mSrc[0].mTemp = cai->mDst.mTemp; + + ltvalue[cai->mDst.mTemp] = nullptr; + } + else if (mci0 && mi1 && mci0->mCode == IC_RELATIONAL_OPERATOR) + { + InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT); + cai->mDst.mTemp = spareTemps++; + cai->mDst.mType = ins->mDst.mType; + cai->mConst.mIntConst = 0; + cai->mConst.mFloatConst = 0; + mInstructions.Insert(i, cai); + + ins->mCode = IC_SELECT; + ins->mNumOperands = 3; + ins->mSrc[2] = mci0->mDst; + ins->mSrc[0].mTemp = cai->mDst.mTemp; + + ltvalue[cai->mDst.mTemp] = nullptr; + } #endif } #endif diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index a168f9e..20c1a90 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -1624,6 +1624,12 @@ bool NativeCodeInstruction::IsCommutative(void) const return mType == ASMIT_ADC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR; } +bool NativeCodeInstruction::IsLogic(void) const +{ + return mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR; +} + + bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const { @@ -26516,6 +26522,60 @@ bool NativeCodeBasicBlock::EliminateMicroBlocks(void) return changed; } +bool NativeCodeBasicBlock::CombineAlternateLoads(void) +{ + bool changed = false; + if (!mVisited) + { + mVisited = true; + + if (mTrueJump && mFalseJump && (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS) && + mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 && + mTrueJump->mTrueJump == mFalseJump->mTrueJump && + !mTrueJump->mFalseJump && !mFalseJump->mFalseJump && + mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1) + { + if (mTrueJump->mIns[0].mType == ASMIT_LDA && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && + mFalseJump->mIns[0].mType == ASMIT_LDA && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE) + { + mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C; + mIns.Push(mFalseJump->mIns[0]); + mFalseJump->mIns.Remove(0); + mExitRequiredRegs += CPU_REG_A; + mFalseJump->mEntryRequiredRegs += CPU_REG_A; + changed = true; + } + else if (mTrueJump->mIns[0].mType == ASMIT_LDX && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && + mFalseJump->mIns[0].mType == ASMIT_LDX && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE) + { + mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C; + mIns.Push(mFalseJump->mIns[0]); + mFalseJump->mIns.Remove(0); + mExitRequiredRegs += CPU_REG_X; + mFalseJump->mEntryRequiredRegs += CPU_REG_X; + changed = true; + } + else if (mTrueJump->mIns[0].mType == ASMIT_LDY && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && + mFalseJump->mIns[0].mType == ASMIT_LDY && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE) + { + mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C; + mIns.Push(mFalseJump->mIns[0]); + mFalseJump->mIns.Remove(0); + mExitRequiredRegs += CPU_REG_Y; + mFalseJump->mEntryRequiredRegs += CPU_REG_Y; + changed = true; + } + } + + if (mTrueJump && mTrueJump->CombineAlternateLoads()) + changed = true; + if (mFalseJump && mFalseJump->CombineAlternateLoads()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::FoldLoopEntry(void) { bool changed = false; @@ -33394,6 +33454,58 @@ bool NativeCodeBasicBlock::MoveLoadAddImmStoreAbsXUp(int at) return false; } +bool NativeCodeBasicBlock::MoveLoadLogicStoreAbsUp(int at) +{ + // at + 0 : LDA zp + // at + 1 : ORA zp / imm + // at + 2 : STA abs / abs,x / abs,y + + int j = at - 1; + while (j >= 0) + { + if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress) + { + while (j + 1 < mIns.Size() && mIns[j + 1].mType == ASMIT_STA) + j++; + + if (mIns[j].mLive & LIVE_CPU_REG_A) + return false; + + mIns[j].mLive |= LIVE_CPU_REG_A; + for (int i = j + 1; i < at; i++) + mIns[i].mLive |= LIVE_CPU_REG_C; + + mIns[at + 1].mLive |= mIns[j].mLive; + mIns[at + 2].mLive |= mIns[j].mLive; + + mIns.Insert(j + 1, mIns[at + 2]); // STA + mIns.Insert(j + 1, mIns[at + 2]); // ORA + + mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED; + mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED; + mIns[at + 4].mType = ASMIT_NOP; mIns[at + 4].mMode = ASMIM_IMPLIED; + + return true; + } + + if (mIns[j].ChangesZeroPage(mIns[at + 0].mAddress)) + return false; + if (mIns[at + 1].mType == ASMIM_ZERO_PAGE && mIns[j].ChangesZeroPage(mIns[at + 1].mAddress)) + return false; + + if (mIns[j].UsesMemoryOf(mIns[at + 2])) + return false; + if (mIns[at + 2].mMode == ASMIM_ABSOLUTE_X && mIns[j].ChangesXReg()) + return false; + if (mIns[at + 2].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg()) + return false; + + j--; + } + + return false; +} + bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at) { @@ -42101,6 +42213,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerShuffle(int pass) #endif + +#if 1 + // move load - add # - store up to initial store + // + + for (int i = 1; i + 2 < mIns.Size(); i++) + { + if ( + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].IsLogic() && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && + mIns[i + 2].mType == ASMIT_STA && (mIns[i + 2].mMode == ASMIM_ZERO_PAGE || mIns[i + 2].mMode == ASMIM_ABSOLUTE || mIns[i + 2].mMode == ASMIM_ABSOLUTE_X || mIns[i + 2].mMode == ASMIM_ABSOLUTE_Y) && + (mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0) + { + if (MoveLoadLogicStoreAbsUp(i)) + changed = true; + } + } + CheckLive(); + +#endif + #if 1 // move load - ora/and/eor # - store up to initial store // @@ -47266,6 +47399,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate6(int i, int pass) mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED; return true; } + else if ( + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && + mIns[i + 1].mType == ASMIT_ROL && mIns[i + 1].mMode == ASMIM_IMPLIED && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_LDA && !mIns[i + 3].MayBeSameAddress(mIns[i + 2]) && + mIns[i + 4].mType == ASMIT_ASL && mIns[i + 4].mMode == ASMIM_IMPLIED && + mIns[i + 5].mType == ASMIT_ORA && mIns[i + 5].SameEffectiveAddress(mIns[i + 2]) && !(mIns[i + 5].mLive & LIVE_MEM)) + { + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 4].mType = ASMIT_ROL; + mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED; + return true; + } if (pass == 0 && mIns[i + 0].mType == ASMIT_CLC && @@ -52349,6 +52497,10 @@ void NativeCodeProcedure::Optimize(void) } while (changed); +#if 1 + ResetVisited(); + mEntryBlock->CombineAlternateLoads(); +#endif #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 539098a..439400a 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -198,6 +198,7 @@ public: bool IsSame(const NativeCodeInstruction& ins) const; bool IsSameLS(const NativeCodeInstruction& ins) const; bool IsCommutative(void) const; + bool IsLogic(void) const; bool IsShift(void) const; bool IsShiftOrInc(void) const; bool IsSimpleJSR(void) const; @@ -463,6 +464,8 @@ public: bool MoveTYADCStoreDown(int at); bool MoveShiftZeroPageUp(int at); + bool MoveLoadLogicStoreAbsUp(int at); + bool MoveLDSTXOutOfRange(int at); bool MoveCLCLoadAddZPStoreDown(int at); @@ -617,6 +620,7 @@ public: bool BypassRegisterConditionBlock(void); bool FoldLoopEntry(void); + bool CombineAlternateLoads(void); bool Is16BitImmSum(int at, int & val, int& reg) const;