diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 0516c5a..d853de8 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -983,17 +983,18 @@ cistream::cistream(void) void cistream::refill(void) { - mBufferFill = 0; mBufferPos = 0; - char ch; - while (mBufferFill < 32) + char fill = 0; + while (fill < 32) { char ch = getchar(); - mBuffer[mBufferFill++] = ch; + mBuffer[fill++] = ch; if (ch == '\n') break; } + + mBufferFill = fill; } cistream cin; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 50a1068..90771e6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -12837,6 +12837,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) for (int i = 0; i < block->mInstructions.Size(); i++) { InterInstruction* ins = block->mInstructions[i]; + InterInstruction* nins = nullptr; + if (i + 1 < block->mInstructions.Size()) + nins = block->mInstructions[i + 1]; + int t = ins->mDst.mTemp; if (t >= 0) { @@ -12866,6 +12870,8 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mExpensive = true; else if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[0].mRange.mMaxValue >= 256) ins->mExpensive = true; + else if (nins && nins->mCode == IC_LEA && nins->mSrc[0].mTemp >= 0 && (nins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_UNBOUND || nins->mSrc[0].mRange.mMaxValue >= 255)) + ins->mExpensive = true; break; case IC_LOAD: case IC_STORE: @@ -15631,6 +15637,17 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray return changed; } +static int TempUseDelta(const InterInstruction* ins) +{ + int d = 0; + if (ins->mDst.mTemp >= 0) + d++; + for (int i = 0; i < ins->mNumOperands; i++) + if (ins->mSrc[i].mTemp >= 0 && ins->mSrc[i].mFinal) + d--; + return d; +} + void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars) { int i; @@ -15945,25 +15962,26 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati j--; while (j >= 0) { + InterInstruction* jins = mInstructions[j]; + if (j < ti - 1) { if (CanMoveInstructionDown(j, ti)) { - InterInstruction* jins = mInstructions[j]; for (int k = j; k < ti - 1; k++) { SwapInstructions(jins, mInstructions[k + 1]); mInstructions[k] = mInstructions[k + 1]; } mInstructions[ti - 1] = jins; - if (mInstructions[ti - 1]->NumUsedTemps() <= 1) - ti--; + if (jins->NumUsedTemps() <= 1 && !(jins->mCode == IC_CALL || jins->mCode == IC_CALL_NATIVE)) + ti--; // mInstructions.Insert(i, mInstructions[j]); // mInstructions.Remove(j); } } - else if (mInstructions[j]->NumUsedTemps() <= 1) + else if (jins->NumUsedTemps() <= 1 && !(jins->mCode == IC_CALL || jins->mCode == IC_CALL_NATIVE)) ti--; j--; @@ -15974,6 +15992,33 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati #endif CheckFinalLocal(); + // check move calls our of range to save register spilling + i = 0; + while (i < mInstructions.Size()) + { + InterInstruction* ins(mInstructions[i]); + if ((ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) && ins->mSrc[0].mTemp < 0) + { + int j = i; + while (j > 0 && CanSwapInstructions(ins, mInstructions[j - 1]) && TempUseDelta(mInstructions[j - 1]) >= 0) + j--; + while (j < i && TempUseDelta(mInstructions[j]) == 0) + j++; + + if (j < i) + { + while (i > j) + { + i--; + SwapInstructions(mInstructions[i], ins); + mInstructions[i + 1] = mInstructions[i]; + } + mInstructions[j] = ins; + } + } + i++; + } + // sort stores up bool changed; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 97f6ace..642b288 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5921,6 +5921,29 @@ void NativeCodeBasicBlock::StoreByteIndexedValue(InterCodeProcedure* proc, const } +void NativeCodeBasicBlock::StoreByteOffsetIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* wins) +{ + mIns.Push(NativeCodeInstruction(iins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(iins, ASMIT_CLC)); + mIns.Push(NativeCodeInstruction(iins, ASMIT_ADC, ASMIM_IMMEDIATE, wins->mSrc[1].mIntConst)); + mIns.Push(NativeCodeInstruction(iins, ASMIT_TAY)); + + uint32 flags = NCIF_LOWER | NCIF_UPPER; + if (wins->mVolatile) + flags |= NCIF_VOLATILE; + + for (int i = 0; i < InterTypeSize[wins->mSrc[0].mType]; i++) + { + if (i != 0) + mIns.Push(NativeCodeInstruction(wins, ASMIT_INY, ASMIM_IMPLIED)); + if (wins->mSrc[0].mTemp < 0) + mIns.Push(NativeCodeInstruction(wins, ASMIT_LDA, ASMIM_IMMEDIATE, (wins->mSrc[0].mIntConst >> (8 * i)) & 0xff)); + else + mIns.Push(NativeCodeInstruction(wins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp] + i)); + mIns.Push(NativeCodeInstruction(wins, ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[iins->mSrc[1].mTemp], nullptr, flags)); + } +} + void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins) { int size = InterTypeSize[wins->mSrc[0].mType]; @@ -19830,6 +19853,55 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool } } +#if 1 + if (mTrueJump && mFalseJump && mIns.Size() >= 2) + { + int nins = mIns.Size(); + if (mIns[nins - 2].mType == ASMIT_LDA && mIns[nins - 2].mMode == ASMIM_IMMEDIATE && + mIns[nins - 1].mType == ASMIT_CMP && mIns[nins - 1].mMode == ASMIM_ZERO_PAGE && (mIns[nins - 1].mLive & LIVE_MEM) && !(mIns[nins - 1].mLive & LIVE_CPU_REG_A) && + !mTrueJump->mEntryRequiredRegs[CPU_REG_C] && !mFalseJump->mEntryRequiredRegs[CPU_REG_C] && !mTrueJump->mEntryRequiredRegs[CPU_REG_Z] && !mFalseJump->mEntryRequiredRegs[CPU_REG_Z]) + { + int im = mIns[nins - 2].mAddress; + + mIns[nins - 2].CopyMode(mIns[nins - 1]); + mIns[nins - 2].mLive |= LIVE_MEM; + mIns[nins - 1].mMode = ASMIM_IMMEDIATE; + mIns[nins - 1].mFlags = NCIF_LOWER | NCIF_UPPER; + + if (mBranch == ASMIT_BCC) + { + if (im == 255) + { + mIns[nins - 1].mType = ASMIT_SEC; + mIns[nins - 1].mMode = ASMIM_IMPLIED; + } + else + { + mIns[nins - 1].mAddress = im + 1; + mBranch = ASMIT_BCS; + } + } + else if (mBranch == ASMIT_BCS) + { + if (im == 255) + { + mIns[nins - 1].mType = ASMIT_SEC; + mIns[nins - 1].mMode = ASMIM_IMPLIED; + } + else + { + mIns[nins - 1].mAddress = im + 1; + mBranch = ASMIT_BCC; + } + } + else + mIns[nins - 1].mAddress = im; + + + changed = true; + } + } +#endif CheckLive(); if (mTrueJump && mFalseJump) @@ -26343,6 +26415,9 @@ bool NativeCodeBasicBlock::ForwardReplaceZeroPage(int at, int from, int to) changed = true; if (mFalseJump && mFalseJump->ForwardReplaceZeroPage(0, from, to)) changed = true; + + if (changed) + mEntryRequiredRegs += to; } return changed; @@ -41351,7 +41426,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "mod"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "fill_row"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41429,7 +41504,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]); mEntryBlock->mBranch = ASMIT_JMP; - if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && !proc->mDispatchedCall && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && (mGenerator->mCompilerOptions & COPT_NATIVE)) + if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && !proc->mDispatchedCall && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && proc->mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP && (mGenerator->mCompilerOptions & COPT_NATIVE)) { #if 1 if (proc->mParamVars.Size() == 1 && proc->mParamVars[0]->mSize == 1) @@ -42712,6 +42787,7 @@ void NativeCodeProcedure::Optimize(void) else cnt++; + } while (changed); #if 1 @@ -43141,6 +43217,16 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode block->StoreByteIndexedValue(iproc, ins, iblock->mInstructions[i + 1]); i++; } + else if (i + 1 < iblock->mInstructions.Size() && + iblock->mInstructions[i + 1]->mCode == IC_STORE && iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal && + ins->mSrc[1].mTemp >= 0 && ins->mSrc[0].IsUByte() && ins->mSrc[0].mTemp >= 0 && + iblock->mInstructions[i + 1]->mSrc[1].mIntConst + ins->mSrc[0].mRange.mMaxValue + InterTypeSize[iblock->mInstructions[i + 1]->mSrc[0].mType] <= 256 && + (iblock->mInstructions[i + 1]->mSrc[0].mTemp >= 0 || iblock->mInstructions[i + 1]->mSrc[0].mType <= IT_INT32) && + (InterTypeSize[iblock->mInstructions[i + 1]->mSrc[0].mType] == 1 || iblock->mInstructions[i + 1]->mSrc[1].mStride == 1)) + { + block->StoreByteOffsetIndexedValue(iproc, ins, iblock->mInstructions[i + 1]); + i++; + } else if (i + 2 < iblock->mInstructions.Size() && ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mLinkerObject->mSize <= 256 && // ins->mSrc[0].IsUByte() && diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index c674169..5975eaf 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -331,6 +331,8 @@ public: bool LoadUnopStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* oins, const InterInstruction* wins); bool LoadLoadOpStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins1, const InterInstruction* rins0, const InterInstruction* oins, const InterInstruction* wins); void LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins); + void StoreByteOffsetIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* sins); + NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0); void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);