diff --git a/include/c64/rasterirq.c b/include/c64/rasterirq.c new file mode 100644 index 0000000..ecbe8a0 --- /dev/null +++ b/include/c64/rasterirq.c @@ -0,0 +1,316 @@ +#include "rasterirq.h" + +#include +#include + +volatile char npos = 1, tpos = 0; + +byte rasterIRQRows[NUM_IRQS]; +byte rasterIRQIndex[NUM_IRQS]; +byte rasterIRQNext[NUM_IRQS]; +byte rasterIRQLow[NUM_IRQS]; +byte rasterIRQHigh[NUM_IRQS]; + +byte nextIRQ; + +__asm irq0 +{ + pha + txa + pha + tya + pha + + ldx nextIRQ +l1: + lda rasterIRQNext, x + cmp #$ff + beq e1 + + ldy rasterIRQIndex, x + tax + lda rasterIRQLow, y + sta ji + 1 + lda rasterIRQHigh, y + sta ji + 2 + +ji: + jsr $0000 +jx: + + inc nextIRQ + ldx nextIRQ + + lda rasterIRQNext, x + cmp #$ff + beq e2 + + tay + + sec + sbc #4 + cmp $d012 + bcc l1 + + dey + sty $d012 +w1: + jmp ex + +e2: + sta $d012 + + lda npos + sta tpos + + asl $d019 + jmp ex + +e1: + ldx #0 + stx nextIRQ + lda rasterIRQNext, x + sec + sbc #1 + sta $d012 + +ex: + asl $d019 + + pla + tay + pla + tax + pla + rti + +} + +__asm irq1 +{ + ldx nextIRQ +l1: + lda rasterIRQNext, x + cmp #$ff + beq e1 + + ldy rasterIRQIndex, x + tax + lda rasterIRQLow, y + sta ji + 1 + lda rasterIRQHigh, y + sta ji + 2 + +ji: + jsr $0000 +jx: + + inc nextIRQ + ldx nextIRQ + + lda rasterIRQNext, x + cmp #$ff + beq e2 + + tay + + sec + sbc #4 + cmp $d012 + bcc l1 + + dey + sty $d012 +w1: + jmp ex + +e2: + sta $d012 + + lda npos + sta tpos + + asl $d019 + jmp ex + +e1: + ldx #0 + stx nextIRQ + lda rasterIRQNext, x + sec + sbc #1 + sta $d012 + +ex: + asl $d019 + + jmp $ea31 +} + +// 0 lda #data0 +// 2 ldy #data1 +// 4 cpx $d012 +// 7 bcc -5 +// 9 sta addr0 +// 12 sty addr1 +// 15 lda #data2 +// 17 sta addr2 +// 20 lda #data3 +// 22 sta addr3 +// ... +// rts + +void rirq_build(RIRQCode * ic, byte size) +{ + ic->size = size; + + ic->code[0] = 0xa9; // lda # + ic->code[2] = 0xa0; // ldy # + ic->code[4] = 0xec; // cpx + ic->code[5] = 0x12; + ic->code[6] = 0xd0; + ic->code[7] = 0xb0; // bcs + ic->code[8] = -5; + ic->code[9] = 0x8d; // sta + + if (size == 1) + { + ic->code[12] = 0x60; // rts + } + else + { + ic->code[12] = 0x8c; // sty + + byte p = 15; + for(byte i=2; icode[p] = 0xa9; // lda # + ic->code[p + 2] = 0x8d; // sta + p += 5; + } + ic->code[p] = 0x60; + } +} + +void rirq_set(byte n, byte row, RIRQCode * write) +{ + rasterIRQLow[n] = (unsigned)&write->code & 0xff; + rasterIRQHigh[n] = (unsigned)&write->code >> 8; + + rasterIRQRows[n] = row; +} + +static const byte irqai[6] = {RIRQ_ADDR_0, RIRQ_ADDR_1, RIRQ_ADDR_2, RIRQ_ADDR_3, RIRQ_ADDR_4}; +static const byte irqdi[6] = {RIRQ_DATA_0, RIRQ_DATA_1, RIRQ_DATA_2, RIRQ_DATA_3, RIRQ_DATA_4}; + +void rirq_addr(RIRQCode * ic, byte n, void * addr) +{ + byte p = irqai[n]; + ic->code[p + 0] = (unsigned)addr & 0xff; + ic->code[p + 1] = (unsigned)addr >> 8; +} + +void rirq_data(RIRQCode * ic, byte n, byte data) +{ + byte p = irqdi[n]; + ic->code[p] = data; +} + +void rirq_write(RIRQCode * ic, byte n, void * addr, byte data) +{ + byte p = irqai[n]; + ic->code[p + 0] = (unsigned)addr & 0xff; + ic->code[p + 1] = (unsigned)addr >> 8; + p = irqdi[n]; + ic->code[p] = data; +} + +void rirq_move(byte n, byte row) +{ + rasterIRQRows[n] = row; +} + +void rirq_clear(byte n) +{ + rasterIRQRows[n] = 255; +} + +void rirq_init(bool kernalIRQ) +{ + for(byte i=0; i 0 && rr < rasterIRQRows[rj]) + { + rasterIRQIndex[j] = rj; + j--; + rj = rasterIRQIndex[j - 1] + } + rasterIRQIndex[j] = ri; + } + + for(byte i=0; imSrc[i])) return false; + if (mCode == IC_CONSTANT && !mConst.IsEqual(ins->mConst)) + return false; + return true; } @@ -1845,6 +1848,7 @@ InterCodeBasicBlock::InterCodeBasicBlock(void) { mInPath = false; mLoopHead = false; + mChecked = false; } InterCodeBasicBlock::~InterCodeBasicBlock(void) @@ -1884,15 +1888,23 @@ void InterCodeBasicBlock::CollectEntries(void) } } -static bool IsInfiniteLoop(const InterCodeBasicBlock* block) +static bool IsInfiniteLoop(InterCodeBasicBlock* head, InterCodeBasicBlock* block) { - const InterCodeBasicBlock* nblock = block; - while (nblock->mTrueJump && !nblock->mFalseJump) + if (!block->mChecked) { - nblock = nblock->mTrueJump; - if (nblock == block) - return true; + if (block->mTrueJump && !block->mFalseJump) + { + if (block->mTrueJump == head) + return true; + + block->mChecked = true; + bool loop = IsInfiniteLoop(head, block->mTrueJump); + block->mChecked = false; + + return loop; + } } + return false; } @@ -1924,7 +1936,7 @@ void InterCodeBasicBlock::GenerateTraces(bool expand) if (mFalseJump) mFalseJump->mNumEntries++; } - else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump)) + else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump)) { mTrueJump->mNumEntries--; @@ -2140,6 +2152,33 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI ins->mSrc[1].mIntConst = tvalue[ins->mSrc[1].mTemp]->mConst.mIntConst; ins->mSrc[1].mOperandSize = tvalue[ins->mSrc[1].mTemp]->mConst.mOperandSize; ins->mSrc[1].mTemp = -1; + + if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_BINARY_OPERATOR) + { + InterInstruction* iins = tvalue[ins->mSrc[0].mTemp]; + if (iins->mOperator == IA_ADD) + { + if (iins->mSrc[0].mTemp >= 0 && iins->mSrc[1].mTemp < 0) + { + ins->mSrc[0].mTemp = iins->mSrc[0].mTemp; + ins->mSrc[1].mIntConst += iins->mSrc[1].mIntConst; + } + else if (iins->mSrc[0].mTemp < 0 && iins->mSrc[1].mTemp >= 0) + { + ins->mSrc[0].mTemp = iins->mSrc[1].mTemp; + ins->mSrc[1].mIntConst += iins->mSrc[0].mIntConst; + } + } + else if (iins->mOperator == IA_SUB) + { + if (iins->mSrc[0].mTemp < 0 && iins->mSrc[1].mTemp >= 0) + { + ins->mSrc[0].mTemp = iins->mSrc[1].mTemp; + ins->mSrc[1].mIntConst -= iins->mSrc[0].mIntConst; + } + } + + } } break; case IC_TYPECAST: diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 2e85f48..8ced327 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -408,7 +408,7 @@ public: InterCodeBasicBlock * mTrueJump, * mFalseJump, * mDominator; GrowingInstructionArray mInstructions; - bool mVisited, mInPath, mLoopHead; + bool mVisited, mInPath, mLoopHead, mChecked; NumberSet mLocalRequiredTemps, mLocalProvidedTemps; NumberSet mEntryRequiredTemps, mEntryProvidedTemps; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 7d0f50f..cac281c 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -123,7 +123,7 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) requiredTemps -= CPU_REG_A; requiredTemps -= CPU_REG_X; requiredTemps -= CPU_REG_Y; - + if (mFlags & NCIF_RUNTIME) { for (int i = 0; i < 4; i++) @@ -515,6 +515,11 @@ bool NativeCodeInstruction::ChangesYReg(void) const return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR; } +bool NativeCodeInstruction::ChangesXReg(void) const +{ + return mType == ASMIT_TAX || mType == ASMIT_LDX || mType == ASMIT_INX || mType == ASMIT_DEX || mType == ASMIT_JSR; +} + bool NativeCodeInstruction::ChangesZeroPage(int address) const { if (mMode == ASMIM_ZERO_PAGE && mAddress == address) @@ -1888,6 +1893,21 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps += BC_REG_ADDR + i; } + if (!(mFlags & NCIF_RUNTIME)) + { + if (mLinkerObject) + { + for (int i = 0; i < mLinkerObject->mNumTemporaries; i++) + { + for (int j = 0; j < mLinkerObject->mTempSizes[i]; j++) + { + if (!providedTemps[mLinkerObject->mTemporaries[i] + j]) + requiredTemps += mLinkerObject->mTemporaries[i] + j; + } + } + } + } + providedTemps += CPU_REG_A; providedTemps += CPU_REG_X; providedTemps += CPU_REG_Y; @@ -4806,8 +4826,15 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg)); if (InterTypeSize[ins->mDst.mType] > 1) { - mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, 2)); - mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg + 1)); + NativeCodeBasicBlock* iblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + + this->Close(eblock, iblock, ASMIT_BNE); + + iblock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg + 1)); + + iblock->Close(eblock, nullptr, ASMIT_JMP); + return eblock; } } else if (ins->mOperator == IA_ADD && InterTypeSize[ins->mDst.mType] == 1 && ( @@ -4883,18 +4910,46 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p { if (sins1 && sins0) { - insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg); - insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg + 1); - - if (sins1->mDst.mTemp == ins->mDst.mTemp) + if (sins0->mSrc[0].mMemory == IM_INDIRECT && sins1->mSrc[0].mMemory == IM_INDIRECT && sins0->mSrc[0].mIntConst < 255 && sins1->mSrc[0].mIntConst < 255) { - LoadValueToReg(proc, sins1, treg, nullptr, nullptr); - LoadValueToReg(proc, sins0, treg, &insl, &insh); + if (ins->mOperator == IA_ADD) + mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins0->mSrc[0].mIntConst + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins0->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins1->mSrc[0].mIntConst + 0)); + mIns.Push(NativeCodeInstruction(atype, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins1->mSrc[0].mTemp])); + if (InterTypeSize[ins->mDst.mType] > 1) + { + if (ins->mDst.mTemp == sins0->mSrc[0].mTemp || ins->mDst.mTemp == sins1->mSrc[0].mTemp) + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + else + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins0->mSrc[0].mIntConst + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins0->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins1->mSrc[0].mIntConst + 1)); + mIns.Push(NativeCodeInstruction(atype, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins1->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (ins->mDst.mTemp == sins0->mSrc[0].mTemp || ins->mDst.mTemp == sins1->mSrc[0].mTemp) + mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg)); + } + else + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); } else { - LoadValueToReg(proc, sins0, treg, nullptr, nullptr); - LoadValueToReg(proc, sins1, treg, &insl, &insh); + insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg); + insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg + 1); + + if (sins1->mDst.mTemp == ins->mDst.mTemp) + { + LoadValueToReg(proc, sins1, treg, nullptr, nullptr); + LoadValueToReg(proc, sins0, treg, &insl, &insh); + } + else + { + LoadValueToReg(proc, sins0, treg, nullptr, nullptr); + LoadValueToReg(proc, sins1, treg, &insl, &insh); + } } } else if (sins1) @@ -6389,7 +6444,7 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc } } -void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins) +void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction* ins) { if (ins->mCode == IC_ASSEMBLER) { @@ -6408,6 +6463,7 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterIn } assert(ins->mSrc[0].mLinkerObject); + mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject)); if (ins->mDst.mTemp >= 0) @@ -6820,7 +6876,7 @@ bool NativeCodeBasicBlock::FindGlobalAddress(int at, int reg, int& apos) return false; } -bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, const NativeCodeInstruction*& ains, int& ireg) +bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction*& ains, int& ireg) { int j = at - 7; while (j >= 0) @@ -6835,17 +6891,53 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, const NativeCo { ains = &(mIns[j + 1]); ireg = mIns[j + 2].mAddress; + apos = j + 0; + + if (reg == ireg && !direct) + return false; int k = j + 7; while (k < at) { if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) return false; + if (reg == ireg && mIns[k].ChangesYReg()) + return false; k++; } return true; } + else if ( + mIns[j + 0].mType == ASMIT_STA && mIns[j + 0].mMode == ASMIM_ZERO_PAGE && + mIns[j + 1].mType == ASMIT_CLC && + mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_LOWER) && mIns[j + 2].mLinkerObject && + mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg && + mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 2].mLinkerObject && + mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 && + mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1) + { + ains = &(mIns[j + 2]); + ireg = mIns[j + 0].mAddress; + apos = j + 1; + + if (reg == ireg && !direct) + return false; + + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress()) + return false; + if (reg == ireg && mIns[k].ChangesYReg()) + return false; + k++; + } + + return true; + } + + if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress()) return false; @@ -6860,7 +6952,7 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, const NativeCo return false; j--; } - if (mFromJump->FindGlobalAddressSumY(mFromJump->mIns.Size(), reg, ains, ireg)) + if (mFromJump->FindGlobalAddressSumY(mFromJump->mIns.Size(), reg, false, apos, ains, ireg)) { int k = 0; while (k < at) @@ -6876,6 +6968,7 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, const NativeCo return false; } + bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg) { int j = at - 7; @@ -6958,6 +7051,7 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at) { if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress) { + mIns[j].mLive |= LIVE_CPU_REG_A; mIns.Insert(j + 1, mIns[at + 1]); mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED; @@ -6998,6 +7092,7 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) { mIns[i] = mIns[i - 1]; } + mIns[j - 1].mLive |= LIVE_CPU_REG_A; mIns[j] = mIns[at + 1]; mIns[at + 1].mType = ASMIT_NOP; @@ -7463,7 +7558,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mVisited = true; - #if 1 // move load store pairs up to initial store @@ -7516,7 +7610,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && (mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0) - { + { if (MoveLoadAddImmStoreUp(i)) changed = true; } @@ -7602,8 +7696,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) { const NativeCodeInstruction* ains; + int sreg = mIns[i + 0].mAddress; + int apos, breg, ireg; - if (FindAddressSumY(i, mIns[i + 0].mAddress, apos, breg, ireg)) + if (FindAddressSumY(i, sreg, apos, breg, ireg)) { if (breg != mIns[i + 0].mAddress || !(mIns[i + 0].mLive & LIVE_MEM)) { @@ -7625,7 +7721,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) progress = true; } } - else if (FindGlobalAddressSumY(i, mIns[i + 0].mAddress, ains, ireg)) + else if (FindGlobalAddressSumY(i, sreg, true, apos, ains, ireg)) { if (mIns[i + 0].mLive & LIVE_CPU_REG_Y) { @@ -7633,11 +7729,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mLive |= LIVE_CPU_REG_Y; } - mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg)); - mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; - mIns[i + 1].mLinkerObject = ains->mLinkerObject; - mIns[i + 1].mAddress = ains->mAddress; - mIns[i + 1].mFlags &= ~NCIF_YZERO; + mIns[i + 0].mMode = ASMIM_ABSOLUTE_Y; + mIns[i + 0].mLinkerObject = ains->mLinkerObject; + mIns[i + 0].mAddress = ains->mAddress; + mIns[i + 0].mFlags &= ~NCIF_YZERO; + + if (ireg == sreg) + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg)); + else + mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg)); progress = true; } @@ -7762,6 +7862,38 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 0].mType = ASMIT_LDA; progress = true; } + else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_INDIRECT_Y) + { + const NativeCodeInstruction* ains; + + int sreg = mIns[i + 1].mAddress; + int apos, ireg; + if (FindGlobalAddressSumY(i, sreg, true, apos, ains, ireg)) + { + if (mIns[i + 1].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 2, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, mIns[i + 0].mAddress)); + mIns[i + 2].mLive |= LIVE_CPU_REG_Y; + } + + mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; + mIns[i + 1].mLinkerObject = ains->mLinkerObject; + mIns[i + 1].mAddress = ains->mAddress + mIns[i + 0].mAddress; + + if (ireg == sreg) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg)); + } + else + { + mIns[i + 0].mMode = ASMIM_ZERO_PAGE; + mIns[i + 0].mAddress = ireg; + } + + progress = true; + } + } } @@ -7909,6 +8041,13 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) progress = true; } #endif + else if ( + mIns[i + 0].mType == ASMIT_TAX && + !mIns[i + 1].ChangesXReg() && + mIns[i + 2].mType == ASMIT_TXA && !(mIns[i + 2].mLive & LIVE_CPU_REG_Z)) + { + mIns[i + 2].mType = ASMIT_NOP; + } #if 1 if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && @@ -8636,6 +8775,8 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) bool changed; do { + changed = false; + ResetVisited(); for (int i = 0; i < mBlocks.Size(); i++) { @@ -8646,6 +8787,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } entryBlock->CountEntries(nullptr); +#if 1 do { BuildDataFlowSets(); @@ -8658,7 +8800,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) changed = true; } while (changed); - +#endif ResetVisited(); if (entryBlock->PeepHoleOptimizer()) changed = true; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index d0086d7..65c7c46 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -73,6 +73,7 @@ public: bool RequiresAccu(void) const; bool RequiresYReg(void) const; bool ChangesYReg(void) const; + bool ChangesXReg(void) const; bool ChangesZeroPage(int address) const; bool UsesZeroPage(int address) const; bool ChangesGlobalMemory(void) const; @@ -164,7 +165,7 @@ public: bool MoveLoadAddImmStoreUp(int at); bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg); bool FindGlobalAddress(int at, int reg, int& apos); - bool FindGlobalAddressSumY(int at, int reg, const NativeCodeInstruction * & ains, int& ireg); + bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, int& ireg); bool ValueForwarding(const NativeRegisterDataSet& data);