diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 0058a72..d7200e8 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3897,6 +3897,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) } } } + else if (ins->mSrc[1].mTemp >= 0) + vr = mLocalValueRange[ins->mSrc[1].mTemp]; else vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; break; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 199a6b9..6fe781d 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -6768,33 +6768,62 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); - if (ins->mSrc[1].mTemp < 0) + if (ins->mSrc[1].IsUByte()) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff)); - } - else if (ins->mSrc[1].mTemp != ins->mDst.mTemp) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + if (ins->mSrc[1].mTemp < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff)); + } + else if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + this->Close(lblock, eblock, ASMIT_BNE); + + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } else { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + if (ins->mSrc[1].mTemp < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff)); + } + else if (ins->mSrc[1].mTemp != ins->mDst.mTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + this->Close(lblock, eblock, ASMIT_BNE); + + lblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + lblock->Close(lblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } - - mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); - this->Close(lblock, eblock, ASMIT_BNE); - - lblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); - lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - lblock->Close(lblock, eblock, ASMIT_BNE); - - eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); return eblock; } } break; @@ -9058,20 +9087,37 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i apos = j + 0; int ireg = iins->mAddress; - if (reg == ireg && !direct) - return false; - - int k = j + 7; - while (k < at) + if (reg == ireg) { - if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + if (!direct) return false; - if (reg == ireg && mIns[k].ChangesYReg()) - return false; - k++; - } - return true; + flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive; + + int k = j + 7; + while (k < at) + { + if (mIns[k].ChangesYReg()) + flags &= ~LIVE_CPU_REG_Y; + if (mIns[k].ChangesXReg()) + flags &= ~LIVE_CPU_REG_X; + k++; + } + + return flags != 0; + } + else + { + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } } else if ( mIns[j + 0].mType == ASMIT_STA && mIns[j + 0].mMode == ASMIM_ZERO_PAGE && @@ -9087,20 +9133,37 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i apos = j + 1; int ireg = iins->mAddress; - if (reg == ireg && !direct) - return false; - - int k = j + 7; - while (k < at) + if (reg == ireg) { - if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + if (!direct) return false; - if (reg == ireg && mIns[k].ChangesYReg()) - return false; - k++; - } - return true; + flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive; + + int k = j + 7; + while (k < at) + { + if (mIns[k].ChangesYReg()) + flags &= ~LIVE_CPU_REG_Y; + if (mIns[k].ChangesXReg()) + flags &= ~LIVE_CPU_REG_X; + k++; + } + + return flags != 0; + } + else + { + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } } else if (mIns[j + 0].mType == ASMIT_CLC && mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 1].mFlags & NCIF_LOWER) && mIns[j + 1].mLinkerObject && @@ -9175,20 +9238,37 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i addr = mIns[j + 2].mAddress + 256 * (mIns[j + 4].mAddress + mIns[j + 5].mAddress); int ireg = iins->mAddress; - if (reg == ireg && !direct) - return false; - - int k = j + 7; - while (k < at) + if (reg == ireg) { - if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + if (!direct) return false; - if (reg == ireg && mIns[k].ChangesYReg()) - return false; - k++; - } - return true; + flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive; + + int k = j + 7; + while (k < at) + { + if (mIns[k].ChangesYReg()) + flags &= ~LIVE_CPU_REG_Y; + if (mIns[k].ChangesXReg()) + flags &= ~LIVE_CPU_REG_X; + k++; + } + + return flags != 0; + } + else + { + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } } else if (mIns[j + 0].mType == ASMIT_CLC && mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_IMMEDIATE && @@ -9205,20 +9285,37 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i addr = mIns[j + 1].mAddress + 256 * (mIns[j + 4].mAddress + mIns[j + 5].mAddress); int ireg = iins->mAddress; - if (reg == ireg && !direct) - return false; - - int k = j + 7; - while (k < at) + if (reg == ireg) { - if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + if (!direct) return false; - if (reg == ireg && mIns[k].ChangesYReg()) - return false; - k++; - } - return true; + flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive; + + int k = j + 7; + while (k < at) + { + if (mIns[k].ChangesYReg()) + flags &= ~LIVE_CPU_REG_Y; + if (mIns[k].ChangesXReg()) + flags &= ~LIVE_CPU_REG_X; + k++; + } + + return flags != 0; + } + else + { + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + return false; + k++; + } + + return true; + } } else if ( mIns[j + 1].mType == ASMIT_CLC && @@ -9335,6 +9432,59 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i return false; } +bool NativeCodeBasicBlock::PatchGlobalAdressSumYByX(int at, int reg, const NativeCodeInstruction& ains, int addr) +{ + int yindex = 0; + int last = at; + + while (last < mIns.Size()) + { + if (mIns[last].mType == ASMIT_LDY && mIns[last].mMode == ASMIM_IMMEDIATE) + yindex = mIns[last].mAddress; + else if (mIns[last].ChangesYReg()) + return false; + else if (mIns[last].mMode == ASMIM_ZERO_PAGE && (mIns[last].mAddress == reg || mIns[last].mAddress == reg + 1) && mIns[last].ChangesAddress()) + return false; + else if (mIns[last].mMode == ASMIM_INDIRECT_Y && mIns[last].mAddress == reg) + { + if (!(mIns[last].mLive & LIVE_MEM)) + break; + } + else if (mIns[last].RequiresXReg()) + return false; + last++; + } + + if (last == mIns.Size()) + return false; + + yindex = 0; + for (int i = at; i <= last; i++) + { + mIns[i].mLive | LIVE_CPU_REG_X; + + if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE) + yindex = mIns[i].mAddress; + else if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == reg) + { + mIns[i].mMode = ASMIM_ABSOLUTE_X; + if (ains.mMode == ASMIM_IMMEDIATE) + { + mIns[i].mLinkerObject = nullptr; + mIns[i].mAddress = addr + yindex; + } + else + { + mIns[i].mLinkerObject = ains.mLinkerObject; + mIns[i].mAddress = ains.mAddress + yindex; + } + } + } + + return true; +} + + bool NativeCodeBasicBlock::PatchDirectAddressSumY(int at, int reg, int apos, int breg) { int yindex = 0; @@ -12059,14 +12209,19 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } - if (iins || (flags & LIVE_CPU_REG_Y)) + if (flags & LIVE_CPU_REG_Y) { mIns[i + 0].mMode = ASMIM_ABSOLUTE_Y; } - else + else if (flags & LIVE_CPU_REG_X) { mIns[i + 0].mMode = ASMIM_ABSOLUTE_X; } + else + { + mIns[i + 0].mMode = ASMIM_ABSOLUTE_Y; + } + if (ains->mMode == ASMIM_IMMEDIATE) { @@ -12092,9 +12247,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } else { + PatchGlobalAdressSumYByX(i + 1, sreg, *ains, addr); mIns.Insert(apos, NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns[apos].mLive = LIVE_CPU_REG_X | LIVE_CPU_REG_A; - for (int j = apos; j < i + 1; j++) + for (int j = apos; j < i + 2; j++) mIns[j].mLive |= LIVE_CPU_REG_X; } } @@ -12104,8 +12260,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, iins->mMode, iins->mAddress, iins->mLinkerObject, iins->mFlags)); else if (iins->mAddress == sreg) { - mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress)); - mIns[apos].mLive = LIVE_CPU_REG_Y | LIVE_MEM; + if (flags & LIVE_CPU_REG_Y) + { + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress)); + mIns[apos].mLive = LIVE_CPU_REG_Y | LIVE_CPU_REG_A | LIVE_MEM; + for (int j = apos; j < i + 2; j++) + mIns[j].mLive |= LIVE_CPU_REG_Y; + } + else + { + PatchGlobalAdressSumYByX(i + 1, sreg, *ains, addr); + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, iins->mAddress)); + mIns[apos].mLive = LIVE_CPU_REG_X | LIVE_CPU_REG_A | LIVE_MEM; + for (int j = apos; j < i + 2; j++) + mIns[j].mLive |= LIVE_CPU_REG_X; + } + i++; } else mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress)); @@ -12440,14 +12610,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } - if (iins || (flags & LIVE_CPU_REG_Y)) + if (flags & LIVE_CPU_REG_Y) { mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; } - else + else if (flags & LIVE_CPU_REG_X) { mIns[i + 1].mMode = ASMIM_ABSOLUTE_X; } + else + { + mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; + } if (ains->mMode == ASMIM_IMMEDIATE) { @@ -12472,6 +12646,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } else { + PatchGlobalAdressSumYByX(i + 1, sreg, *ains, addr); mIns.Insert(apos, NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns[apos].mLive = LIVE_CPU_REG_X | LIVE_CPU_REG_A; for (int j = apos; j < i + 2; j++) @@ -12488,8 +12663,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) else if (iins->mAddress == sreg) { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; - mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress)); - mIns[apos].mLive = LIVE_CPU_REG_Y | LIVE_MEM; + if (flags & LIVE_CPU_REG_Y) + { + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress)); + mIns[apos].mLive = LIVE_CPU_REG_Y | LIVE_CPU_REG_A | LIVE_MEM; + for (int j = apos; j < i + 2; j++) + mIns[j].mLive |= LIVE_CPU_REG_Y; + } + else + { + PatchGlobalAdressSumYByX(i + 1, sreg, *ains, addr); + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, iins->mAddress)); + mIns[apos].mLive = LIVE_CPU_REG_X | LIVE_CPU_REG_A | LIVE_MEM; + for (int j = apos; j < i + 2; j++) + mIns[j].mLive |= LIVE_CPU_REG_X; + } } else { diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index a180af6..727613f 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -222,6 +222,8 @@ public: bool MoveAddHighByteDown(int at); bool ReverseLoadCommutativeOpUp(int aload, int aop); + bool PatchGlobalAdressSumYByX(int at, int reg, const NativeCodeInstruction& ains, int addr); + bool ValueForwarding(const NativeRegisterDataSet& data, bool global); void CollectEntryBlocks(NativeCodeBasicBlock* block);