From a305dbb1cd9ad35554d5cd19137247fb917f2a79 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 23 Dec 2023 10:40:45 +0100 Subject: [PATCH] Improve function placement in linker --- autotest/autotest.bat | 6 + oscar64/Compiler.cpp | 6 + oscar64/Declaration.cpp | 5 +- oscar64/Emulator.cpp | 20 +- oscar64/Emulator.h | 1 + oscar64/InterCode.cpp | 27 +- oscar64/Linker.cpp | 169 +++++- oscar64/Linker.h | 12 +- oscar64/NativeCodeGenerator.cpp | 925 ++++++++++++++++++++++++-------- oscar64/NativeCodeGenerator.h | 6 +- 10 files changed, 907 insertions(+), 270 deletions(-) diff --git a/autotest/autotest.bat b/autotest/autotest.bat index d3680b3..a23ff9d 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -298,6 +298,9 @@ exit /b %errorlevel% ..\release\oscar64 -e -O3 -n %~1 @if %errorlevel% neq 0 goto :error +..\release\oscar64 -e -O2 -xz -Oz -n %~1 +@if %errorlevel% neq 0 goto :error + @exit /b 0 :testb @@ -334,4 +337,7 @@ exit /b %errorlevel% ..\release\oscar64 -e -O3 -n %~1 @if %errorlevel% neq 0 goto :error +..\release\oscar64 -e -O2 -xz -Oz -n %~1 +@if %errorlevel% neq 0 goto :error + @exit /b 0 diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 3897627..da66c16 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -1087,7 +1087,10 @@ bool Compiler::GenerateCode(void) mLinker->ReferenceObject(mCompilationUnits->mReferenced[i]->mLinkerObject); if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + { mLinker->CombineSameConst(); + mLinker->CheckDirectJumps(); + } if (mCompilerOptions & COPT_VERBOSE) printf("Link executable\n"); @@ -1286,6 +1289,9 @@ int Compiler::ExecuteCode(bool profile, int trace) printf("Running emulation...\n"); Emulator* emu = new Emulator(mLinker); + if (mCompilerOptions & COPT_EXTENDED_ZERO_PAGE) + emu->mJiffies = false; + int ecode = 20; if (mCompilerOptions & COPT_TARGET_PRG) { diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index e30d317..2195c9e 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -919,7 +919,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration* dec = new Declaration(mLocation, DT_VARIABLE_REF); dec->mFlags = mLeft->mDecValue->mFlags; dec->mBase = mLeft->mDecValue; - dec->mOffset = mDecType->mSize * mRight->mDecValue->mInteger; + dec->mOffset = int(mDecType->mSize * mRight->mDecValue->mInteger); dec->mSize = mDecType->mSize; ex->mDecValue = dec; ex->mDecType = mDecType; @@ -1770,7 +1770,8 @@ Declaration* Declaration::ToStriped(Errors * errors) else { ndec->mStride = 1; - ndec->mBase = mBase->ToStriped(mSize / mBase->mSize); + if (mBase->mSize > 0) + ndec->mBase = mBase->ToStriped(mSize / mBase->mSize); } } else if (ndec->mBase) diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index 3f32dc2..bc30247 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -7,6 +7,7 @@ Emulator::Emulator(Linker* linker) { for (int i = 0; i < 0x10000; i++) mMemory[i] = 0; + mJiffies = true; } @@ -514,19 +515,22 @@ int Emulator::Emulate(int startIP, int trace) int ticks = 0; while (mIP != 0) { - ticks++; - if (ticks > 4500) + if (mJiffies) { - mMemory[0xa2]++; - if (!mMemory[0xa2]) + ticks++; + if (ticks > 4500) { - mMemory[0xa1]++; - if (!mMemory[0xa1]) + mMemory[0xa2]++; + if (!mMemory[0xa2]) { - mMemory[0xa0]++; + mMemory[0xa1]++; + if (!mMemory[0xa1]) + { + mMemory[0xa0]++; + } } + ticks = 0; } - ticks = 0; } if (mIP == 0xffd2) diff --git a/oscar64/Emulator.h b/oscar64/Emulator.h index 72d24ce..2b5a6c4 100644 --- a/oscar64/Emulator.h +++ b/oscar64/Emulator.h @@ -16,6 +16,7 @@ public: int mIP; uint8 mRegA, mRegX, mRegY, mRegS, mRegP; + bool mJiffies; Linker* mLinker; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 76e12d9..3ae016c 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -698,7 +698,7 @@ static bool SameMemRegion(const InterOperand& op1, const InterOperand& op2) // returns true if op2 is part of op1 static bool SameMemSegment(const InterOperand& op1, const InterOperand& op2) { - if (op1.mMemory != op2.mMemory || op1.mIntConst > op2.mIntConst || op1.mIntConst + op1.mOperandSize < op2.mIntConst + op2.mOperandSize) + if (op1.mMemory != op2.mMemory || op1.mIntConst > op2.mIntConst || op1.mIntConst + op1.mOperandSize < op2.mIntConst + op2.mOperandSize || op1.mStride != op2.mStride) return false; switch (op1.mMemory) @@ -4698,14 +4698,14 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) if (mSrc[1].mStride != 1) { if (mSrc[0].mStride != 1) - fprintf(file, "COPY%c%d%c%d", memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory], mSrc[1].mStride); + fprintf(file, "COPY%d:%c%d%c%d", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory], mSrc[1].mStride); else - fprintf(file, "COPY%c%c%d", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory], mSrc[1].mStride); + fprintf(file, "COPY%d:%c%c%d", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory], mSrc[1].mStride); } else if (mSrc[0].mStride != 1) - fprintf(file, "COPY%c%d%c", memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory]); + fprintf(file, "COPY%d:%c%d%c", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory]); else - fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); + fprintf(file, "COPY%d:%c%c", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); break; case IC_MALLOC: @@ -6279,7 +6279,10 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray ins->mSrc[0].mMemory = ltemps[k]->mSrc[0].mMemory; ins->mSrc[0].mTemp = ltemps[k]->mSrc[0].mTemp; ins->mSrc[0].mVarIndex = ltemps[k]->mSrc[0].mVarIndex; - ins->mSrc[0].mIntConst = ins->mSrc[0].mIntConst * ltemps[k]->mSrc[0].mStride + ltemps[k]->mSrc[0].mIntConst; + if (ltemps[k]->mSrc[0].mStride != ltemps[k]->mSrc[1].mStride) + ins->mSrc[0].mIntConst = (ins->mSrc[0].mIntConst - ltemps[k]->mSrc[1].mIntConst) / ltemps[k]->mSrc[1].mStride * ltemps[k]->mSrc[0].mStride + ltemps[k]->mSrc[0].mIntConst; + else + ins->mSrc[0].mIntConst = ins->mSrc[0].mIntConst - ltemps[k]->mSrc[1].mIntConst + ltemps[k]->mSrc[0].mIntConst; ins->mSrc[0].mLinkerObject = ltemps[k]->mSrc[0].mLinkerObject; ins->mSrc[0].mStride = ltemps[k]->mSrc[0].mStride; changed = true; @@ -6330,14 +6333,14 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray j = 0; for (int k = 0; k < ltemps.Size(); k++) { - if (ltemps[k]->mSrc[0].mTemp < 0 && ltemps[k]->mSrc[0].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[0].mVarIndex] || - ltemps[k]->mSrc[1].mTemp < 0 && ltemps[k]->mSrc[1].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[1].mVarIndex] || - ltemps[k]->mSrc[0].mTemp < 0 && (ltemps[k]->mSrc[0].mMemory == IM_PARAM || ltemps[k]->mSrc[0].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[0].mVarIndex] || - ltemps[k]->mSrc[1].mTemp < 0 && (ltemps[k]->mSrc[1].mMemory == IM_PARAM || ltemps[k]->mSrc[1].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[1].mVarIndex]) + if (ltemps[k]->mSrc[0].mTemp < 0 && ltemps[k]->mSrc[1].mTemp < 0 && + (ltemps[k]->mSrc[0].mMemory == IM_LOCAL && !aliasedLocals[ltemps[k]->mSrc[0].mVarIndex] || + (ltemps[k]->mSrc[0].mMemory == IM_PARAM || ltemps[k]->mSrc[0].mMemory == IM_FPARAM) && !aliasedParams[ltemps[k]->mSrc[0].mVarIndex]) && + (ltemps[k]->mSrc[1].mMemory == IM_LOCAL && !aliasedLocals[ltemps[k]->mSrc[1].mVarIndex] || + (ltemps[k]->mSrc[1].mMemory == IM_PARAM || ltemps[k]->mSrc[1].mMemory == IM_FPARAM) && !aliasedParams[ltemps[k]->mSrc[1].mVarIndex])) { - } - else ltemps[j++] = ltemps[k]; + } } ltemps.SetSize(j); } diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index b22d7f7..83a7109 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -46,6 +46,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref) LinkerObject::LinkerObject(void) : mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr) + , mPrefix(nullptr), mSuffix(nullptr) {} LinkerObject::~LinkerObject(void) @@ -307,6 +308,44 @@ bool LinkerObject::IsSameConst(const LinkerObject* obj) const return false; } +int LinkerObject::FirstBank(void) const +{ + if (mRegion->mCartridgeBanks) + { + uint64 m = mRegion->mCartridgeBanks; + int i = 1; + while (!(m & 1)) + { + i++; + m >>= 1; + } + return i; + } + else + return 0; +} + +bool LinkerObject::IsBefore(const LinkerObject* obj) const +{ + if (mFlags & LOBJF_PLACED) + { + if (obj->mFlags & LOBJF_PLACED) + { + int b0 = FirstBank(), b1 = obj->FirstBank(); + if (b0 < b1) + return true; + else if (b0 == b1) + return mAddress < obj->mAddress; + else + return false; + } + else + return true; + } + else + return false; +} + LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment) { LinkerObject* obj = new LinkerObject; @@ -327,6 +366,47 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L return obj; } +static bool Forwards(LinkerObject* pobj, LinkerObject* lobj) +{ + if (lobj->mAlignment == 1 && pobj && lobj->mType == LOT_NATIVE_CODE && pobj->mType == LOT_NATIVE_CODE && lobj->mSection == pobj->mSection) + { + if (pobj->mSize >= 3 && pobj->mData[pobj->mSize - 3] == 0x4c && pobj->mReferences.Size() > 0) + { + int i = 0; + while (i < pobj->mReferences.Size() && pobj->mReferences[i]->mOffset != pobj->mSize - 2) + i++; + if (i < pobj->mReferences.Size() && pobj->mReferences[i]->mRefObject == lobj && pobj->mReferences[i]->mRefOffset == 0) + { + printf("Direct %s -> %s\n", pobj->mIdent->mString, lobj->mIdent->mString); + + pobj->mSuffixReference = i; + + return true; + } + } + } + + return false; +} + + + +void Linker::CheckDirectJumps(void) +{ + for (int i = 0; i < mObjects.Size(); i++) + { + for (int j = 0; j < mObjects.Size(); j++) + { + if (i != j && !mObjects[j]->mPrefix && Forwards(mObjects[i], mObjects[j])) + { + mObjects[i]->mSuffix = mObjects[j]; + mObjects[j]->mPrefix = mObjects[i]; + break; + } + } + } +} + void Linker::CombineSameConst(void) { bool changed = true; @@ -415,32 +495,17 @@ void Linker::ReferenceObject(LinkerObject* obj) } } -static bool Forwards(LinkerObject* pobj, LinkerObject* lobj) -{ - if (lobj->mAlignment == 1 && pobj && lobj->mType == LOT_NATIVE_CODE && pobj->mType == LOT_NATIVE_CODE) - { - if (pobj->mSize >= 3 && pobj->mData[pobj->mSize - 3] == 0x4c && pobj->mReferences.Size() > 0) - { - int i = 0; - while (i < pobj->mReferences.Size() && pobj->mReferences[i]->mOffset != pobj->mSize - 2) - i++; - if (i < pobj->mReferences.Size() && pobj->mReferences[i]->mRefObject == lobj && pobj->mReferences[i]->mRefOffset == 0) - { - printf("Direct %s -> %s\n", pobj->mIdent->mString, lobj->mIdent->mString); - - pobj->mReferences[i]->mFlags = 0; - pobj->mSize -= 3; - - return true; - } - } - } - - return false; -} - bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) { + if (merge && lobj->mPrefix && !(lobj->mPrefix->mFlags & LOBJF_PLACED)) + { + if (!Allocate(linker, lobj->mPrefix, true)) + return false; + + if (lobj->mFlags & LOBJF_PLACED) + return true; + } + int i = 0; while (i < mFreeChunks.Size()) { @@ -451,9 +516,11 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) ; else if (end <= mFreeChunks[i].mEnd) { - // Check if directly follows an object that jumps to this new object - if (merge && Forwards(mFreeChunks[i].mLastObject, lobj)) + if (merge && lobj->mPrefix && lobj->mPrefix == mFreeChunks[i].mLastObject) { + lobj->mPrefix->mReferences[lobj->mPrefix->mSuffixReference]->mFlags = 0; + lobj->mPrefix->mSize -= 3; + start -= 3; end -= 3; } @@ -483,6 +550,12 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) mFreeChunks[i].mEnd = start; } + if (merge && lobj->mSuffix && !(lobj->mSuffix->mFlags & LOBJF_PLACED)) + { + if (!Allocate(linker, lobj->mSuffix, true)) + return false; + } + return true; } i++; @@ -500,8 +573,11 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) if (end <= mEnd) { // Check if directly follows an object that jumps to this new object - if (merge && Forwards(mLastObject, lobj)) + if (merge && lobj->mPrefix && lobj->mPrefix == mLastObject) { + lobj->mPrefix->mReferences[lobj->mPrefix->mSuffixReference]->mFlags = 0; + lobj->mPrefix->mSize -= 3; + start -= 3; end -= 3; mLastObject = nullptr; @@ -520,6 +596,12 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) mLastObject = lobj; + if (merge && lobj->mSuffix && !(lobj->mSuffix->mFlags & LOBJF_PLACED)) + { + if (!Allocate(linker, lobj->mSuffix, true)) + return false; + } + return true; } @@ -735,6 +817,36 @@ void Linker::PlaceObjects(void) } } +void Linker::SortObjectsPartition(int l, int r) +{ + while (l < r) + { + int pi = (l + r) >> 1; + + LinkerObject* po = mObjects[pi]; + mObjects[pi] = mObjects[l]; + + pi = l; + for (int i = l + 1; i < r; i++) + { + if (mObjects[i]->IsBefore(po)) + { + mObjects[pi++] = mObjects[i]; + mObjects[i] = mObjects[pi]; + } + } + mObjects[pi] = po; + + SortObjectsPartition(l, pi); + l = pi + 1; + } +} + +void Linker::SortObjects(void) +{ + SortObjectsPartition(0, mObjects.Size()); +} + void Linker::Link(void) { if (mErrors->mErrorCount == 0) @@ -885,8 +997,9 @@ void Linker::Link(void) } } } - } + + SortObjects(); } static const char * LinkerObjectTypeNames[] = diff --git a/oscar64/Linker.h b/oscar64/Linker.h index a8f30e9..c55611b 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -195,6 +195,8 @@ public: int mNumTemporaries; ZeroPageSet mZeroPageSet; LinkerSection * mStackSection; + LinkerObject * mPrefix, * mSuffix; + int mSuffixReference; ExpandingArray mRanges; ExpandingArray mCodeLocations; @@ -219,6 +221,9 @@ public: void MarkRelevant(void); bool IsSameConst(const LinkerObject* obj) const; + + bool IsBefore(const LinkerObject* obj) const; + int FirstBank(void) const; }; class LinkerOverlay @@ -256,6 +261,8 @@ public: LinkerOverlay* AddOverlay(const Location& location, const Ident* ident, int bank); + void SortObjects(void); + // void AddReference(const LinkerReference& ref); bool WritePrgFile(DiskImage * image, const char* filename); @@ -290,7 +297,8 @@ public: int mProgramStart, mProgramEnd; void ReferenceObject(LinkerObject* obj); - + + void CheckDirectJumps(void); void CollectReferences(void); void CombineSameConst(void); void PatchReferences(bool inlays); @@ -301,5 +309,7 @@ protected: NativeCodeDisassembler mNativeDisassembler; ByteCodeDisassembler mByteCodeDisassembler; + void SortObjectsPartition(int l, int r); + Errors* mErrors; }; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 6fb6392..9ad80b1 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -1161,6 +1161,24 @@ void NativeCodeInstruction::BuildCollisionTable(NumberSet& liveTemps, NumberSet* } } } + else if (mType == ASMIT_RTS) + { + if (mFlags & NCIF_LOWER) + { + UpdateCollisionSet(liveTemps, collisionSets, BC_REG_ACCU + 0); + + if (mFlags & NCIF_UPPER) + { + UpdateCollisionSet(liveTemps, collisionSets, BC_REG_ACCU + 1); + + if (mFlags & NCIF_LONG) + { + UpdateCollisionSet(liveTemps, collisionSets, BC_REG_ACCU + 2); + UpdateCollisionSet(liveTemps, collisionSets, BC_REG_ACCU + 3); + } + } + } + } } @@ -2540,6 +2558,36 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI else if (mMode == ASMIM_ZERO_PAGE) iaddr = mAddress; + int opmask = 0, opvalue = 0; + if (mMode == ASMIM_IMMEDIATE) + { + opmask = 0xff; + opvalue = mAddress; + } + else if (mMode == ASMIM_ZERO_PAGE) + { + opmask = data.mRegs[mAddress].mMask; + opvalue = data.mRegs[mAddress].mValue; + } +#if 1 + else if ((mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y) && mLinkerObject && (mLinkerObject->mFlags & LOBJF_CONST) && mLinkerObject->mSize <= 256 && mLinkerObject->mReferences.Size() == 0 && mType != ASMIT_JSR) + { + int mor = 0; + int mand = 0xff; + for (int i = 0; i < mLinkerObject->mSize; i++) + { + mor |= mLinkerObject->mData[i]; + mand &= mLinkerObject->mData[i]; + } + opmask = (mand | ~mor) & 0xff; + opvalue = mand; +#if 0 + if (opmask) + printf("Check %s, %02x %02x\n", mLinkerObject->mIdent->mString, opmask, opvalue); +#endif + } +#endif + switch (mType) { case ASMIT_JSR: @@ -2625,6 +2673,21 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI data.mRegs[CPU_REG_C].mValue = 0; } } + else if (data.mRegs[CPU_REG_C].mMask == 1 && data.mRegs[CPU_REG_C].mValue == 0) + { + if ((((~opmask | opvalue) & (~data.mRegs[CPU_REG_A].mMask | data.mRegs[CPU_REG_A].mValue)) & 0xff) == 0) + { + mType = ASMIT_ORA; + data.mRegs[CPU_REG_A].mValue |= opvalue; + data.mRegs[CPU_REG_A].mMask &= opmask; + changed = true; + } + else + { + data.mRegs[CPU_REG_C].mMask = 0; + data.mRegs[CPU_REG_A].mMask = 0; + } + } else { data.mRegs[CPU_REG_C].mMask = 0; @@ -2638,26 +2701,23 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI break; case ASMIT_LDA: - if (mMode == ASMIM_ZERO_PAGE) - { - data.mRegs[CPU_REG_A].mMask = data.mRegs[mAddress].mMask; - data.mRegs[CPU_REG_A].mValue = data.mRegs[mAddress].mValue; - - if (data.mRegs[CPU_REG_A].mMask == 0xff) - { - mType = ASMIT_LDA; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_A].mValue; - changed = true; - } - } - else if (mMode == ASMIM_IMMEDIATE) + if (mMode == ASMIM_IMMEDIATE) { data.mRegs[CPU_REG_A].mMask = 0xff; data.mRegs[CPU_REG_A].mValue = mAddress & 0xff; } else - data.mRegs[CPU_REG_A].mMask = 0; + { + data.mRegs[CPU_REG_A].mMask = opmask; + data.mRegs[CPU_REG_A].mValue = opvalue; + if (opmask == 0xff) + { + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = opvalue; + changed = true; + } + } break; case ASMIT_STA: if (mMode == ASMIM_ZERO_PAGE) @@ -2668,26 +2728,23 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI break; case ASMIT_LDX: - if (mMode == ASMIM_ZERO_PAGE) - { - data.mRegs[CPU_REG_X].mMask = data.mRegs[mAddress].mMask; - data.mRegs[CPU_REG_X].mValue = data.mRegs[mAddress].mValue; - - if (data.mRegs[CPU_REG_X].mMask == 0xff) - { - mType = ASMIT_LDX; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_X].mValue; - changed = true; - } - } - else if (mMode == ASMIM_IMMEDIATE) + if (mMode == ASMIM_IMMEDIATE) { data.mRegs[CPU_REG_X].mMask = 0xff; data.mRegs[CPU_REG_X].mValue = mAddress & 0xff; } else - data.mRegs[CPU_REG_X].mMask = 0; + { + data.mRegs[CPU_REG_X].mMask = opmask; + data.mRegs[CPU_REG_X].mValue = opvalue; + if (opmask == 0xff) + { + mType = ASMIT_LDX; + mMode = ASMIM_IMMEDIATE; + mAddress = opvalue; + changed = true; + } + } break; case ASMIT_STX: if (mMode == ASMIM_ZERO_PAGE) @@ -2698,26 +2755,23 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI break; case ASMIT_LDY: - if (mMode == ASMIM_ZERO_PAGE) - { - data.mRegs[CPU_REG_Y].mMask = data.mRegs[mAddress].mMask; - data.mRegs[CPU_REG_Y].mValue = data.mRegs[mAddress].mValue; - - if (data.mRegs[CPU_REG_Y].mMask == 0xff) - { - mType = ASMIT_LDY; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_Y].mValue; - changed = true; - } - } - else if (mMode == ASMIM_IMMEDIATE) + if (mMode == ASMIM_IMMEDIATE) { data.mRegs[CPU_REG_Y].mMask = 0xff; data.mRegs[CPU_REG_Y].mValue = mAddress & 0xff; } else - data.mRegs[CPU_REG_Y].mMask = 0; + { + data.mRegs[CPU_REG_Y].mMask = opmask; + data.mRegs[CPU_REG_Y].mValue = opvalue; + if (opmask == 0xff) + { + mType = ASMIT_LDY; + mMode = ASMIM_IMMEDIATE; + mAddress = opvalue; + changed = true; + } + } break; case ASMIT_STY: if (mMode == ASMIM_ZERO_PAGE) @@ -2728,102 +2782,48 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI break; case ASMIT_AND: - if (mMode == ASMIM_ZERO_PAGE) + { + int zeros = + (opmask & ~opvalue) | + (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + int ones = + (opmask & opvalue) & + (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; + data.mRegs[CPU_REG_A].mValue = ones & 0xff; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) { - int zeros = - (data.mRegs[mAddress].mMask & ~data.mRegs[mAddress].mValue) | - (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); - - int ones = - (data.mRegs[mAddress].mMask & data.mRegs[mAddress].mValue) & - (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); - - data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; - data.mRegs[CPU_REG_A].mValue = ones & 0xff; - - if (data.mRegs[CPU_REG_A].mMask == 0xff) - { - mType = ASMIT_LDA; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_A].mValue; - changed = true; - } + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; } - else if (mMode == ASMIM_IMMEDIATE) - { - if (mAddress != 0xff && ((data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue) | mAddress) == 0xff) - { - mAddress = 0xff; - changed = true; - } - - int zeros = ~mAddress | (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); - - int ones = mAddress & (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); - - data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; - data.mRegs[CPU_REG_A].mValue = ones & 0xff; - - if (data.mRegs[CPU_REG_A].mMask == 0xff) - { - mType = ASMIT_LDA; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_A].mValue; - changed = true; - } - } - else - data.mRegs[CPU_REG_A].mMask &= ~data.mRegs[CPU_REG_A].mValue; - break; + } break; case ASMIT_ORA: - if (mMode == ASMIM_ZERO_PAGE) + { + int ones = + (opmask & opvalue) | + (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); + + int zeros = + (opmask & ~opvalue) & + (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); + + data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; + data.mRegs[CPU_REG_A].mValue = ones & 0xff; + + if (data.mRegs[CPU_REG_A].mMask == 0xff) { - int ones = - (data.mRegs[mAddress].mMask & data.mRegs[mAddress].mValue) | - (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); - - int zeros = - (data.mRegs[mAddress].mMask & ~data.mRegs[mAddress].mValue) & - (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); - - data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; - data.mRegs[CPU_REG_A].mValue = ones & 0xff; - - if (data.mRegs[CPU_REG_A].mMask == 0xff) - { - mType = ASMIT_LDA; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_A].mValue; - changed = true; - } + mType = ASMIT_LDA; + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; } - else if (mMode == ASMIM_IMMEDIATE) - { - if (mAddress != 0x00 && (~(data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue) & mAddress) == 0x00) - { - mAddress = 0x00; - changed = true; - } - - int ones = mAddress | (data.mRegs[CPU_REG_A].mMask & data.mRegs[CPU_REG_A].mValue); - - int zeros = ~ mAddress & (data.mRegs[CPU_REG_A].mMask & ~data.mRegs[CPU_REG_A].mValue); - - data.mRegs[CPU_REG_A].mMask = (ones | zeros) & 0xff; - data.mRegs[CPU_REG_A].mValue = ones & 0xff; - - if (data.mRegs[CPU_REG_A].mMask == 0xff) - { - mType = ASMIT_LDA; - mMode = ASMIM_IMMEDIATE; - mAddress = data.mRegs[CPU_REG_A].mValue; - changed = true; - } - } - else - data.mRegs[CPU_REG_A].mMask &= data.mRegs[CPU_REG_A].mValue; - break; + } break; case ASMIT_EOR: data.mRegs[CPU_REG_A].mMask = 0; @@ -17270,6 +17270,108 @@ bool NativeCodeBasicBlock::SinglePathRegisterForwardY(NativeCodeBasicBlock* path return false; } +bool NativeCodeBasicBlock::SinglePathStoreForward(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (mFalseJump) + { + NumberSet touched(NUM_REGS); + + int i = mIns.Size(); + while (i > 0) + { + i--; + if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && !touched[mIns[i].mAddress] && !touched[CPU_REG_A]) + { + if (mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && !mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && mTrueJump->mNumEntries == 1) + { + mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STA, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_A; + mExitRequiredRegs += CPU_REG_A; + mTrueJump->mEntryRequiredRegs += CPU_REG_A; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + else if (mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && !mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && mFalseJump->mNumEntries == 1) + { + mFalseJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STA, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_A; + mExitRequiredRegs += CPU_REG_A; + mFalseJump->mEntryRequiredRegs += CPU_REG_A; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + } + if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ZERO_PAGE && !touched[mIns[i].mAddress] && !touched[CPU_REG_X]) + { + if (mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && !mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && mTrueJump->mNumEntries == 1) + { + mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STX, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_X; + mExitRequiredRegs += CPU_REG_X; + mTrueJump->mEntryRequiredRegs += CPU_REG_X; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + else if (mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && !mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && mFalseJump->mNumEntries == 1) + { + mFalseJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STX, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_X; + mExitRequiredRegs += CPU_REG_X; + mFalseJump->mEntryRequiredRegs += CPU_REG_X; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + } + if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE && !touched[mIns[i].mAddress] && !touched[CPU_REG_Y]) + { + if (mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && !mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && mTrueJump->mNumEntries == 1) + { + mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STY, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + mTrueJump->mEntryRequiredRegs += CPU_REG_Y; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + else if (mFalseJump->mEntryRequiredRegs[mIns[i].mAddress] && !mTrueJump->mEntryRequiredRegs[mIns[i].mAddress] && mFalseJump->mNumEntries == 1) + { + mFalseJump->mIns.Insert(0, NativeCodeInstruction(mIns[i].mIns, ASMIT_STY, mIns[i])); + for (int j = i; j < mIns.Size(); j++) mIns[j].mLive |= LIVE_CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + mFalseJump->mEntryRequiredRegs += CPU_REG_Y; + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } + } + + if (mIns[i].ChangesAccu()) touched += CPU_REG_A; + if (mIns[i].ChangesXReg()) touched += CPU_REG_X; + if (mIns[i].ChangesYReg()) touched += CPU_REG_Y; + if (mIns[i].mMode == ASMIM_ZERO_PAGE) touched += mIns[i].mAddress; + if (mIns[i].mMode == ASMIM_INDIRECT_Y) + { + touched += mIns[i].mAddress; + touched += mIns[i].mAddress + 1; + } + if (mIns[i].mType == ASMIT_JSR) + break; + } + } + if (mTrueJump && mTrueJump->SinglePathStoreForward()) + changed = true; + if (mFalseJump && mFalseJump->SinglePathStoreForward()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::SinglePathRegisterForward(void) { bool changed = false; @@ -20203,6 +20305,8 @@ void NativeCodeBasicBlock::PrependInstruction(const NativeCodeInstruction& ins) mIns[0].mLive |= LIVE_CPU_REG_Y; if (mEntryRequiredRegs[CPU_REG_C]) mIns[0].mLive |= LIVE_CPU_REG_C; + if (ins.mMode == ASMIM_ZERO_PAGE && ins.UsesAddress()) + mEntryRequiredRegs += ins.mAddress; } bool NativeCodeBasicBlock::ShortcutBlockExit(void) @@ -20327,6 +20431,9 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void) { if (mIns[i - 1].mMode == ASMIM_IMMEDIATE || (mIns[i - 1].mMode == ASMIM_ZERO_PAGE && !ChangedOnPath(this, i, mIns.Size(), mIns[i - 1].mAddress))) { + if (mIns[i - 1].mMode == ASMIM_ZERO_PAGE) + mExitRequiredRegs += mIns[i - 1].mAddress; + if (mTrueJump->mEntryRequiredRegs[CPU_REG_A]) mTrueJump->PrependInstruction(mIns[i - 1]); else @@ -20363,6 +20470,9 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void) { if (mIns[i - 1].mMode == ASMIM_IMMEDIATE || (mIns[i - 1].mMode == ASMIM_ZERO_PAGE && !ChangedOnPath(this, i, mIns.Size(), mIns[i - 1].mAddress))) { + if (mIns[i - 1].mMode == ASMIM_ZERO_PAGE) + mExitRequiredRegs += mIns[i - 1].mAddress; + if (mTrueJump->mEntryRequiredRegs[CPU_REG_X]) mTrueJump->PrependInstruction(mIns[i - 1]); else @@ -20382,6 +20492,9 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void) { if (mIns[i - 1].mMode == ASMIM_IMMEDIATE || (mIns[i - 1].mMode == ASMIM_ZERO_PAGE && !ChangedOnPath(this, i, mIns.Size(), mIns[i - 1].mAddress))) { + if (mIns[i - 1].mMode == ASMIM_ZERO_PAGE) + mExitRequiredRegs += mIns[i - 1].mAddress; + if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y]) mTrueJump->PrependInstruction(mIns[i - 1]); else @@ -20392,6 +20505,7 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void) } else if (i > 0 && mIns[i - 1].mType == ASMIT_TAY && !(mIns[i - 1].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A)) && !ChangesAccuOnPath(this, i, mIns.Size())) { + mExitRequiredRegs += CPU_REG_A; if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y]) mTrueJump->PrependInstruction(mIns[i - 1]); else @@ -25589,64 +25703,138 @@ bool NativeCodeBasicBlock::PatchCrossBlockY2XFloodExit(const NativeCodeBasicBloc return false; } -void NativeCodeBasicBlock::PropagateZPAbsolute(void) +void NativeCodeBasicBlock::PropagateZPAbsolute(const NativeRegisterDataSet& data) { if (!mVisited) { - mVisited = true; + mDataSet = data; - mDataSet.Reset(); + assert(mIndex == 1000 || mNumEntries == mEntryBlocks.Size()); - for (int i = 0; i < mIns.Size(); i++) + if (mLoopHead) { - if (i + 1 < mIns.Size() && - mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE) && - mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) - { - int r = mIns[i + 1].mAddress; + mDataSet.Reset(); + } + else if (mNumEntries > 0) + { + if (mNumEntered > 0) + mDataSet.Intersect(mNDataSet); - mDataSet.mRegs[r].mMode = NRDM_ABSOLUTE; - mDataSet.mRegs[r].mLinkerObject = mIns[i].mLinkerObject; - mDataSet.mRegs[r].mValue = mIns[i].mAddress; - mDataSet.mRegs[r].mFlags = mIns[i].mFlags; - i++; - } - else if (mIns[i].mType == ASMIT_JSR) - mDataSet.Reset(); - else if (mIns[i].mMode == ASMIM_ZERO_PAGE) - { - int r = mIns[i].mAddress; + mNumEntered++; - if (mIns[i].ChangesAddress()) - mDataSet.ResetZeroPage(r); - else if (mDataSet.mRegs[r].mMode == NRDM_ABSOLUTE) - { - mIns[i].mMode = ASMIM_ABSOLUTE; - mIns[i].mLinkerObject = mDataSet.mRegs[r].mLinkerObject; - mIns[i].mAddress = mDataSet.mRegs[r].mValue; - } - } - else if (mIns[i].mMode == ASMIM_ABSOLUTE || mIns[i].mMode == ASMIM_ABSOLUTE_X || mIns[i].mMode == ASMIM_ABSOLUTE_Y) + if (mNumEntered < mNumEntries) { - if (mIns[i].ChangesAddress()) - mDataSet.ResetAbsolute(mIns[i].mLinkerObject, mIns[i].mAddress); - } - else if (mIns[i].mMode == ASMIM_INDIRECT_Y) - { - int r = mIns[i].mAddress; - - if (mDataSet.mRegs[r].mMode == NRDM_ABSOLUTE && mDataSet.mRegs[r + 1].mMode == NRDM_ABSOLUTE && - mDataSet.mRegs[r].mLinkerObject == mDataSet.mRegs[r + 1].mLinkerObject && - mDataSet.mRegs[r].mValue + 1 == mDataSet.mRegs[r + 1].mValue) - { - mIns[i].mLinkerObject = mDataSet.mRegs[r].mLinkerObject; - mIns[i].mAddress = mDataSet.mRegs[r].mValue; - } + mNDataSet = mDataSet; + return; } } - if (mTrueJump) mTrueJump->PropagateZPAbsolute(); - if (mFalseJump) mFalseJump->PropagateZPAbsolute(); + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_A].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_A].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_A].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_LDX && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.mRegs[CPU_REG_X].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_X].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_X].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_X].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.mRegs[CPU_REG_Y].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_Y].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_Y].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_Y].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.ResetAbsolute(mIns[i].mLinkerObject, mIns[i].mAddress); + mDataSet.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_A].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_A].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_A].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.ResetAbsolute(mIns[i].mLinkerObject, mIns[i].mAddress); + mDataSet.mRegs[CPU_REG_X].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_X].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_X].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_X].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ABSOLUTE && mIns[i].mLinkerObject && (mIns[i].mLinkerObject->mFlags & LOBJF_ZEROPAGE)) + { + mDataSet.ResetAbsolute(mIns[i].mLinkerObject, mIns[i].mAddress); + mDataSet.mRegs[CPU_REG_Y].mMode = NRDM_ABSOLUTE; + mDataSet.mRegs[CPU_REG_Y].mLinkerObject = mIns[i].mLinkerObject; + mDataSet.mRegs[CPU_REG_Y].mValue = mIns[i].mAddress; + mDataSet.mRegs[CPU_REG_Y].mFlags = mIns[i].mFlags; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE) + mDataSet.mRegs[mIns[i].mAddress] = mDataSet.mRegs[CPU_REG_A]; + else if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ZERO_PAGE) + mDataSet.mRegs[mIns[i].mAddress] = mDataSet.mRegs[CPU_REG_X]; + else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE) + mDataSet.mRegs[mIns[i].mAddress] = mDataSet.mRegs[CPU_REG_Y]; + else if (mIns[i].mType == ASMIT_JSR) + mDataSet.Reset(); + else + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE) + { + int r = mIns[i].mAddress; + + if (mIns[i].ChangesAddress()) + mDataSet.ResetZeroPage(r); + else if (mDataSet.mRegs[r].mMode == NRDM_ABSOLUTE) + { + mIns[i].mMode = ASMIM_ABSOLUTE; + mIns[i].mLinkerObject = mDataSet.mRegs[r].mLinkerObject; + mIns[i].mAddress = mDataSet.mRegs[r].mValue; + } + } + else if (mIns[i].mMode == ASMIM_ABSOLUTE) + { + if (mIns[i].ChangesAddress()) + mDataSet.ResetAbsolute(mIns[i].mLinkerObject, mIns[i].mAddress); + } + else if (mIns[i].mMode == ASMIM_ABSOLUTE_X || mIns[i].mMode == ASMIM_ABSOLUTE_Y) + { + if (mIns[i].ChangesAddress()) + mDataSet.ResetAbsoluteXY(mIns[i].mLinkerObject, mIns[i].mAddress); + } + else if (mIns[i].mMode == ASMIM_INDIRECT_Y) + { + int r = mIns[i].mAddress; + + if (mDataSet.mRegs[r].mMode == NRDM_ABSOLUTE && mDataSet.mRegs[r + 1].mMode == NRDM_ABSOLUTE && + mDataSet.mRegs[r].mLinkerObject == mDataSet.mRegs[r + 1].mLinkerObject && + mDataSet.mRegs[r].mValue + 1 == mDataSet.mRegs[r + 1].mValue) + { + mIns[i].mLinkerObject = mDataSet.mRegs[r].mLinkerObject; + mIns[i].mAddress = mDataSet.mRegs[r].mValue; + } + } + + if (mIns[i].ChangesAccu()) + mDataSet.mRegs[CPU_REG_A].Reset(); + if (mIns[i].ChangesXReg()) + mDataSet.mRegs[CPU_REG_X].Reset(); + if (mIns[i].ChangesYReg()) + mDataSet.mRegs[CPU_REG_Y].Reset(); + } + } + + if (mTrueJump) mTrueJump->PropagateZPAbsolute(mDataSet); + if (mFalseJump) mFalseJump->PropagateZPAbsolute(mDataSet); } } @@ -36129,6 +36317,28 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen j += 3; i += 5; } + else if (i + 2 < mIns.Size() && + mIns[i + 0].mType == ASMIT_LDX && HasAsmInstructionMode(ASMIT_INC, mIns[i + 0].mMode) && + mIns[i + 1].mType == ASMIT_INX && + mIns[i + 2].mType == ASMIT_STX && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && + !(mIns[i + 2].mLive & LIVE_CPU_REG_X)) + { + mIns[j + 0] = mIns[i + 0]; + mIns[j + 0].mType = ASMIT_INC; + j += 1; + i += 3; + } + else if (i + 2 < mIns.Size() && + mIns[i + 0].mType == ASMIT_LDX && HasAsmInstructionMode(ASMIT_DEC, mIns[i + 0].mMode) && + mIns[i + 1].mType == ASMIT_DEX && + mIns[i + 2].mType == ASMIT_STX && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && + !(mIns[i + 2].mLive & LIVE_CPU_REG_X)) + { + mIns[j + 0] = mIns[i + 0]; + mIns[j + 0].mType = ASMIT_DEC; + j += 1; + i += 3; + } else if (i + 2 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && @@ -36212,16 +36422,66 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen i += 4; } #endif + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_INC, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 1]) && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_INC; + j += 1; + i += 4; + } + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_SEC && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_DEC, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 1]) && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_DEC; + j += 1; + i += 4; + } + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_INC, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 1]) && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_DEC; + j += 1; + i += 4; + } + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_SEC && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_DEC, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 1]) && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_INC; + j += 1; + i += 4; + } + else if (i + 3 < mIns.Size() && mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && - mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 3].mMode) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) { - mIns[j + 0] = NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_LDX, mIns[i + 1]); + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_LDX; mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED; - mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress; mIns[j + 2].mLinkerObject = nullptr; + mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].CopyMode(mIns[i + 3]); j += 3; i += 4; } @@ -36229,12 +36489,13 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen mIns[i + 0].mType == ASMIT_SEC && mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) && mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && - mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 3].mMode) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) { - mIns[j + 0] = NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_LDX, mIns[i + 1]); + mIns[j + 0] = mIns[i + 1]; + mIns[j + 0].mType = ASMIT_LDX; mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED; - mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress; mIns[j + 2].mLinkerObject = nullptr; + mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].CopyMode(mIns[i + 3]); j += 3; i += 4; } @@ -36270,13 +36531,13 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen else if (i + 3 < mIns.Size() && mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) && - mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && mIns[i + 3].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 3].mMode) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) { mIns[j + 0] = mIns[i + 1]; mIns[j + 0].mType = ASMIT_LDX; - mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED; + mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED; mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].CopyMode(mIns[i + 3]); j += 3; i += 4; @@ -36284,13 +36545,13 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen else if (i + 3 < mIns.Size() && mIns[i + 0].mType == ASMIT_SEC && mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) && - mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && mIns[i + 3].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 3].mMode) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) { mIns[j + 0] = mIns[i + 1]; mIns[j + 0].mType = ASMIT_LDX; - mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED; + mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED; mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].CopyMode(mIns[i + 3]); j += 3; i += 4; @@ -43342,6 +43603,105 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif } +#if 1 + if (pass == 0 && + i + 7 < mIns.Size() && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 1].mFlags & NCIF_LOWER) && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + + mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 4].mFlags & NCIF_UPPER) && (mIns[i +4].mLinkerObject == mIns[i + 1].mLinkerObject) && + mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && + mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 2].mAddress + 1 && + mIns[i + 7].mType == ASMIT_STA && mIns[i + 7].mMode == ASMIM_ZERO_PAGE && mIns[i + 7].mAddress == mIns[i + 3].mAddress + 1 && + !(mIns[i + 7].mLive & LIVE_CPU_REG_A)) + { + proc->ResetPatched(); + if (CheckGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, i + 8, -1)) + { + NativeCodeInstruction ins(mIns[i + 2]); + mIns[i + 2] = mIns[i + 1]; + mIns[i + 1] = ins; + + mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED; + + proc->ResetPatched(); + if (PatchGlobalAddressSumYPointer(this, mIns[i + 1].mAddress, mIns[i + 1].mAddress, i + 8, -1, mIns[i + 2].mLinkerObject, mIns[i + 2].mAddress + mIns[i + 5].mAddress * 256)) + progress = true; + } + else + { + proc->ResetPatched(); + if (CheckGlobalAddressSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, i + 8, -1)) + { + NativeCodeInstruction ins(mIns[i + 3]); + mIns[i + 3] = mIns[i + 2]; + mIns[i + 2] = mIns[i + 1]; + mIns[i + 1] = ins; + + mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED; + + proc->ResetPatched(); + if (PatchGlobalAddressSumYPointer(this, mIns[i + 1].mAddress, mIns[i + 1].mAddress, i + 8, -1, mIns[i + 2].mLinkerObject, mIns[i + 2].mAddress + mIns[i + 5].mAddress * 256)) + progress = true; + } + } + } + if (pass == 0 && + i + 8 < mIns.Size() && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 1].mFlags & NCIF_LOWER) && + mIns[i + 2].mType == ASMIT_ADC && (mIns[i + 2].mMode == ASMIM_ZERO_PAGE || mIns[i + 2].mMode == ASMIM_ABSOLUTE) && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && + + mIns[i + 5].mType == ASMIT_LDA && mIns[i + 5].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[i + 5].mFlags & NCIF_UPPER) && (mIns[i + 5].mLinkerObject == mIns[i + 1].mLinkerObject) && + mIns[i + 6].mType == ASMIT_ADC && mIns[i + 6].mMode == ASMIM_IMMEDIATE && + mIns[i + 7].mType == ASMIT_STA && mIns[i + 7].mMode == ASMIM_ZERO_PAGE && mIns[i + 7].mAddress == mIns[i + 3].mAddress + 1 && + mIns[i + 8].mType == ASMIT_STA && mIns[i + 8].mMode == ASMIM_ZERO_PAGE && mIns[i + 8].mAddress == mIns[i + 4].mAddress + 1 && + !(mIns[i + 8].mLive & LIVE_CPU_REG_A)) + { + proc->ResetPatched(); + if (CheckGlobalAddressSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, i + 9, -1)) + { + NativeCodeInstruction ins(mIns[i + 3]); + mIns[i + 3] = mIns[i + 1]; + mIns[i + 1] = mIns[i + 2]; + mIns[i + 2] = ins; + + mIns[i + 1].mType = ASMIT_LDA; + mIns[i + 3].mType = ASMIT_ADC; + + mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED; + + proc->ResetPatched(); + if (PatchGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, i + 9, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress + mIns[i + 6].mAddress * 256)) + progress = true; + } +#if 0 + else + { + proc->ResetPatched(); + if (CheckGlobalAddressSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, i + 8, -1)) + { + NativeCodeInstruction ins(mIns[i + 3]); + mIns[i + 3] = mIns[i + 2]; + mIns[i + 2] = mIns[i + 1]; + mIns[i + 1] = ins; + + mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED; + + proc->ResetPatched(); + if (PatchGlobalAddressSumYPointer(this, mIns[i + 1].mAddress, mIns[i + 1].mAddress, i + 8, -1, mIns[i + 2].mLinkerObject, mIns[i + 2].mAddress + mIns[i + 5].mAddress * 256)) + progress = true; + } + } +#endif + } +#endif + + if (i + 5 < mIns.Size() && mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED && mIns[i + 1].mType == ASMIT_LSR && mIns[i + 1].mMode == ASMIM_IMPLIED && @@ -44770,7 +45130,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_builtin"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -44871,6 +45231,8 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) #endif } + mGenerator->PopulateShortMulTables(); + Optimize(); if (mEntryBlock->mIns.Size() > 0) @@ -45573,7 +45935,6 @@ void NativeCodeProcedure::Optimize(void) if (mEntryBlock->PeepHoleOptimizer(this, step)) changed = true; - #endif if (step == 2) { @@ -45696,6 +46057,7 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->CheckBlocks(true); #endif + #if 1 if (step > 2 && !changed) { @@ -45709,6 +46071,7 @@ void NativeCodeProcedure::Optimize(void) ResetVisited(); if (mEntryBlock->PropagateSinglePath()) changed = true; + } @@ -45961,8 +46324,21 @@ void NativeCodeProcedure::Optimize(void) ResetVisited(); if (mEntryBlock->SinglePathRegisterForward()) changed = true; + } + if (step > 7) + { + ResetVisited(); + if (mEntryBlock->SinglePathStoreForward()) + changed = true; + } + +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckBlocks(); +#endif + if (step == 7) { ResetVisited(); @@ -46227,10 +46603,12 @@ void NativeCodeProcedure::Optimize(void) #if 1 if (!changed && step < 12) { + ResetIndexFlipped(); + cnt = 0; step++; changed = true; - + swappedXY = false; } #endif else @@ -46318,8 +46696,10 @@ void NativeCodeProcedure::Optimize(void) ResetVisited(); mEntryBlock->CrossBlockFlagsForwarding(); + ResetVisited(); - mEntryBlock->PropagateZPAbsolute(); + data.Reset(); + mEntryBlock->PropagateZPAbsolute(data); BuildDataFlowSets(); ResetVisited(); @@ -46404,6 +46784,16 @@ void NativeCodeProcedure::ResetEntryBlocks(void) mBlocks[i]->mEntryBlocks.SetSize(0); } +void NativeCodeProcedure::ResetIndexFlipped(void) +{ + for (int i = 0; i < mBlocks.Size(); i++) + { + for (int j = 0; j < mBlocks[i]->mIns.Size(); j++) + mBlocks[i]->mIns[j].mFlags &= ~NICT_INDEXFLIPPED; + } +} + + void NativeCodeProcedure::ResetPatched(void) { for (int i = 0; i < mBlocks.Size(); i++) @@ -46961,39 +47351,47 @@ NativeCodeGenerator::~NativeCodeGenerator(void) } void NativeCodeGenerator::CompleteRuntime(void) +{ + PopulateShortMulTables(); +} + + +void NativeCodeGenerator::PopulateShortMulTables(void) { for (int i = 0; i < mMulTables.Size(); i++) { const MulTable& m(mMulTables[i]); - m.mLinkerLSB->AddSpace(m.mSize); - m.mLinkerMSB->AddSpace(m.mSize); - - for (int j = 0; j < m.mSize; j++) + if (m.mLinkerLSB->mSize != m.mSize) { - int val = m.mFactor; - switch (m.mOperator) - { - case IA_MUL: - val *= j; - break; - case IA_SHL: - val <<= j; - break; - case IA_SHR: - val = (val & 0xffff) >> j; - break; - case IA_SAR: - val = (int)(short)val >> j; - break; - } + m.mLinkerLSB->AddSpace(m.mSize); + m.mLinkerMSB->AddSpace(m.mSize); - m.mLinkerLSB->mData[j] = (uint8)(val); - m.mLinkerMSB->mData[j] = (uint8)(val >> 8); + for (int j = 0; j < m.mSize; j++) + { + int val = m.mFactor; + switch (m.mOperator) + { + case IA_MUL: + val *= j; + break; + case IA_SHL: + val <<= j; + break; + case IA_SHR: + val = (val & 0xffff) >> j; + break; + case IA_SAR: + val = (int)(short)val >> j; + break; + } + + m.mLinkerLSB->mData[j] = (uint8)(val); + m.mLinkerMSB->mData[j] = (uint8)(val >> 8); + } } } } - LinkerObject* NativeCodeGenerator::AllocateShortMulTable(InterOperator op, int factor, int size, bool msb) { assert(size > 0); @@ -47031,6 +47429,9 @@ LinkerObject* NativeCodeGenerator::AllocateShortMulTable(InterOperator op, int f sprintf_s(name, "__%stab%dH", base, factor); mt.mLinkerMSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA); + mt.mLinkerLSB->mFlags |= LOBJF_CONST; + mt.mLinkerMSB->mFlags |= LOBJF_CONST; + mt.mFactor = factor; mt.mSize = size; mt.mOperator = op; @@ -47188,8 +47589,80 @@ void NativeCodeGenerator::BuildFunctionProxies(void) FunctionCall* cp = mFunctionCalls; while (cp) { + ExpandingArray ocalls; + FunctionCall* ncp = cp; while (ncp) + { + if (ncp->mCount == 1) + ocalls.Push(ncp); + ncp = ncp->mSame; + } + + // Loop while we have unmatched calls + while (ocalls.Size() > 1) + { + int i = 0; + while (i < ocalls.Size()) + { + int j = 0; + while (j < ocalls.Size() && (i == j || ocalls[i]->PotentialMatches(ocalls[j]) == 0)) + j++; + if (j == ocalls.Size()) + ocalls.Remove(i); + else + i++; + } + + if (ocalls.Size() > 1) + { + // Find best matching pair + int besti = 0, bestj = 0, bestm = 0; + for (int i = 0; i < ocalls.Size(); i++) + { + for (int j = i + 1; j < ocalls.Size(); j++) + { + int m = ocalls[i]->PotentialMatches(ocalls[j]); + if (m > bestm) + { + besti = i; + bestj = j; + bestm = m; + } + } + } + + FunctionCall* fi = ocalls[besti], * fj = ocalls[bestj]; + + ocalls.Remove(besti); + + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + if (fi->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) + { + if (!fi->mIns[i - BC_REG_FPARAMS].IsSame(fj->mIns[i - BC_REG_FPARAMS])) + { + fi->mIns[i - BC_REG_FPARAMS].mType = ASMIT_INV; + } + } + } + + int i = 0; + while (i < ocalls.Size()) + { + if (ocalls[i]->Matches(fi) > 0) + { + ocalls.Remove(i); + fi->mCount++; + } + else + i++; + } + } + } + + ncp = cp; + while (ncp) { if (ncp->mCount > 1) { @@ -47329,3 +47802,19 @@ int NativeCodeGenerator::FunctionCall::Matches(const FunctionCall* fc) const return match; } +int NativeCodeGenerator::FunctionCall::PotentialMatches(const FunctionCall* fc) const +{ + int match = 0; + + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) + { + if (mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) + match++; + } + } + + return match; +} + diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index b8fa4f7..bb677fd 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -615,6 +615,7 @@ public: bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg); bool SinglePathRegisterForward(void); + bool SinglePathStoreForward(void); bool CanBytepassLoad(const NativeCodeInstruction& ains, int from = 0) const; bool CanHoistStore(const NativeCodeInstruction& ains) const; @@ -717,7 +718,7 @@ public: bool PatchCrossBlockY2XFlood(const NativeCodeBasicBlock* block, int at); bool PatchCrossBlockY2XFloodExit(const NativeCodeBasicBlock* block); - void PropagateZPAbsolute(void); + void PropagateZPAbsolute(const NativeRegisterDataSet& data); void RegisterFunctionCalls(void); bool MergeFunctionCalls(void); @@ -770,6 +771,7 @@ class NativeCodeProcedure void ResetVisited(void); void ResetPatched(void); void RebuildEntry(void); + void ResetIndexFlipped(void); void SaveTempsToStack(int tempSave); void LoadTempsFromStack(int tempSave); @@ -801,6 +803,7 @@ public: }; LinkerObject* AllocateShortMulTable(InterOperator op, int factor, int size, bool msb); + void PopulateShortMulTables(void); Runtime& ResolveRuntime(const Ident* ident); @@ -820,6 +823,7 @@ public: bool IsSame(const FunctionCall* fc) const; int Matches(const FunctionCall* fc) const; + int PotentialMatches(const FunctionCall* fc) const; }; FunctionCall* mFunctionCalls;