From 1c0db235a813cdb370d135c1fa5135cc1d9a9bca Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 30 Jun 2024 12:29:41 +0200 Subject: [PATCH] Fix emulator cycle count --- oscar64/Emulator.cpp | 79 +++++++++---- oscar64/Emulator.h | 2 +- oscar64/InterCode.cpp | 199 ++++++++++++++++++++++++++++++-- oscar64/InterCode.h | 5 + oscar64/NativeCodeGenerator.cpp | 9 +- 5 files changed, 257 insertions(+), 37 deletions(-) diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index 1e4dd7f..5f85f0d 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -115,7 +115,7 @@ void Emulator::DumpCycles(void) } } -bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles) +bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles, bool cross, bool indexed) { int t; @@ -134,12 +134,14 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mRegA = (t & 255); UpdateStatusCarry(mRegA, t >= 256); + if (cross) cycles++; break; case ASMIT_AND: if (mode != ASMIM_IMMEDIATE) addr = mMemory[addr]; mRegA &= addr; UpdateStatus(mRegA); + if (cross) cycles++; break; case ASMIT_ASL: if (mode == ASMIM_IMPLIED) @@ -154,19 +156,29 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatusCarry(t & 255, t >= 256); cycles += 2; + if (indexed) cycles++; } break; case ASMIT_BCC: if (!(mRegP & STATUS_CARRY)) + { mIP = addr; + cycles++; + } break; case ASMIT_BCS: if ((mRegP & STATUS_CARRY)) + { mIP = addr; + cycles++; + } break; case ASMIT_BEQ: if ((mRegP & STATUS_ZERO)) + { mIP = addr; + cycles++; + } break; case ASMIT_BIT: t = mMemory[addr]; @@ -235,6 +247,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mRegP |= STATUS_OVERFLOW; UpdateStatusCarry(t & 255, t >= 256); + if (cross) cycles++; break; case ASMIT_CPX: if (mode != ASMIM_IMMEDIATE) @@ -275,6 +288,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatus(t & 255); cycles += 2; + if (indexed) cycles++; } break; case ASMIT_DEX: @@ -292,6 +306,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in addr = mMemory[addr]; mRegA ^= addr; UpdateStatus(mRegA); + if (cross) cycles++; break; case ASMIT_INC: if (mode == ASMIM_IMPLIED) @@ -306,6 +321,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatus(t & 255); cycles += 2; + if (indexed) cycles++; } break; case ASMIT_INX: @@ -334,18 +350,21 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in addr = mMemory[addr]; mRegA = addr; UpdateStatus(mRegA); + if (cross) cycles++; break; case ASMIT_LDX: if (mode != ASMIM_IMMEDIATE) addr = mMemory[addr]; mRegX = addr; UpdateStatus(mRegX); + if (cross) cycles++; break; case ASMIT_LDY: if (mode != ASMIM_IMMEDIATE) addr = mMemory[addr]; mRegY = addr; UpdateStatus(mRegY); + if (cross) cycles++; break; case ASMIT_LSR: if (mode == ASMIM_IMPLIED) @@ -362,6 +381,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatusCarry(t & 255, c != 0); cycles += 2; + if (indexed) cycles++; } break; case ASMIT_NOP: @@ -371,6 +391,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in addr = mMemory[addr]; mRegA |= addr; UpdateStatus(mRegA); + if (cross) cycles++; break; case ASMIT_PHA: mMemory[0x100 + mRegS] = mRegA; @@ -405,6 +426,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatusCarry(t & 255, t >= 256); cycles+=2; + if (indexed) cycles++; } break; case ASMIT_ROR: @@ -422,6 +444,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mMemory[addr] = t & 255; UpdateStatusCarry(t & 255, c != 0); cycles += 2; + if (indexed) cycles++; } break; case ASMIT_RTI: @@ -444,6 +467,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in mRegA = (t & 255); UpdateStatusCarry(t & 255, t >= 256); + if (cross) cycles++; break; case ASMIT_SEC: mRegP |= STATUS_CARRY; @@ -454,6 +478,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in break; case ASMIT_STA: mMemory[addr] = mRegA; + if (indexed) cycles++; break; case ASMIT_STX: mMemory[addr] = mRegX; @@ -512,13 +537,12 @@ int Emulator::Emulate(int startIP, int trace) mMemory[0x1fe] = 0xff; mMemory[0x1ff] = 0xff; - int ticks = 0; + int tcycles = 0, cycles = 0; while (mIP != 0) { if (mJiffies) { - ticks++; - if (ticks > 4500) + if (cycles >= tcycles + 16667) { mMemory[0xa2]++; if (!mMemory[0xa2]) @@ -529,7 +553,7 @@ int Emulator::Emulate(int startIP, int trace) mMemory[0xa0]++; } } - ticks = 0; + tcycles += 16667; } } @@ -556,11 +580,13 @@ int Emulator::Emulate(int startIP, int trace) mRegS += 2; } - uint8 opcode = mMemory[mIP]; + uint8 opcode = mMemory[mIP]; AsmInsData d = DecInsData[opcode]; - int addr = 0, taddr; - int ip = mIP; - int iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1]; + int addr = 0, taddr; + int ip = mIP; + int iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1]; + bool cross = false, indexed = false; + int icycles = 0; mIP++; switch (d.mMode) @@ -568,56 +594,60 @@ int Emulator::Emulate(int startIP, int trace) case ASMIM_IMPLIED: if (trace & 2) printf("%04x : %04x %02x __ __ %s (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType], mRegA, mRegX, mRegY, mRegP, mRegS); - mCycles[ip] += 2; + icycles = 2; break; case ASMIM_IMMEDIATE: addr = mMemory[mIP++]; if (trace & 2) printf("%04x : %04x %02x %02x __ %s #$%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], mMemory[ip+1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS); - mCycles[ip] += 2; + icycles = 2; break; case ASMIM_ZERO_PAGE: addr = mMemory[mIP++]; if (trace & 2) printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]); - mCycles[ip] += 3; + icycles = 3; break; case ASMIM_ZERO_PAGE_X: taddr = mMemory[mIP++]; addr = (taddr + mRegX) & 0xff; if (trace & 2) printf("%04x : %04x %02x %02x __ %s $%02x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); - mCycles[ip] += 3; + icycles = 4; break; case ASMIM_ZERO_PAGE_Y: taddr = mMemory[mIP++]; addr = (taddr + mRegY) & 0xff; if (trace & 2) printf("%04x : %04x %02x %02x __ %s $%02x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); - mCycles[ip] += 3; + icycles = 4; break; case ASMIM_ABSOLUTE: addr = mMemory[mIP] + 256 * mMemory[mIP + 1]; if (trace & 2) printf("%04x : %04x %02x %02x %02x %s $%04x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]); mIP += 2; - mCycles[ip] += 4; + icycles = 4; break; case ASMIM_ABSOLUTE_X: taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; addr = (taddr + mRegX) & 0xffff; + cross = mMemory[mIP] + mRegX >= 256; + indexed = true; if (trace & 2) printf("%04x : %04x %02x %02x %02x %s $%04x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); mIP += 2; - mCycles[ip] += 5; + icycles = 4; break; case ASMIM_ABSOLUTE_Y: taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; addr = (taddr + mRegY) & 0xffff; + cross = mMemory[mIP] + mRegY >= 256; + indexed = true; if (trace & 2) printf("%04x : %04x %02x %02x %02x %s $%04x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); mIP += 2; - mCycles[ip] += 5; + icycles = 4; break; case ASMIM_INDIRECT: taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; @@ -625,21 +655,23 @@ int Emulator::Emulate(int startIP, int trace) addr = mMemory[taddr] + 256 * mMemory[taddr + 1]; if (trace & 2) printf("%04x : %04x %02x %02x %02x %s ($%04x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr); - mCycles[ip] += 6; + icycles = 6; break; case ASMIM_INDIRECT_X: taddr = (mMemory[mIP++] + mRegX) & 0xff; addr = mMemory[taddr] + 256 * mMemory[taddr + 1]; if (trace & 2) printf("%04x : %04x %02x %02x __ %s ($%02x,x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], mMemory[ip + 1], mRegA, mRegX, mRegY, mRegP, mRegS, taddr, addr, mMemory[addr]); - mCycles[ip] += 6; + icycles = 6; break; case ASMIM_INDIRECT_Y: taddr = mMemory[mIP++]; addr = (mMemory[taddr] + 256 * mMemory[taddr + 1] + mRegY) & 0xffff; + cross = mMemory[taddr] + mRegY >= 256; + indexed = true; if (trace & 2) printf("%04x : %04x %02x %02x __ %s ($%02x),y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); - mCycles[ip] += 6; + icycles = 5; break; case ASMIM_RELATIVE: taddr = mMemory[mIP++]; @@ -649,7 +681,7 @@ int Emulator::Emulate(int startIP, int trace) addr = taddr + mIP; if (trace & 2) printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr); - mCycles[ip] += 2; + icycles = 2; break; } @@ -685,8 +717,11 @@ int Emulator::Emulate(int startIP, int trace) ); } - if (!EmulateInstruction(d.mType, d.mMode, addr, mCycles[ip])) + if (!EmulateInstruction(d.mType, d.mMode, addr, icycles, cross, indexed)) return -1; + + mCycles[ip] += icycles; + cycles += icycles; } if (mRegS == 0xff) diff --git a/oscar64/Emulator.h b/oscar64/Emulator.h index 2b5a6c4..36d8036 100644 --- a/oscar64/Emulator.h +++ b/oscar64/Emulator.h @@ -22,7 +22,7 @@ public: int Emulate(int startIP, int trace); void DumpProfile(void); - bool EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles); + bool EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles, bool cross, bool indexed); protected: void UpdateStatus(uint8 result); void UpdateStatusCarry(uint8 result, bool carry); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index f0c3fb1..b4c9ddd 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -8333,9 +8333,9 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSetsBackward(const GrowingVaria { InterInstruction* ins(mInstructions[i]); if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT && ins->mSrc[0].mTemp >= 0) - mMemoryValueSize[ins->mSrc[0].mTemp] = int64max(mMemoryValueSize[ins->mSrc[0].mTemp], ins->mSrc[0].mIntConst + InterTypeSize[ins->mDst.mType]); + mMemoryValueSize[ins->mSrc[0].mTemp] = int64max(mMemoryValueSize[ins->mSrc[0].mTemp], ins->mSrc[0].mIntConst + (InterTypeSize[ins->mDst.mType] - 1) * ins->mSrc[0].mStride + 1); else if (ins->mCode == IC_STORE && ins->mSrc[1].mMemory == IM_INDIRECT && ins->mSrc[1].mTemp >= 0) - mMemoryValueSize[ins->mSrc[1].mTemp] = int64max(mMemoryValueSize[ins->mSrc[1].mTemp], ins->mSrc[1].mIntConst + InterTypeSize[ins->mSrc[0].mType]); + mMemoryValueSize[ins->mSrc[1].mTemp] = int64max(mMemoryValueSize[ins->mSrc[1].mTemp], ins->mSrc[1].mIntConst + (InterTypeSize[ins->mSrc[0].mType] - 1) * ins->mSrc[1].mStride + 1); else if (ins->mCode == IC_FILL) { if (ins->mSrc[1].mMemory == IM_INDIRECT && ins->mSrc[1].mTemp >= 0) @@ -8711,6 +8711,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray break; #endif case IA_CMPLS: + // Why limit weak, makes no sense if (s0 < 0) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); @@ -8825,7 +8826,11 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray if (s0 < 0) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); - mTrueValueRange[s1].LimitMinWeak(0); + + if (mInstructions[sz - 2]->mSrc[0].mIntConst > 0 && mInstructions[sz - 2]->mSrc[0].mIntConst < SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType)) + mTrueValueRange[s1].LimitMin(0); + else + mTrueValueRange[s1].LimitMinWeak(0); if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0) { @@ -12240,7 +12245,10 @@ InterInstruction* InterCodeBasicBlock::FindTempOrigin(int temp) const for (int i = mInstructions.Size() - 1; i >= 0; i--) { if (mInstructions[i]->mDst.mTemp == temp) + { + mMark = i; return mInstructions[i]; + } } return nullptr; } @@ -17554,6 +17562,133 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa } } +static bool IsSimilarLea(InterInstruction* ins0, InterInstruction* ins1) +{ + if (ins0->mCode == IC_LEA && ins1->mCode == IC_LEA && + ins0->mSrc[0].mTemp == ins1->mSrc[0].mTemp && + ins0->mSrc[1].mTemp == ins1->mSrc[1].mTemp && + ins0->mSrc[0].IsUByte() && ins1->mSrc[0].IsUByte()) + { + if (ins0->mSrc[1].mTemp >= 0 && ins0->mSrc[1].mFinal && ins1->mSrc[1].mFinal || + ins0->mSrc[1].mMemory == ins1->mSrc[1].mMemory && + ins0->mSrc[1].mVarIndex == ins1->mSrc[1].mVarIndex && + ins0->mSrc[1].mLinkerObject == ins1->mSrc[1].mLinkerObject) + { + if (ins0->mSrc[1].mIntConst < ins1->mSrc[1].mIntConst) + { + if (ins1->mSrc[0].mRange.mMaxValue + ins1->mSrc[1].mIntConst - ins0->mSrc[1].mIntConst < 128) + return true; + } + else if (ins0->mSrc[1].mIntConst > ins1->mSrc[1].mIntConst) + { + if (ins0->mSrc[0].mRange.mMaxValue + ins0->mSrc[1].mIntConst - ins1->mSrc[1].mIntConst < 128) + return true; + } + else + return true; + } + } + + return false; +} + +bool InterCodeBasicBlock::ShortLeaMerge(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (!mLoopHead && mEntryBlocks.Size() > 1) + { + int k = 0; + while (k < mEntryBlocks.Size() && !mEntryBlocks[k]->mFalseJump) + k++; + + if (k == mEntryBlocks.Size()) + { + GrowingInstructionArray iins(nullptr); + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + int ttemp = -1; + if (ins->mCode == IC_STORE && ins->mSrc[1].mTemp >= 0) + ttemp = ins->mSrc[1].mTemp; + else if (ins->mCode == IC_LOAD && ins->mSrc[0].mTemp >= 0) + ttemp = ins->mSrc[0].mTemp; + + if (ttemp >= 0 && !IsTempModifiedInRange(0, i, ttemp)) + { + bool found = true; + + iins.SetSize(0); + for (int k = 0; k < mEntryBlocks.Size(); k++) + { + InterInstruction* sins = mEntryBlocks[k]->FindTempOrigin(ttemp); + if (sins && sins->mCode == IC_LEA && mEntryBlocks[k]->CanMoveInstructionBehindBlock(mEntryBlocks[k]->mMark)) + iins.Push(sins); + else + { + found = false; + break; + } + } + + if (found) + { + int64 minint = iins[0]->mSrc[1].mIntConst; + + for (int k = 1; k < mEntryBlocks.Size(); k++) + { + if (IsSimilarLea(iins[0], iins[k])) + { + if (iins[k]->mSrc[1].mIntConst < minint) + minint = iins[k]->mSrc[1].mIntConst; + } + else + { + found = false; + break; + } + } + + if (found) + { + mInstructions.Insert(0, iins[0]->Clone()); + iins[0]->mSrc[1].mIntConst = minint; + + for (int k = 0; k < mEntryBlocks.Size(); k++) + { + InterInstruction* sins = iins[k]; + sins->mCode = IC_BINARY_OPERATOR; + sins->mOperator = IA_ADD; + sins->mDst = sins->mSrc[0]; + sins->mSrc[1].mTemp = -1; + sins->mSrc[1].mType = sins->mSrc[0].mType; + sins->mSrc[1].mIntConst -= minint; + sins->mDst.mRange.mMaxValue += sins->mSrc[1].mIntConst; + mEntryBlocks[k]->mExitRequiredTemps += sins->mDst.mTemp; + } + + changed = true; + } + } + } + } + } + } + + if (mTrueJump && mTrueJump->ShortLeaMerge()) changed = true; + if (mFalseJump && mFalseJump->ShortLeaMerge()) changed = true; + } + + return changed; +} + + void InterCodeBasicBlock::CompactInstructions(void) { if (!mVisited) @@ -17735,6 +17870,28 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 2]->mSrc[1].mFinal = false; changed = true; } + else if ( + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_ADD && + mInstructions[i + 0]->mSrc[0].mTemp < 0 && mInstructions[i + 0]->mSrc[0].mIntConst >= 0 && + mInstructions[i + 1]->mCode == IC_TYPECAST && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal && + mInstructions[i + 1]->mDst.mType == IT_POINTER && mInstructions[i + 1]->mSrc[0].mType == IT_INT16) + { + int64 addr = mInstructions[i + 0]->mSrc[0].mIntConst; + + mInstructions[i + 0]->mCode = IC_LEA; + mInstructions[i + 0]->mSrc[0] = mInstructions[i + 0]->mSrc[1]; + mInstructions[i + 0]->mSrc[1].mTemp = -1; + mInstructions[i + 0]->mSrc[1].mType = IT_POINTER; + mInstructions[i + 0]->mSrc[1].mMemory = IM_ABSOLUTE; + mInstructions[i + 0]->mSrc[1].mIntConst = addr; + mInstructions[i + 0]->mSrc[1].mLinkerObject = nullptr; + mInstructions[i + 0]->mSrc[1].mVarIndex = -1; + mInstructions[i + 0]->mDst = mInstructions[i + 1]->mDst; + + mInstructions[i + 1]->mCode = IC_NONE; + mInstructions[i + 1]->mNumOperands = 0; + changed = true; + } else if ( mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SAR && mInstructions[i + 0]->mSrc[0].mTemp < 0 && mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_MUL && mInstructions[i + 1]->mSrc[0].mTemp < 0 && @@ -21034,7 +21191,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "getch"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -22223,10 +22380,12 @@ bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const { if (!(mInstructions[j0]->IsEqual(block->mInstructions[j1]))) { - if (mInstructions[j0]->mCode == IC_LEA && mInstructions[j0]->mSrc[1].mTemp < 0) - return false; - if (block->mInstructions[j1]->mCode == IC_LEA && block->mInstructions[j1]->mSrc[1].mTemp < 0) - return false; + if (mInstructions[j0]->mCode == IC_LEA && mInstructions[j0]->mSrc[1].mTemp < 0 || + block->mInstructions[j1]->mCode == IC_LEA && block->mInstructions[j1]->mSrc[1].mTemp < 0) + { + if (!IsSimilarLea(mInstructions[j0], block->mInstructions[j1])) + return false; + } } } @@ -22257,10 +22416,12 @@ bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const { if (!(mInstructions[j0]->IsEqual(block->mInstructions[j1]))) { - if (mInstructions[j0]->mCode == IC_LEA && mInstructions[j0]->mSrc[1].mTemp < 0) - return false; - if (block->mInstructions[j1]->mCode == IC_LEA && mInstructions[j1]->mSrc[1].mTemp < 0) - return false; + if (mInstructions[j0]->mCode == IC_LEA && mInstructions[j0]->mSrc[1].mTemp < 0 || + block->mInstructions[j1]->mCode == IC_LEA && block->mInstructions[j1]->mSrc[1].mTemp < 0) + { + if (!IsSimilarLea(mInstructions[j0], block->mInstructions[j1])) + return false; + } } } } @@ -22305,6 +22466,14 @@ bool PartitionSameExitCode(GrowingArray & eblocks, Growin return false; } +void InterCodeProcedure::ShortLeaMerge(void) +{ + ResetVisited(); + mEntryBlock->ShortLeaMerge(); + + DisassembleDebug("ShortLeaMerge"); +} + void InterCodeProcedure::MergeBasicBlocks(void) { ResetVisited(); @@ -22461,6 +22630,12 @@ void InterCodeProcedure::MergeBasicBlocks(void) } } + if (!changed) + { + ResetVisited(); + changed = mEntryBlock->ShortLeaMerge(); + } + } while (changed); ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 2518489..23922df 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -367,6 +367,7 @@ public: GrowingInstructionArray mInstructions; bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath, mValueRangeValid; + mutable int mMark; NumberSet mLocalUsedTemps, mLocalModifiedTemps; NumberSet mLocalRequiredTemps, mLocalProvidedTemps; @@ -616,6 +617,8 @@ public: void SplitBranches(void); void FollowJumps(void); + bool ShortLeaMerge(void); + bool IsEqual(const InterCodeBasicBlock* block) const; void CompactInstructions(void); @@ -742,6 +745,8 @@ protected: void RecheckLocalAliased(void); void ConstLoopOptimization(void); + void ShortLeaMerge(void); + void MergeBasicBlocks(void); void CheckUsedDefinedTemps(void); void WarnUsedUndefinedVariables(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 55a1af6..f77873f 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -50355,8 +50355,13 @@ void NativeCodeProcedure::Optimize(void) if (step == 12) { ResetVisited(); - if (mEntryBlock->GlobalLoadStoreForwarding(false, NativeCodeInstruction(), NativeCodeInstruction(), NativeCodeInstruction()) || - mEntryBlock->GlobalLoadStoreForwarding(true, NativeCodeInstruction(), NativeCodeInstruction(), NativeCodeInstruction())) + bool cc = mEntryBlock->GlobalLoadStoreForwarding(false, NativeCodeInstruction(), NativeCodeInstruction(), NativeCodeInstruction()); + if (!cc) + { + ResetVisited(); + cc = mEntryBlock->GlobalLoadStoreForwarding(true, NativeCodeInstruction(), NativeCodeInstruction(), NativeCodeInstruction()); + } + if (cc) { ResetVisited(); NativeRegisterDataSet data;