diff --git a/autotest/arraytest.c b/autotest/arraytest.c index 4b12596..4ac510a 100644 --- a/autotest/arraytest.c +++ b/autotest/arraytest.c @@ -77,16 +77,17 @@ int main(void) a[i] = i % 10; al[i] = i % 10; } - +#if 0 assert(sum(a, 100) == 450); copy(b, a, 100); assert(sum(b, 100) == 450); reverse(c, a, 100); assert(sum(c, 100) == 450); - assert(sumb(a, 100) == 450); +#endif copyb(b, a, 100); assert(sumb(b, 100) == 450); +#if 0 reverseb(c, a, 100); assert(sumb(c, 100) == 450); @@ -97,6 +98,6 @@ int main(void) reversel(cl, al, 100); assert(suml(cl, 100) == 450); - +#endif return 0; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 7c483ed..2a89375 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -19,6 +19,90 @@ static bool IsIntegerType(InterType type) return type >= IT_INT8 && type <= IT_INT32; } +IntegerValueRange::IntegerValueRange(void) + : mMinState(S_UNKNOWN), mMaxState(S_UNKNOWN) +{} + +IntegerValueRange::~IntegerValueRange(void) +{} + +bool IntegerValueRange::Same(const IntegerValueRange& range) const +{ + if (mMinState == range.mMinState && mMaxState == range.mMaxState) + { + if ((mMinState == S_BOUND || mMinState == S_WEAK) && mMinValue != range.mMinValue) + return false; + if ((mMaxState == S_BOUND || mMaxState == S_WEAK) && mMaxValue != range.mMaxValue) + return false; + + return true; + } + + return false; +} + +bool IntegerValueRange::Merge(const IntegerValueRange& range) +{ + bool changed = false; + + if (mMinState != S_UNBOUND) + { + if (range.mMinState == S_UNKNOWN) + { + if (mMinState == S_BOUND) + mMinState = S_WEAK; + } + else if (range.mMinState == S_UNBOUND) + { + mMinState = S_UNBOUND; + changed = true; + } + else if (mMinState == S_UNKNOWN) + { + mMinState = S_WEAK; + mMinValue = range.mMinValue; + changed = true; + } + else if (range.mMinValue < mMinValue) + { + if (range.mMinState == S_WEAK) + mMinState = S_WEAK; + mMinValue = range.mMinValue; + changed = true; + } + } + + if (mMaxState != S_UNBOUND) + { + if (range.mMaxState == S_UNKNOWN) + { + if (mMaxState == S_BOUND) + mMaxState = S_WEAK; + } + else if (range.mMaxState == S_UNBOUND) + { + mMaxState = S_UNBOUND; + changed = true; + } + else if (mMaxState == S_UNKNOWN) + { + mMaxState = S_WEAK; + mMaxValue = range.mMaxValue; + changed = true; + } + else if (range.mMaxValue > mMaxValue) + { + if (range.mMaxState == S_WEAK) + mMaxState = S_WEAK; + mMaxValue = range.mMaxValue; + changed = true; + } + } + + return changed; +} + + ValueSet::ValueSet(void) { mSize = 32; @@ -1485,6 +1569,13 @@ InterOperand::InterOperand(void) : mTemp(INVALID_TEMPORARY), mType(IT_NONE), mFinal(false), mIntConst(0), mFloatConst(0), mVarIndex(-1), mOperandSize(0), mLinkerObject(nullptr), mMemory(IM_NONE) {} +bool InterOperand::IsUByte(void) const +{ + return + mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= 0 && + mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 256; +} + bool InterOperand::IsEqual(const InterOperand& op) const { if (mType != op.mType || mTemp != op.mTemp) @@ -2202,6 +2293,46 @@ void InterInstruction::SimpleLocalToTemp(int vindex, int temp) } } +void InterOperand::Disassemble(FILE* file) +{ + static char typechars[] = "NBCILFP"; + + if (mTemp >= 0) + { + fprintf(file, "R%d(%c)", mTemp, typechars[mType]); + if (mRange.mMinState >= IntegerValueRange::S_WEAK || mRange.mMaxState >= IntegerValueRange::S_WEAK) + { + fprintf(file, "["); + if (mRange.mMinState == IntegerValueRange::S_WEAK) + fprintf(file, "~%d", int(mRange.mMinValue)); + else if (mRange.mMinState == IntegerValueRange::S_BOUND) + fprintf(file, "%d", int(mRange.mMinValue)); + else if (mRange.mMinState == IntegerValueRange::S_UNKNOWN) + fprintf(file, "?"); + fprintf(file, ".."); + if (mRange.mMaxState == IntegerValueRange::S_WEAK) + fprintf(file, "~%d", int(mRange.mMaxValue)); + else if (mRange.mMaxState == IntegerValueRange::S_BOUND) + fprintf(file, "%d", int(mRange.mMaxValue)); + else if (mRange.mMaxState == IntegerValueRange::S_UNKNOWN) + fprintf(file, "?"); + fprintf(file, "]"); + } + } + else if (mType == IT_POINTER) + { + fprintf(file, "V%d+%d", mVarIndex, int(mIntConst)); + } + else if (IsIntegerType(mType) || mType == IT_BOOL) + { + fprintf(file, "C%c:%d", typechars[mType], int(mIntConst)); + } + else if (mType == IT_FLOAT) + { + fprintf(file, "C%c:%f", typechars[mType], mFloatConst); + } +} + void InterInstruction::Disassemble(FILE* file) { if (this->mCode != IC_NONE) @@ -2285,18 +2416,11 @@ void InterInstruction::Disassemble(FILE* file) static char typechars[] = "NBCILFP"; fprintf(file, "\t"); - if (mDst.mTemp >= 0) fprintf(file, "R%d(%c)", mDst.mTemp, typechars[mDst.mType]); + if (mDst.mTemp >= 0) + mDst.Disassemble(file); fprintf(file, "\t<-\t"); - if (mSrc[2].mTemp >= 0) fprintf(file, "R%d(%c%c), ", mSrc[2].mTemp, typechars[mSrc[2].mType], mSrc[2].mFinal ? 'F' : '-'); - if (mSrc[1].mTemp >= 0) - fprintf(file, "R%d(%c%c), ", mSrc[1].mTemp, typechars[mSrc[1].mType], mSrc[1].mFinal ? 'F' : '-'); - else if (this->mCode == IC_STORE) - fprintf(file, "V%d+%d, ", mSrc[1].mVarIndex, int(mSrc[1].mIntConst)); - if (mSrc[0].mTemp >= 0) - fprintf(file, "R%d(%c%c)", mSrc[0].mTemp, typechars[mSrc[0].mType], mSrc[0].mFinal ? 'F' : '-'); - else if (this->mCode == IC_LOAD) - fprintf(file, "V%d+%d", mSrc[0].mVarIndex, int(mSrc[0].mIntConst)); + if (this->mCode == IC_CONSTANT) { if (mDst.mType == IT_POINTER) @@ -2304,23 +2428,39 @@ void InterInstruction::Disassemble(FILE* file) fprintf(file, "C%c%d(%d:%d)", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst)); } else if (mDst.mType == IT_FLOAT) - fprintf(file, "C%f", mConst.mFloatConst); + fprintf(file, "CF:%f", mConst.mFloatConst); else { #ifdef _WIN32 - fprintf(file, "C%I64d", mConst.mIntConst); + fprintf(file, "CI:%I64d", mConst.mIntConst); #else - fprintf(file, "C%lld", mConst.mIntConst); + fprintf(file, "CI:%lld", mConst.mIntConst); #endif } } + else + { + bool first = true; + for (int i = 0; i < mNumOperands; i++) + { + int j = mNumOperands - i - 1; + if (!first) + fprintf(file, ", "); + if (mSrc[j].mType != IT_NONE) + { + mSrc[j].Disassemble(file); + first = false; + } + } + } fprintf(file, "\n"); } } InterCodeBasicBlock::InterCodeBasicBlock(void) - : mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr) + : mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr), + mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mEntryBlocks(nullptr) { mInPath = false; mLoopHead = false; @@ -2353,6 +2493,26 @@ void InterCodeBasicBlock::Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlo } +void InterCodeBasicBlock::CollectEntryBlocks(InterCodeBasicBlock* from) +{ + if (from) + { + int i = 0; + while (i < mEntryBlocks.Size() && mEntryBlocks[i] != from) + i++; + if (i == mEntryBlocks.Size()) + mEntryBlocks.Push(from); + } + + if (!mVisited) + { + mVisited = true; + + if (mTrueJump) mTrueJump->CollectEntryBlocks(this); + if (mFalseJump) mFalseJump->CollectEntryBlocks(this); + } +} + void InterCodeBasicBlock::CollectEntries(void) { mNumEntries++; @@ -3130,6 +3290,392 @@ bool InterCodeBasicBlock::PropagateConstTemps(const GrowingInstructionPtrArray& return changed; } +bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void) +{ + bool changed = false; + + mNumEntered++; + if (!mLoopHead && mNumEntered < mEntryBlocks.Size()) + return false; + + mLocalValueRange.Clear(); + + for (int j = 0; j < mEntryBlocks.Size(); j++) + { + InterCodeBasicBlock* from = mEntryBlocks[j]; + GrowingIntegerValueRangeArray& range(this == from->mTrueJump ? from->mTrueValueRange : from->mFalseValueRange); + if (j == 0) + mLocalValueRange = range; + else + { + for (int i = 0; i < mLocalValueRange.Size(); i++) + mLocalValueRange[i].Merge(range[i]); + } + } + + for (int i = 0; i < mLocalValueRange.Size(); i++) + if (!mLocalValueRange[i].Same(mEntryValueRange[i])) + changed = true; + + if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size()) + return changed; + + if (!mVisited || changed) + { + mVisited = true; + + if (changed) + { + mEntryValueRange = mLocalValueRange; + + UpdateLocalIntegerRangeSets(); + } + + if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets()) + changed = true; + if (mFalseJump && mFalseJump->BuildGlobalIntegerRangeSets()) + changed = true; + } + + return changed; +} + +void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) +{ + mLocalValueRange = mEntryValueRange; + + int sz = mInstructions.Size(); + + for (int i = 0; i < sz; i++) + { + InterInstruction* ins(mInstructions[i]); + + for (int i = 0; i < ins->mNumOperands; i++) + { + if (ins->mSrc[i].mTemp >= 0) + ins->mSrc[i].mRange = mLocalValueRange[ins->mSrc[i].mTemp]; + } + + if (ins->mDst.mTemp >= 0 && IsIntegerType(ins->mDst.mType)) + { + IntegerValueRange& vr(mLocalValueRange[ins->mDst.mTemp]); + + switch (ins->mCode) + { + case IC_CONSTANT: + vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = vr.mMaxValue = ins->mConst.mIntConst; + break; + case IC_UNARY_OPERATOR: + { + switch (ins->mOperator) + { + case IA_NEG: + { + IntegerValueRange tr; + IntegerValueRange& sr(mLocalValueRange[ins->mSrc[0].mTemp]); + + tr.mMinState = vr.mMaxState; + tr.mMinValue = -vr.mMaxValue; + tr.mMaxState = vr.mMinState; + tr.mMaxValue = -vr.mMinValue; + vr = tr; + } + break; + default: + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + } + break; + } + case IC_CONVERSION_OPERATOR: + switch (ins->mOperator) + { + case IA_EXT8TO16S: + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -128 || vr.mMaxValue > 127) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = 127; + } + if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < -128 || vr.mMinValue > 127) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = -128; + } + break; + + case IA_EXT8TO16U: + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = 255; + } + if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = 0; + } + break; + + default: + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + } + break; + + case IC_BINARY_OPERATOR: + switch (ins->mOperator) + { + case IA_ADD: + if (ins->mSrc[0].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[1].mTemp]; + if (ins->mSrc[0].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (ins->mSrc[0].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + vr.mMaxValue += ins->mSrc[0].mIntConst; + vr.mMinValue += ins->mSrc[0].mIntConst; + } + else if (ins->mSrc[1].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + if (ins->mSrc[1].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (ins->mSrc[1].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + vr.mMaxValue += ins->mSrc[1].mIntConst; + vr.mMinValue += ins->mSrc[1].mIntConst; + } + else + { + if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = ins->mSrc[0].mRange.mMaxValue + ins->mSrc[1].mRange.mMaxValue; + } + else + vr.mMaxState = IntegerValueRange::S_UNBOUND; + + if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = ins->mSrc[0].mRange.mMinValue + ins->mSrc[1].mRange.mMinValue; + } + else + vr.mMinState = IntegerValueRange::S_UNBOUND; + } + + break; + case IA_SUB: + if (ins->mSrc[0].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[1].mTemp]; + if (ins->mSrc[0].mIntConst < 0 && vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (ins->mSrc[0].mIntConst > 0 && vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + vr.mMaxValue -= ins->mSrc[0].mIntConst; + vr.mMinValue -= ins->mSrc[0].mIntConst; + } + else if (ins->mSrc[1].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + int maxv = vr.mMaxValue, minv = vr.mMinValue; + + if (vr.mMaxState == IntegerValueRange::S_WEAK) + { + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + vr.mMinState = IntegerValueRange::S_UNBOUND; + } + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + + vr.mMaxValue = ins->mSrc[1].mIntConst - minv; + vr.mMinValue = ins->mSrc[1].mIntConst - maxv; + } + else + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + + break; + case IA_MUL: + if (ins->mSrc[0].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[1].mTemp]; + if (ins->mSrc[0].mIntConst > 0) + { + if (vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + + vr.mMaxValue *= ins->mSrc[0].mIntConst; + vr.mMinValue *= ins->mSrc[0].mIntConst; + } + else + { + if (vr.mMaxState == IntegerValueRange::S_WEAK) + { + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + vr.mMinState = IntegerValueRange::S_UNBOUND; + } + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + + int maxv = vr.mMaxValue, minv = vr.mMinValue; + vr.mMaxValue = ins->mSrc[0].mIntConst * minv; + vr.mMinValue = ins->mSrc[0].mIntConst * maxv; + } + } + else if (ins->mSrc[1].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + if (ins->mSrc[1].mIntConst > 0) + { + if (vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + + vr.mMaxValue *= ins->mSrc[1].mIntConst; + vr.mMinValue *= ins->mSrc[1].mIntConst; + } + else + { + if (vr.mMaxState == IntegerValueRange::S_WEAK) + { + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + vr.mMinState = IntegerValueRange::S_UNBOUND; + } + if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + + int maxv = vr.mMaxValue, minv = vr.mMinValue; + vr.mMaxValue = ins->mSrc[1].mIntConst * minv; + vr.mMinValue = ins->mSrc[1].mIntConst * maxv; + } + } + else + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + + break; + case IA_SHL: + if (ins->mSrc[0].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[1].mTemp]; + if (vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMaxState = IntegerValueRange::S_UNBOUND; + else if (vr.mMinState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; + + vr.mMaxValue <<= ins->mSrc[0].mIntConst; + vr.mMinValue <<= ins->mSrc[0].mIntConst; + } + else + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + break; + case IA_AND: + if (ins->mSrc[0].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[1].mTemp]; + if (ins->mSrc[0].mIntConst >= 0) + { + vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMaxValue = ins->mSrc[0].mIntConst; + vr.mMinValue = 0; + } + } + else if (ins->mSrc[1].mTemp < 0) + { + vr = mLocalValueRange[ins->mSrc[0].mTemp]; + if (ins->mSrc[1].mIntConst >= 0) + { + vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMaxValue = ins->mSrc[1].mIntConst; + vr.mMinValue = 0; + } + } + else + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + break; + + default: + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + } + break; + + default: + vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; + } + + ins->mDst.mRange = vr; + } + } + + for (int i = 0; i < mLocalValueRange.Size(); i++) + if (!mExitRequiredTemps[i]) + mLocalValueRange[i].mMinState = mLocalValueRange[i].mMaxState = IntegerValueRange::S_UNKNOWN; + + mTrueValueRange = mLocalValueRange; + mFalseValueRange = mLocalValueRange; + + if (sz >= 2) + { + if (mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[sz - 1]->mSrc[0].mTemp == mInstructions[sz - 2]->mDst.mTemp) + { + if (mInstructions[sz - 2]->mOperator == IA_CMPLS) + { + if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) + { + int t = mInstructions[sz - 2]->mSrc[1].mTemp; + mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND; + mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1; + + mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; + mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + } + } + else if (mInstructions[sz - 2]->mOperator == IA_CMPLU) + { + if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) + { + int t = mInstructions[sz - 2]->mSrc[1].mTemp; + mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND; + mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1; + mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; + mTrueValueRange[t].mMinValue = 0; + + mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; + mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + } + } + } + } +} + +void InterCodeBasicBlock::BuildLocalIntegerRangeSets(int num) +{ + int i; + + if (!mVisited) + { + mVisited = true; + + mEntryValueRange.SetSize(num, true); + mTrueValueRange.SetSize(num, true); + mFalseValueRange.SetSize(num, true); + mLocalValueRange.SetSize(num, true); + + UpdateLocalIntegerRangeSets(); + + if (mTrueJump) mTrueJump->BuildLocalIntegerRangeSets(num); + if (mFalseJump) mFalseJump->BuildLocalIntegerRangeSets(num); + } +} + void InterCodeBasicBlock::BuildLocalTempSets(int num) { int i; @@ -5926,13 +6472,27 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->CollectActiveTemporaries(activeSet); - mTemporaries.SetSize(activeSet.Num(), true); - ResetVisited(); mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries); + ResetVisited(); + mEntryBlock->CollectEntryBlocks(nullptr); + + BuildDataFlowSets(); + + ResetVisited(); + mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size()); + + do { + DisassembleDebug("tt"); + + ResetVisited(); + } while (mEntryBlock->BuildGlobalIntegerRangeSets()); + + DisassembleDebug("Estimated value range"); + MapVariables(); DisassembleDebug("mapped variabled"); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 0487098..e8df5fe 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -128,6 +128,30 @@ typedef GrowingArray GrowingVariableArray; #define INVALID_TEMPORARY (-1) +class IntegerValueRange +{ +public: + IntegerValueRange(void); + ~IntegerValueRange(void); + + int64 mMinValue, mMaxValue; + + enum State + { + S_UNKNOWN, + S_UNBOUND, + S_WEAK, + S_BOUND + } mMinState, mMaxState; + + bool Same(const IntegerValueRange& range) const; + bool Merge(const IntegerValueRange& range); +}; + + + +typedef GrowingArray GrowingIntegerValueRangeArray; + class ValueSet { protected: @@ -300,10 +324,15 @@ public: int mVarIndex, mOperandSize; LinkerObject * mLinkerObject; InterMemory mMemory; + IntegerValueRange mRange; InterOperand(void); bool IsEqual(const InterOperand & op) const; + + bool IsUByte(void) const; + + void Disassemble(FILE* file); }; class InterInstruction @@ -430,6 +459,10 @@ public: NumberSet mEntryRequiredParams, mEntryProvidedParams; NumberSet mExitRequiredParams, mExitProvidedParams; + GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange; + + GrowingArray mEntryBlocks; + GrowingInstructionPtrArray mMergeTValues; ValueSet mMergeValues; TempForwardingTable mMergeForwardingTable; @@ -441,6 +474,7 @@ public: void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump); void CollectEntries(void); + void CollectEntryBlocks(InterCodeBasicBlock* from); void GenerateTraces(bool expand); void LocalToTemp(int vindex, int temp); @@ -467,6 +501,10 @@ public: bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars); bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars); + void BuildLocalIntegerRangeSets(int num); + void UpdateLocalIntegerRangeSets(void); + bool BuildGlobalIntegerRangeSets(void); + GrowingIntArray mEntryRenameTable; GrowingIntArray mExitRenameTable; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index fd7f48c..debbcb8 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5624,9 +5624,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); if (InterTypeSize[ins->mDst.mType] > 1) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); - mIns.Push(insh); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (ins->mDst.IsUByte()) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } } @@ -5645,9 +5653,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); if (InterTypeSize[ins->mDst.mType] > 1) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(insh); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (ins->mDst.IsUByte()) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } } @@ -5929,77 +5945,131 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p if (ins->mSrc[0].mTemp < 0) { + int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + int shift = ins->mSrc[0].mIntConst & 15; - if (shift == 0) + if (ins->mDst.IsUByte()) { - if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + if (shift == 0) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (sreg != treg) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + } } - } - else if (shift == 1) - { - if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + else if (shift == 1) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + } + } + else if (shift >= 8) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + } + else if (shift > 5) + { + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + for(int i=shift; i<8; i++) + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0xff << shift)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg )); } else { - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + for (int i = 0; i < shift; i++) + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); } - } - else if (shift == 7) - { - int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0)); - mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); - } - else if (shift >= 8) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - for (int i = 8; i < shift; i++) - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); } else { - if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + if (shift == 0) + { + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift == 1) + { + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift == 7) + { + int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + } + else if (shift >= 8) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + for (int i = 8; i < shift; i++) + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); } else { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); - } - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - for (int i = 1; i < shift; i++) - { - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + } mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + for (int i = 1; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + } + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff)) @@ -8699,6 +8769,109 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i return false; } +bool NativeCodeBasicBlock::PatchDirectAddressSumY(int at, int reg, int apos, int breg) +{ + int yindex = 0; + int last = at; + + while (last < mIns.Size()) + { + if (mIns[last].mType == ASMIT_LDY && mIns[last].mMode == ASMIM_IMMEDIATE && (mIns[last].mAddress == yindex || mIns[last].mAddress == yindex + 1)) + yindex = mIns[last].mAddress; + else if (mIns[last].ChangesYReg()) + return false; + else if (mIns[last].mMode == ASMIM_ZERO_PAGE && (mIns[last].mAddress == breg || mIns[last].mAddress == breg + 1 || mIns[last].mAddress == reg || mIns[last].mAddress == reg + 1) && mIns[last].ChangesAddress()) + return false; + else if (mIns[last].mMode == ASMIM_INDIRECT_Y && mIns[last].mAddress == reg) + { + if (!(mIns[last].mLive & LIVE_MEM)) + break; + } + else if (mIns[last].RequiresYReg()) + return false; + last++; + } + + if (last == mIns.Size()) + return false; + + mIns[apos].mType = ASMIT_TAY; + for (int i = 0; i < 5; i++) + { + mIns[apos + i + 1].mType = ASMIT_NOP; + mIns[apos + i + 1].mMode = ASMIM_IMPLIED; + } + yindex = 0; + + for (int i = apos; i <= last; i++) + { + mIns[i].mLive | LIVE_CPU_REG_Y; + + if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE) + { + if (mIns[i].mAddress == yindex) + { + mIns[i].mType = ASMIT_NOP; + mIns[i].mMode = ASMIM_IMPLIED; + } + else + { + mIns[i].mType = ASMIT_INY; + mIns[i].mMode = ASMIM_IMPLIED; + yindex++; + } + } + else if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == reg) + { + mIns[i].mAddress = breg; + } + } + + return true; +} + +bool NativeCodeBasicBlock::FindDirectAddressSumY(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].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1) && mIns[k].ChangesAddress()) + return false; + + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1)) + return false; + if (mIns[k].mMode == ASMIM_INDIRECT_Y && mIns[k].mAddress == breg) + return false; + + k++; + } + + apos = j; + + return true; + } + + if (mIns[j + 5].mMode == ASMIM_ZERO_PAGE && (mIns[j + 5].mAddress == reg || mIns[j + 5].mAddress == reg + 1) && mIns[j + 5].ChangesAddress() || mIns[j + 5].ChangesYReg() || mIns[j + 5].RequiresYReg()) + return false; + + j--; + } + + return false; +} + bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg) { @@ -12011,6 +12184,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } #if 1 + 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) + { + int apos, breg; + if (FindDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg)) + { + if (PatchDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg)) + progress = true; + } + } + +#endif +#if 0 if (i + 7 < mIns.Size()) { if ( @@ -12042,7 +12227,79 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } #endif -#if 1 +#if 0 + if (i + 8 < mIns.Size()) + { + if ( + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 && + mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 && + mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 && + !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() && + mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 && + mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress && !(mIns[i + 8].mLive & LIVE_MEM)) + { + for (int j = 0; j < 6; j++) + { + mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED; + } + + if (mIns[i + 8].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + mIns[i + 9].mLive |= LIVE_CPU_REG_Y; + } + + mIns[i + 0].mType = ASMIT_TAY; + mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED; + mIns[i + 8].mAddress = mIns[i + 1].mAddress; + progress = true; + } + } +#endif +#if 0 + if (i + 11 < mIns.Size()) + { + if ( + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 && + mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 && + mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 && + !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() && + mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 && + mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress && + !mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 9].RequiresYReg() && + mIns[i + 10].mType == ASMIT_LDY && mIns[i + 10].mMode == ASMIM_IMMEDIATE && mIns[i + 10].mAddress == 1 && + mIns[i + 11].mMode == ASMIM_INDIRECT_Y && mIns[i + 11].mAddress == mIns[i + 2].mAddress && + !(mIns[i + 11].mLive & LIVE_MEM)) + { + for (int j = 0; j < 6; j++) + { + mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED; + } + + if (mIns[i + 11].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 12, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 1)); + mIns[i + 12].mLive |= LIVE_CPU_REG_Y; + } + + mIns[i + 0].mType = ASMIT_TAY; + mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED; + mIns[i + 8].mAddress = mIns[i + 1].mAddress; + mIns[i + 10].mType = ASMIT_INY; mIns[i + 10].mMode = ASMIM_IMPLIED; + mIns[i + 11].mAddress = mIns[i + 1].mAddress; + progress = true; + } + } +#endif +#if 0 if (i + 9 < mIns.Size()) { if ( diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 48e6504..308b628 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -197,6 +197,8 @@ public: bool MoveLoadAddImmStoreUp(int at); bool MoveCLCLoadAddZPStoreUp(int at); bool MoveLoadAddZPStoreUp(int at); + bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg); + bool PatchDirectAddressSumY(int at, int reg, int apos, int breg); bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg); bool FindGlobalAddress(int at, int reg, int& apos); bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags);