diff --git a/include/audio/sidfx.c b/include/audio/sidfx.c index e04827b..ca3a781 100644 --- a/include/audio/sidfx.c +++ b/include/audio/sidfx.c @@ -12,10 +12,10 @@ enum SIDFXState static struct SIDFXChannel { - SIDFX * com; - byte delay, cnt, priority; + const SIDFX * com; + byte delay, cnt, priority; volatile SIDFXState state; - unsigned freq, pwm; + unsigned freq, pwm; } channels[3]; @@ -29,7 +29,7 @@ void sidfx_init(void) } } -void sidfx_play(byte chn, SIDFX * fx, byte cnt) +void sidfx_play(byte chn, const SIDFX * fx, byte cnt) { SIDFXState ns = channels[chn].state; diff --git a/include/audio/sidfx.h b/include/audio/sidfx.h index 9bb9733..729afe6 100644 --- a/include/audio/sidfx.h +++ b/include/audio/sidfx.h @@ -14,7 +14,7 @@ struct SIDFX void sidfx_init(void); -inline void sidfx_play(byte chn, SIDFX * fx, byte cnt); +inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt); void sidfx_stop(byte chn); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9afc125..c1138be 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -7817,6 +7817,34 @@ void InterCodeBasicBlock::MarkRelevantStatics(void) } } +bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const +{ + InterInstruction* ins = mInstructions[ii]; + + if (ins->mCode == IC_LOAD) + { + for (int i = ii + 1; i < mInstructions.Size(); i++) + if (!CanBypassLoad(ins, mInstructions[i])) + return false; + } + else if (ins->mCode == IC_STORE) + { + return false; + } + else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME || + ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE) + return false; + else + { + for (int i = ii + 1; i < mInstructions.Size(); i++) + if (!CanBypass(ins, mInstructions[i])) + return false; + } + + return true; +} + + bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const { InterInstruction* ins = mInstructions[ii]; @@ -7923,10 +7951,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void) { mVisited = true; + if (mTrueJump && mTrueJump == mFalseJump) + { + mFalseJump = nullptr; + mInstructions[mInstructions.Size() - 1]->mCode = IC_JUMP; + mInstructions[mInstructions.Size() - 1]->mNumOperands = 0; + mTrueJump->mNumEntries--; + changed = true; + } + if (mTrueJump && mFalseJump) { InterCodeBasicBlock* tblock = nullptr, * fblock = nullptr; + if (mTrueJump != mFalseJump && mTrueJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && mTrueJump->mFalseJump == mFalseJump->mFalseJump) + { + if (mTrueJump->mInstructions.Size() == 1) + { + tblock = mTrueJump; + fblock = mFalseJump; + } + else if (mFalseJump->mInstructions.Size() == 1) + { + fblock = mTrueJump; + tblock = mFalseJump; + } + + if (fblock && tblock) + { + if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp]) + { + fblock->mTrueJump = tblock; + fblock->mFalseJump = nullptr; + fblock->mInstructions[fblock->mInstructions.Size() - 1]->mCode = IC_JUMP; + fblock->mInstructions[fblock->mInstructions.Size() - 1]->mNumOperands = 0; + tblock->mNumEntries++; + tblock->mFalseJump->mNumEntries--; + tblock->mTrueJump->mNumEntries--; + changed = true; + } + } + + fblock = nullptr; + tblock = nullptr; + } + if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump) { tblock = mTrueJump; @@ -7982,6 +8051,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void) } } } +#if 1 + else if ((mins->mCode == IC_BINARY_OPERATOR || mins->mCode == IC_LEA) && (mins->mSrc[1].mTemp < 0 || mins->mSrc[0].mTemp < 0) || mins->mCode == IC_UNARY_OPERATOR || mins->mCode == IC_CONVERSION_OPERATOR) + { + int ttemp = mins->mDst.mTemp; + int stemp = ((mins->mCode == IC_BINARY_OPERATOR || mins->mCode == IC_LEA) && mins->mSrc[0].mTemp < 0) ? mins->mSrc[1].mTemp : mins->mSrc[0].mTemp; + + if (!tblock->mLocalRequiredTemps[ttemp] && !tblock->mLocalModifiedTemps[stemp] && !tblock->mLocalModifiedTemps[ttemp] && !IsTempReferencedOnPath(ttemp, i + 1) && !IsTempModifiedOnPath(stemp, i + 1)) + { + tblock->mEntryRequiredTemps += stemp; + tblock->mExitRequiredTemps += stemp; + + fblock->mEntryRequiredTemps += stemp; + mExitRequiredTemps += stemp; + + fblock->mInstructions.Insert(0, mins); + mInstructions.Remove(i); + + changed = true; + } + } +#endif + else if (mins->mCode == IC_LOAD) + { + int ttemp = mins->mDst.mTemp; + int stemp = mins->mSrc[0].mTemp; + + if (!tblock->mLocalRequiredTemps[ttemp] && (stemp < 0 || !tblock->mLocalModifiedTemps[stemp]) && + !tblock->mLocalModifiedTemps[ttemp] && !IsTempReferencedOnPath(ttemp, i + 1) && (stemp < 0 || !IsTempModifiedOnPath(stemp, i + 1)) && + CanMoveInstructionBehindBlock(i)) + { + if (stemp >= 0) + { + tblock->mEntryRequiredTemps += stemp; + tblock->mExitRequiredTemps += stemp; + + fblock->mEntryRequiredTemps += stemp; + mExitRequiredTemps += stemp; + } + + fblock->mInstructions.Insert(0, mins); + mInstructions.Remove(i); + + changed = true; + } + } } } } @@ -8008,6 +8122,24 @@ bool InterCodeBasicBlock::IsTempModifiedOnPath(int temp, int at) const return false; } +bool InterCodeBasicBlock::IsTempReferencedOnPath(int temp, int at) const +{ + while (at < mInstructions.Size()) + { + const InterInstruction * ins = mInstructions[at]; + + if (ins->mDst.mTemp == temp) + return true; + for (int i = 0; i < ins->mNumOperands; i++) + if (ins->mSrc[i].mTemp == temp) + return true; + + at++; + } + + return false; +} + bool InterCodeBasicBlock::PushSinglePathResultInstructions(void) { int i; @@ -11246,6 +11378,11 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->DropUnreachable(); + BuildDataFlowSets(); + + ResetVisited(); + mEntryBlock->CollectLocalUsedTemps(mTemporaries.Size()); + ResetVisited(); mEntryBlock->ForwardDiamondMovedTemp(); DisassembleDebug("Diamond move forwarding"); @@ -11351,6 +11488,20 @@ void InterCodeProcedure::Close(void) } while (changed); #endif +#if 1 + BuildDataFlowSets(); + + ResetVisited(); + mEntryBlock->CollectLocalUsedTemps(mTemporaries.Size()); + + ResetVisited(); + mEntryBlock->ForwardDiamondMovedTemp(); + DisassembleDebug("Diamond move forwarding 2"); + + TempForwarding(); + + RemoveUnusedInstructions(); +#endif #if 1 ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 5583fef..0da8869 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -455,9 +455,11 @@ public: void RemoveNonRelevantStatics(void); bool IsTempModifiedOnPath(int temp, int at) const; + bool IsTempReferencedOnPath(int temp, int at) const; bool PushSinglePathResultInstructions(void); bool CanMoveInstructionBeforeBlock(int ii) const; + bool CanMoveInstructionBehindBlock(int ii) const; bool MergeCommonPathInstructions(void); void PeepholeOptimization(const GrowingVariableArray& staticVars); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 1cccb04..5668d99 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -13381,9 +13381,14 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool mTrueJump->mIns[0].SameEffectiveAddress(mFalseJump->mIns[0]) && mTrueJump->mIns[1].SameEffectiveAddress(mFalseJump->mIns[1]) && HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode)) { + uint32 live = mIns[s - 1].mLive; + if (mIns[s - 1].RequiresYReg()) + live |= LIVE_CPU_REG_Y; + mTrueJump->mIns[0].mType = ASMIT_LDX; - mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; + mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X | live; mTrueJump->mIns[1].mType = ASMIT_STX; + mTrueJump->mIns[1].mLive |= live; mIns.Insert(s - 1, mTrueJump->mIns[0]); mIns.Insert(s, mTrueJump->mIns[1]); @@ -13391,6 +13396,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); + CheckLive(); + changed = true; } } @@ -13406,9 +13413,15 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode) && !mIns[s - 1].MayBeChangedOnAddress(mTrueJump->mIns[1])) { + uint32 live = mIns[s - 1].mLive; + if (mIns[s - 1].RequiresYReg()) + live |= LIVE_CPU_REG_Y; + mTrueJump->mIns[0].mType = ASMIT_LDX; - mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; + mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X | live; mTrueJump->mIns[1].mType = ASMIT_STX; + mTrueJump->mIns[1].mLive |= live; + mIns.Insert(s - 1, mTrueJump->mIns[0]); mIns.Insert(s, mTrueJump->mIns[1]); @@ -13416,6 +13429,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); + CheckLive(); + changed = true; } } @@ -22238,7 +22253,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y; if (mIns[i + 2].mAddress == 2) mIns[i + 3].mType = ASMIT_INY; else @@ -22254,7 +22269,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y; if (mIns[i + 2].mAddress == 2) mIns[i + 3].mType = ASMIT_DEY; else @@ -22271,12 +22286,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X; if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_INX; else mIns[i + 2].mType = ASMIT_NOP; - mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X; mIns[i + 3].mType = ASMIT_STX; progress = true; } @@ -22288,12 +22303,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X; if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_DEX; else mIns[i + 2].mType = ASMIT_NOP; - mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X; mIns[i + 3].mType = ASMIT_STX; progress = true; } @@ -22324,12 +22339,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y; if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_DEY; else mIns[i + 2].mType = ASMIT_NOP; - mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y; mIns[i + 3].mType = ASMIT_STY; progress = true; } @@ -22342,7 +22357,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STY; progress = true; @@ -22355,7 +22370,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STX; progress = true;