From 3351ee81ccd992d595da7bd9b708d5ad971ceaf8 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 22 May 2022 13:22:36 +0200 Subject: [PATCH] Extend static stack allocation to zero page spilling --- include/crt.c | 35 ++++- oscar64/ByteCodeGenerator.cpp | 2 +- oscar64/Compiler.cpp | 2 + oscar64/Declaration.h | 3 +- oscar64/GlobalAnalyzer.cpp | 30 ++++ oscar64/GlobalAnalyzer.h | 1 + oscar64/InterCode.cpp | 9 +- oscar64/InterCode.h | 5 +- oscar64/InterCodeGenerator.cpp | 3 + oscar64/NativeCodeGenerator.cpp | 257 ++++++++++++++++++++++++++++---- oscar64/NativeCodeGenerator.h | 2 + 11 files changed, 311 insertions(+), 38 deletions(-) diff --git a/include/crt.c b/include/crt.c index a438bc3..3d96551 100644 --- a/include/crt.c +++ b/include/crt.c @@ -2432,7 +2432,40 @@ L1: iny __asm inp_copyl { - jmp startup.exec + lda (ip), y + sta tmp + iny + lda (ip), y + tax + sty tmpy + + beq W1 + ldy #0 +Loop1: + lda (accu), y + sta (addr), y + iny + bne Loop1 + inc accu + 1 + inc addr + 1 + dex + bne Loop1 +W1: + ldy tmp + beq W2 + dey + beq W3 +Loop2: + lda (accu), y + sta (addr), y + dey + bne Loop2 +W3: + lda (accu), y + sta (addr), y +W2: + ldy tmpy + jmp startup.yexec } #pragma bytecode(BC_COPY_LONG, inp_copyl) diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 71340ee..6bf8258 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -1209,7 +1209,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl else { block->PutCode(generator, BC_COPY_LONG); - block->PutByte(uint8(mValue)); + block->PutWord(uint16(mValue)); } break; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 2bf2f40..e5b08f7 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -232,6 +232,8 @@ bool Compiler::GenerateCode(void) else mGlobalAnalyzer->AnalyzeGlobalVariable(dec); } + + mGlobalAnalyzer->CheckInterrupt(); mGlobalAnalyzer->AutoInline(); //mGlobalAnalyzer->DumpCallGraph(); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d207c13..2ce4716 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -79,8 +79,9 @@ static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 34); static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35); static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36); static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37); +static const uint64 DTF_FUNC_INTRCALLED = (1ULL << 38); -static const uint64 DTF_VAR_ALIASING = (1ULL << 37); +static const uint64 DTF_VAR_ALIASING = (1ULL << 39); class Declaration; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 1789dd8..75978f9 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -181,6 +181,33 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec) } } +void GlobalAnalyzer::CheckInterrupt(void) +{ + bool changed = false; + do + { + changed = false; + + for (int i = 0; i < mFunctions.Size(); i++) + { + Declaration* f = mFunctions[i]; + if (f->mFlags & DTF_FUNC_INTRCALLED) + { + for (int j = 0; j < f->mCalled.Size(); j++) + { + Declaration* cf = f->mCalled[j]; + if (!(cf->mFlags & DTF_FUNC_INTRCALLED)) + { + cf->mFlags |= DTF_FUNC_INTRCALLED; + changed = true; + } + } + } + } + + } while (changed); +} + void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) { if (dec->mFlags & DTF_FUNC_ANALYZING) @@ -198,6 +225,9 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) dec->mFlags |= DTF_ANALYZED; dec->mFlags |= DTF_FUNC_INTRSAVE; + if (dec->mFlags & DTF_INTERRUPT) + dec->mFlags |= DTF_FUNC_INTRCALLED; + if ((dec->mFlags & DTF_INTRINSIC) && !dec->mValue) dec->mFlags |= DTF_FUNC_CONSTEXPR; else if (dec->mFlags & DTF_DEFINED) diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index e3846aa..4a4ac82 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -13,6 +13,7 @@ public: void DumpCallGraph(void); void AutoInline(void); void CheckFastcall(Declaration* procDec); + void CheckInterrupt(void); void AnalyzeProcedure(Expression* exp, Declaration* procDec); void AnalyzeAssembler(Expression* exp, Declaration* procDec); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 3426f94..d638cef 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -10166,7 +10166,8 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mIdent(ident), mLinkerObject(linkerObject), mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), - mInterrupt(false), mHardwareInterrupt(false), mCompiled(false) + mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), + mSaveTempsLinkerObject(nullptr) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); @@ -11018,7 +11019,7 @@ void InterCodeProcedure::Close(void) #if 1 ResetVisited(); - if (mEntryBlock->CheckStaticStack()) + if (!mInterruptCalled && mEntryBlock->CheckStaticStack()) { mLinkerObject->mFlags |= LOBJF_STATIC_STACK; mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent, LST_STATIC_STACK); @@ -11035,6 +11036,8 @@ void InterCodeProcedure::Close(void) } } + mSaveTempsLinkerObject = mModule->mLinker->AddObject(mLocation, mIdent, mLinkerObject->mStackSection, LOT_BSS); + ResetVisited(); mEntryBlock->CollectStaticStack(mLinkerObject, mLocalVars); } @@ -11069,6 +11072,8 @@ void InterCodeProcedure::Close(void) BuildTraces(false, false); DisassembleDebug("Final Merged basic blocks"); + if (mSaveTempsLinkerObject && mTempSize > 16) + mSaveTempsLinkerObject->AddSpace(mTempSize - 16); } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 8e6b4f0..cfd9c70 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -499,7 +499,8 @@ public: GrowingTypeArray mTemporaries; GrowingIntArray mTempOffset, mTempSizes; int mTempSize, mCommonFrameSize, mCallerSavedTemps; - bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure, mInterrupt, mHardwareInterrupt, mCompiled; + bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; + bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled; GrowingInterCodeProcedurePtrArray mCalledFunctions; InterCodeModule * mModule; @@ -511,7 +512,7 @@ public: Location mLocation; const Ident * mIdent, * mSection; - LinkerObject * mLinkerObject; + LinkerObject * mLinkerObject, * mSaveTempsLinkerObject; InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); ~InterCodeProcedure(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 099c8f5..9af9280 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3544,6 +3544,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod if (dec->mFlags & DTF_HWINTERRUPT) proc->mHardwareInterrupt = true; + if (dec->mFlags & DTF_FUNC_INTRCALLED) + proc->mInterruptCalled = true; + if (dec->mBase->mFlags & DTF_FASTCALL) { proc->mFastCallProcedure = true; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2892ec7..815e4b3 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5719,6 +5719,10 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, int size = ins->mConst.mOperandSize; int msize = 4; + uint32 flags = NCIF_LOWER | NCIF_UPPER; + if (ins->mVolatile) + flags |= NCIF_VOLATILE; + if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) msize = 8; else if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) @@ -5738,8 +5742,8 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, for (int i = 0; i < size; i++) { mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + i)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + i, ins->mSrc[0].mLinkerObject)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + i, ins->mSrc[0].mLinkerObject, flags)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg, nullptr, flags)); } return this; @@ -5751,8 +5755,8 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); this->Close(lblock, nullptr, ASMIT_JMP); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst - index, ins->mSrc[0].mLinkerObject)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst - index, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg, nullptr, flags)); lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_IMMEDIATE, (index + size) & 255)); lblock->Close(lblock, eblock, ASMIT_BNE); @@ -5760,6 +5764,95 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, return eblock; } } + else if ((ins->mSrc[0].mMemory == IM_GLOBAL || ins->mSrc[0].mMemory == IM_ABSOLUTE) && (ins->mSrc[1].mMemory == IM_GLOBAL || ins->mSrc[1].mMemory == IM_ABSOLUTE)) + { + NativeCodeBasicBlock* block = this; + + int offset = 0; + if (size >= 256) + { + block = nproc->AllocateBlock(); + + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + + + if (size > 256) + { + if (size < 512 && !(size & 1)) + { + int step = size >> 1; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, step)); + this->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + step - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + step - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + lblock->Close(lblock, block, ASMIT_BNE); + + return block; + } + else if (size < 1024 && !(size & 3)) + { + int step = size >> 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, step)); + this->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + step - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + step - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + 2 * step - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + 2 * step - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + 3 * step - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + 3 * step - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + lblock->Close(lblock, block, ASMIT_BNE); + + return block; + } + } + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + this->Close(lblock, nullptr, ASMIT_JMP); + while (offset + 255 < size) + { + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + offset, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + offset, ins->mSrc[1].mLinkerObject, flags)); + offset += 256; + } + lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + lblock->Close(lblock, block, ASMIT_BNE); + + size &= 255; + } + + if (size <= msize) + { + for (int i = 0; i < size; i++) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + offset + i, ins->mSrc[0].mLinkerObject, flags)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i, ins->mSrc[1].mLinkerObject, flags)); + } + } + else + { + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + + block->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size)); + block->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, ins->mSrc[0].mIntConst + offset - 1, ins->mSrc[0].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, ins->mSrc[1].mIntConst + offset - 1, ins->mSrc[1].mLinkerObject, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BNE); + + block = eblock; + } + + return block; + } } #endif @@ -5904,31 +5997,66 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, } else { - NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); - NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* block = this; - if (size < 128) + if (size >= 256) { - mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1)); + block = nproc->AllocateBlock(); + + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* lblock2 = nproc->AllocateBlock(); + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + if (size >= 512) + mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, size >> 8)); this->Close(lblock, nullptr, ASMIT_JMP); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - lblock->Close(lblock, eblock, ASMIT_BPL); - } - else if (size <= 256) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1)); - this->Close(lblock, nullptr, ASMIT_JMP); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - lblock->Close(lblock, eblock, ASMIT_BNE); - eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg)); - eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + lblock->Close(lblock, lblock2, ASMIT_BNE); + lblock2->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, sreg + 1)); + lblock2->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, dreg + 1)); + if (size >= 512) + { + lblock2->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + lblock2->Close(lblock, block, ASMIT_BNE); + } + else + lblock2->Close(block, nullptr, ASMIT_JMP); + + size &= 0xff; } - return eblock; + if (size > 0) + { + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + + if (size < 128) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1)); + block->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BPL); + } + else if (size <= 256) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1)); + block->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg, nullptr, flags)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BNE); + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg, nullptr, flags)); + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg, nullptr, flags)); + } + + block = eblock; + } + + return block; } } @@ -23227,6 +23355,54 @@ void NativeCodeProcedure::CompressTemporaries(void) } } +void NativeCodeProcedure::SaveTempsToStack(int tempSave) +{ + if (mInterProc->mSaveTempsLinkerObject) + { + assert(tempSave <= mInterProc->mSaveTempsLinkerObject->mSize); + + if (tempSave > 3) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_X, 0, mInterProc->mSaveTempsLinkerObject)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + else if (tempSave > 0) + { + for (int i = 0; i < tempSave; i++) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + i)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, i, mInterProc->mSaveTempsLinkerObject)); + } + } + } +} + +void NativeCodeProcedure::LoadTempsFromStack(int tempSave) +{ + if (mInterProc->mSaveTempsLinkerObject) + { + if (tempSave > 3) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, mInterProc->mSaveTempsLinkerObject)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + else if (tempSave > 0) + { + for (int i = 0; i < tempSave; i++) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, i, mInterProc->mSaveTempsLinkerObject)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + i)); + } + } + } +} + void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; @@ -23238,7 +23414,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mIndex = proc->mID; - int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0; + int tempSave = proc->mTempSize > 16 && !proc->mSaveTempsLinkerObject ? proc->mTempSize - 16 : 0; int commonFrameSize = proc->mCommonFrameSize; mStackExpand = tempSave + proc->mLocalSize; @@ -23378,7 +23554,9 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); ignoreExpandCommonFrame = true; - if (tempSave) + if (proc->mSaveTempsLinkerObject) + SaveTempsToStack(tempSave); + else if (tempSave) { mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); if (tempSave == 1) @@ -23413,6 +23591,8 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } } } + else if (proc->mSaveTempsLinkerObject) + SaveTempsToStack(tempSave); } else { @@ -23424,14 +23604,19 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (mStackExpand >> 8) & 0xff)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + if (proc->mSaveTempsLinkerObject) + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + else + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - if (tempSave) + if (proc->mSaveTempsLinkerObject) + SaveTempsToStack(tempSave); + else if (tempSave) { mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); @@ -23493,7 +23678,9 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { if (mStackExpand > 0) { - if (tempSave) + if (proc->mSaveTempsLinkerObject) + LoadTempsFromStack(tempSave); + else if (tempSave) { mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); if (tempSave == 1) @@ -23535,17 +23722,25 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); } + else if (proc->mSaveTempsLinkerObject) + LoadTempsFromStack(tempSave); + } else { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + if (proc->mSaveTempsLinkerObject) + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + else + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); - if (tempSave) + if (proc->mSaveTempsLinkerObject) + LoadTempsFromStack(tempSave); + else if (tempSave) { mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 8f9cf5c..5fb682a 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -390,6 +390,8 @@ class NativeCodeProcedure void ResetVisited(void); void ResetPatched(void); + void SaveTempsToStack(int tempSave); + void LoadTempsFromStack(int tempSave); }; class NativeCodeGenerator