From 18ab7ce079d4607d84236afc4eedcd622e128dea Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 6 Dec 2021 22:56:03 +0100 Subject: [PATCH] Fix broken left shift optimization due to branch in basic block --- autotest/bitshifttest.c | 5 +- include/math.c | 13 ++- oscar64/ByteCodeGenerator.cpp | 4 +- oscar64/Emulator.cpp | 2 +- oscar64/InterCode.cpp | 163 +++++++++++++++++--------------- oscar64/InterCode.h | 2 +- oscar64/NativeCodeGenerator.cpp | 16 ++-- 7 files changed, 114 insertions(+), 91 deletions(-) diff --git a/autotest/bitshifttest.c b/autotest/bitshifttest.c index 52a58fd..029b5d1 100644 --- a/autotest/bitshifttest.c +++ b/autotest/bitshifttest.c @@ -1,6 +1,8 @@ #include #include +#pragma region( main, 0x0a00, 0xd000, , , {code, data, bss, heap, stack} ) + unsigned shl1b(int n) { return 1 << n; @@ -306,6 +308,8 @@ void shr32n(unsigned long xu, long xi) int main(void) { + *(volatile char *)0x01 = 0x36; + for(int i=0; i<32; i++) { printf("1: %.4x : %.4x | %.4x : %.4x\n", shl1b(i), shl1n(i), shr1b(i), shr1n(i)); @@ -327,7 +331,6 @@ int main(void) assert(shr8b(i) == shr8n(i)); } - shl8xb(0x00, 0x00); shl8xb(0xff, 0xff); shl8xb(0x34, 0x34); diff --git a/include/math.c b/include/math.c index ab004f4..ad7e41d 100644 --- a/include/math.c +++ b/include/math.c @@ -183,11 +183,16 @@ float sqrt(float f) { if (f >= 0) { - float fx = f; - int ex = (((int*)&fx)[1] >> 7) - 0x7f; + union { + float f; + int i[2]; + } x; + + x.f = f; + int ex = (x.i[1] >> 7) - 0x7f; ex /= 2; - ((int*)&fx)[1] = (ex + 0x7f) << 7; - float fq = fx; + x.i[1] = (ex + 0x7f) << 7; + float fq = x.f; fq = 0.5 * (fq + f / fq); fq = 0.5 * (fq + f / fq); fq = 0.5 * (fq + f / fq); diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index d11a232..8957348 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -5680,8 +5680,8 @@ void ByteCodeBasicBlock::InitialOffset(int& total, int& linear) total++; linear = 0; } - else - linear += mLinear; + + linear += mLinear; mOffset = total; total += mCode.Size(); diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index 2c3827f..2b27553 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -640,7 +640,7 @@ int Emulator::Emulate(int startIP) break; } - if ((trace & 1) && ip == 0x0851) + if ((trace & 1) && ip == 0x0855) { int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1]; int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1]; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 11bf098..57845ec 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -90,24 +90,100 @@ void ValueSet::FlushFrameAliases(void) } } -void ValueSet::FlushCallAliases(void) + +static bool MemPtrRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset) +{ + while (ins && ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_INDIRECT) + ins = tvalue[ins->mSrc[1].mTemp]; + + if (ins) + { + if (ins->mCode == IC_CONSTANT) + { + mem = ins->mConst.mMemory; + vindex = ins->mConst.mVarIndex; + offset = ins->mConst.mIntConst; + + return true; + } + else if (ins->mCode == IC_LEA) + { + mem = ins->mSrc[1].mMemory; + vindex = ins->mSrc[1].mVarIndex; + offset = ins->mSrc[1].mIntConst; + + return true; + } + } + + return false; +} + + +static bool MemRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset, int& size) +{ + if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT) + { + size = ins->mSrc[0].mOperandSize; + return MemPtrRange(tvalue[ins->mSrc[0].mTemp], tvalue, mem, vindex, offset); + } + else if (ins->mSrc[1].mMemory == IM_INDIRECT) + { + size = ins->mSrc[1].mOperandSize; + return MemPtrRange(tvalue[ins->mSrc[1].mTemp], tvalue, mem, vindex, offset); + } + + if (ins) + { + if (ins->mCode == IC_LOAD) + { + mem = ins->mSrc[0].mMemory; + vindex = ins->mSrc[0].mVarIndex; + offset = ins->mSrc[0].mIntConst; + size = ins->mSrc[0].mOperandSize; + } + else + { + mem = ins->mSrc[1].mMemory; + vindex = ins->mSrc[1].mVarIndex; + offset = ins->mSrc[1].mIntConst; + size = ins->mSrc[1].mOperandSize; + } + + return true; + } + + return false; +} + +void ValueSet::FlushCallAliases(const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams) { int i; - i = 0; + InterMemory mem; + int vindex; + int offset; + int size; + i = 0; while (i < mNum) { - if ((mInstructions[i]->mCode == IC_LOAD && mInstructions[i]->mSrc[0].mMemory != IM_PARAM && mInstructions[i]->mSrc[0].mMemory != IM_LOCAL) || - (mInstructions[i]->mCode == IC_STORE && mInstructions[i]->mSrc[1].mMemory != IM_PARAM && mInstructions[i]->mSrc[1].mMemory != IM_LOCAL)) + if (mInstructions[i]->mCode == IC_LOAD || mInstructions[i]->mCode == IC_STORE) { - // - // potential alias load - // - mNum--; - if (i < mNum) + if (MemRange(mInstructions[i], tvalue, mem, vindex, offset, size) && + ((mem == IM_PARAM && !aliasedParams[vindex]) || + (mem == IM_LOCAL && !aliasedLocals[vindex]))) + i++; + else { - mInstructions[i] = mInstructions[mNum]; + // + // potential alias load + // + mNum--; + if (i < mNum) + { + mInstructions[i] = mInstructions[mNum]; + } } } else @@ -373,71 +449,6 @@ void ValueSet::InsertValue(InterInstruction * ins) mInstructions[mNum++] = ins; } -static bool MemPtrRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset) -{ - while (ins && ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_INDIRECT) - ins = tvalue[ins->mSrc[1].mTemp]; - - if (ins) - { - if (ins->mCode == IC_CONSTANT) - { - mem = ins->mConst.mMemory; - vindex = ins->mConst.mVarIndex; - offset = ins->mConst.mIntConst; - - return true; - } - else if (ins->mCode == IC_LEA) - { - mem = ins->mSrc[1].mMemory; - vindex = ins->mSrc[1].mVarIndex; - offset = ins->mSrc[1].mIntConst; - - return true; - } - } - - return false; -} - - -static bool MemRange(const InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset, int& size) -{ - if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT) - { - size = ins->mSrc[0].mOperandSize; - return MemPtrRange(tvalue[ins->mSrc[0].mTemp], tvalue, mem, vindex, offset); - } - else if (ins->mSrc[1].mMemory == IM_INDIRECT) - { - size = ins->mSrc[1].mOperandSize; - return MemPtrRange(tvalue[ins->mSrc[1].mTemp], tvalue, mem, vindex, offset); - } - - if (ins) - { - if (ins->mCode == IC_LOAD) - { - mem = ins->mSrc[0].mMemory; - vindex = ins->mSrc[0].mVarIndex; - offset = ins->mSrc[0].mIntConst; - size = ins->mSrc[0].mOperandSize; - } - else - { - mem = ins->mSrc[1].mMemory; - vindex = ins->mSrc[1].mVarIndex; - offset = ins->mSrc[1].mIntConst; - size = ins->mSrc[1].mOperandSize; - } - - return true; - } - - return false; -} - static bool StoreAliasing(const InterInstruction * lins, const InterInstruction* sins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, const GrowingVariableArray& staticVars) { InterMemory lmem, smem; @@ -1463,7 +1474,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr break; case IC_CALL: case IC_CALL_NATIVE: - FlushCallAliases(); + FlushCallAliases(tvalue, aliasedLocals, aliasedParams); break; } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 50e11c9..0487098 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -141,7 +141,7 @@ public: ValueSet& operator=(const ValueSet& values); void FlushAll(void); - void FlushCallAliases(void); + void FlushCallAliases(const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams); void FlushFrameAliases(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 81e6ea5..7d5b721 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5698,6 +5698,9 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p } else { + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); @@ -5720,14 +5723,15 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p } mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2)); + this->Close(lblock, eblock, ASMIT_BNE); - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2))); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BNE); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + return eblock; } } break; case IA_SHR: