diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 67b1c07..1a34c5f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2148,7 +2148,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mRight->mType == EX_LIST) { Expression* tex = exp->mRight->mLeft, * sex = exp->mRight->mRight->mLeft, * nex = exp->mRight->mRight->mRight; - if (nex && nex->mType == EX_CONSTANT && nex->mDecValue->mType == DT_CONST_INTEGER && nex->mDecValue->mInteger < 128) + if (nex && nex->mType == EX_CONSTANT && nex->mDecValue->mType == DT_CONST_INTEGER && nex->mDecValue->mInteger < 512) { vl = TranslateExpression(procType, proc, block, tex, breakBlock, continueBlock, inlineMapper); if (vl.mType->mType == DT_TYPE_ARRAY) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index e7c4d44..06817d9 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7013,6 +7013,23 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, { block = nproc->AllocateBlock(); + if (sreg != BC_REG_ACCU && !ins->mSrc[0].mFinal) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + sreg = BC_REG_ACCU; + } + if (dreg != BC_REG_ADDR && !ins->mSrc[1].mFinal) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, dreg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, dreg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR + 1)); + dreg = BC_REG_ADDR; + } + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); NativeCodeBasicBlock* lblock2 = nproc->AllocateBlock(); @@ -17069,6 +17086,81 @@ void NativeCodeBasicBlock::ChangeTailZPStoreToY(int addr) assert(false); } +bool NativeCodeBasicBlock::IsExitYRegZP(int addr, int& index) const +{ + int i = mIns.Size() - 1; + while (i >= 0) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_LDY)) + { + if (addr == mIns[i].mAddress) + { + index = i; + return true; + } + return false; + } + else if (mIns[i].ChangesYReg()) + return false; + else if (mIns[i].ChangesZeroPage(addr)) + return false; + + i--; + } + + return false; +} + +bool NativeCodeBasicBlock::IsExitXRegZP(int addr, int& index) const +{ + int i = mIns.Size() - 1; + while (i >= 0) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && (mIns[i].mType == ASMIT_STX || mIns[i].mType == ASMIT_LDX)) + { + if (addr == mIns[i].mAddress) + { + index = i; + return true; + } + return false; + } + else if (mIns[i].ChangesXReg()) + return false; + else if (mIns[i].ChangesZeroPage(addr)) + return false; + + i--; + } + + return false; +} + +bool NativeCodeBasicBlock::IsExitARegZP(int addr, int& index) const +{ + int i = mIns.Size() - 1; + while (i >= 0) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && (mIns[i].mType == ASMIT_STA || mIns[i].mType == ASMIT_LDA)) + { + if (addr == mIns[i].mAddress) + { + index = i; + return true; + } + return false; + } + else if (mIns[i].ChangesAccu()) + return false; + else if (mIns[i].ChangesZeroPage(addr)) + return false; + + i--; + } + + return false; +} + bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops) { @@ -18186,6 +18278,117 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool } } +#if 1 + if (mEntryBlocks.Size() > 1 && mIns.Size() > 0) + { + if (mIns[0].mType == ASMIT_LDY && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_CPU_REG_Z)) + { + int ei = 0; + int index; + bool found = false, fail = false; + + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitYRegZP(mIns[0].mAddress, index)) + found = true; + else if (mEntryBlocks[i]->mFalseJump) + fail = true; + } + + if (found && !fail) + { + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitYRegZP(mIns[0].mAddress, index)) + { + while (index < mEntryBlocks[i]->mIns.Size()) + mEntryBlocks[i]->mIns[index++].mLive |= LIVE_CPU_REG_Y; + mEntryBlocks[i]->mExitRequiredRegs += CPU_REG_Y; + } + else + { + mEntryBlocks[i]->mIns.Push(mIns[0]); + } + } + + mEntryRequiredRegs += CPU_REG_Y; + mIns.Remove(0); + changed = true; + } + } + else if (mIns[0].mType == ASMIT_LDX && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_CPU_REG_Z)) + { + int ei = 0; + int index; + bool found = false, fail = false; + + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitXRegZP(mIns[0].mAddress, index)) + found = true; + else if (mEntryBlocks[i]->mFalseJump) + fail = true; + } + + if (found && !fail) + { + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitXRegZP(mIns[0].mAddress, index)) + { + while (index < mEntryBlocks[i]->mIns.Size()) + mEntryBlocks[i]->mIns[index++].mLive |= LIVE_CPU_REG_X; + mEntryBlocks[i]->mExitRequiredRegs += CPU_REG_X; + } + else + { + mEntryBlocks[i]->mIns.Push(mIns[0]); + } + } + + mEntryRequiredRegs += CPU_REG_X; + mIns.Remove(0); + changed = true; + } + } + else if (mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_CPU_REG_Z)) + { + int ei = 0; + int index; + bool found = false, fail = false; + + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitARegZP(mIns[0].mAddress, index)) + found = true; + else if (mEntryBlocks[i]->mFalseJump) + fail = true; + } + + if (found && !fail) + { + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i]->IsExitARegZP(mIns[0].mAddress, index)) + { + while (index < mEntryBlocks[i]->mIns.Size()) + mEntryBlocks[i]->mIns[index++].mLive |= LIVE_CPU_REG_A; + mEntryBlocks[i]->mExitRequiredRegs += CPU_REG_A; + } + else + { + mEntryBlocks[i]->mIns.Push(mIns[0]); + } + } + + mEntryRequiredRegs += CPU_REG_A; + mIns.Remove(0); + changed = true; + } + } + } +#endif + CheckLive(); if (mTrueJump && mTrueJump->JoinTailCodeSequences(proc, loops)) @@ -26831,24 +27034,27 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) proc->ResetPatched(); if (CollectGenericLoop(proc, lblocks)) { - int yreg = -1, xreg = -1; - int zyreg[256], zxreg[256]; - for (int i = 0; i < 256; i++) + int yreg = -1, xreg = -1, areg = -1; + int zyreg[NUM_REGS], zxreg[NUM_REGS], zareg[NUM_REGS]; + for (int i = 0; i < NUM_REGS; i++) { zyreg[i] = 0; zxreg[i] = 0; + zareg[i] = 0; } if (mEntryRequiredRegs[CPU_REG_Y]) yreg = -2; if (mEntryRequiredRegs[CPU_REG_X]) xreg = -2; + if (mEntryRequiredRegs[CPU_REG_A]) + areg = -2; for (int i = 0; i < lblocks.Size(); i++) { NativeCodeBasicBlock* block = lblocks[i]; - int yoffset = 0, xoffset = 0; + int yoffset = 0, xoffset = 0, aoffset = 0; for (int j = 0; j < block->mIns.Size(); j++) { @@ -26862,8 +27068,12 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) else yreg = -2; if (ins.mMode == ASMIM_ZERO_PAGE) + { zxreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; + } yoffset = 0; + zareg[CPU_REG_Y] = -1; break; case ASMIT_LDX: if (ins.mMode == ASMIM_ZERO_PAGE && (xreg == -1 || xreg == ins.mAddress)) @@ -26871,28 +27081,42 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) else xreg = -2; if (ins.mMode == ASMIM_ZERO_PAGE) + { zyreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; + } xoffset = 0; + zareg[CPU_REG_X] = -1; break; case ASMIT_STY: if (ins.mMode == ASMIM_ZERO_PAGE) + { zxreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; + } break; case ASMIT_STX: if (ins.mMode == ASMIM_ZERO_PAGE) + { zyreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; + } break; case ASMIT_INY: yoffset++; + zareg[CPU_REG_Y] = -1; break; case ASMIT_DEY: yoffset--; + zareg[CPU_REG_Y] = -1; break; case ASMIT_INX: xoffset++; + zareg[CPU_REG_X] = -1; break; case ASMIT_DEX: xoffset--; + zareg[CPU_REG_X] = -1; break; case ASMIT_INC: case ASMIT_DEC: @@ -26907,6 +27131,11 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) case ASMIT_LDA: if (ins.mMode == ASMIM_ZERO_PAGE) { + if ((areg == -1 || areg == ins.mAddress) && !(ins.mLive & LIVE_CPU_REG_Z)) + areg = ins.mAddress; + else + areg = -2; + if (ins.mAddress == yreg && yoffset != 0) yreg = -2; if (ins.mAddress == xreg && xoffset != 0) @@ -26917,6 +27146,8 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) if (zyreg[ins.mAddress] >= 0) zyreg[ins.mAddress]++; } + else + areg = -2; break; case ASMIT_STA: if (ins.mMode == ASMIM_ZERO_PAGE) @@ -26935,20 +27166,33 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) case ASMIT_TYA: if (yoffset) yreg = -2; + else if ((areg == -1 || areg == CPU_REG_Y) && !(ins.mLive & LIVE_CPU_REG_Z)) + areg = CPU_REG_Y; + else + areg = -2; break; case ASMIT_TXA: if (xoffset) xreg = -2; + else if ((areg == -1 || areg == CPU_REG_X) && !(ins.mLive & LIVE_CPU_REG_Z)) + areg = CPU_REG_X; + else + areg = -2; break; case ASMIT_TAY: yreg = -2; + zareg[CPU_REG_Y] = -1; break; case ASMIT_TAX: xreg = -2; + zareg[CPU_REG_X] = -1; break; case ASMIT_JSR: yreg = -2; xreg = -2; + areg = -2; + zareg[CPU_REG_X] = -1; + zareg[CPU_REG_Y] = -1; break; case ASMIT_CMP: if (ins.mMode == ASMIM_INDIRECT_Y && yoffset != 0 && yreg >= 0) @@ -26959,6 +27203,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { zxreg[ins.mAddress] = -1; zyreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; } break; default: @@ -26966,20 +27211,27 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { zxreg[ins.mAddress] = -1; zyreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; } + if (ins.ChangesAccu()) + areg = -2; } if (!(ins.mLive & LIVE_CPU_REG_Y)) yoffset = 0; if (!(ins.mLive & LIVE_CPU_REG_X)) xoffset = 0; + if (!(ins.mLive & LIVE_CPU_REG_A)) + aoffset = 0; if (ins.mMode == ASMIM_INDIRECT_Y) { zxreg[ins.mAddress] = -1; zyreg[ins.mAddress] = -1; + zareg[ins.mAddress] = -1; zxreg[ins.mAddress + 1] = -1; zyreg[ins.mAddress + 1] = -1; + zareg[ins.mAddress + 1] = -1; } } #if 1 @@ -26987,9 +27239,22 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) yreg = -2; if (xoffset && block->mExitRequiredRegs[CPU_REG_X]) xreg = -2; + if (aoffset && block->mExitRequiredRegs[CPU_REG_A]) + areg = -2; #endif } + if (areg >= 0) + { + if (zareg[areg] < 0) + areg = -2; + else + { + zxreg[areg] = -1; + zyreg[areg] = -1; + } + } + if (xreg != -2) { if (xreg == -1) @@ -27026,7 +27291,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) yreg = -1; } - if (yreg >= 0 || xreg >= 0) + if (yreg >= 0 || xreg >= 0 || areg >= 0) { GrowingArray entries(nullptr); GrowingArray exits(nullptr); @@ -27045,10 +27310,21 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) block->mEntryRequiredRegs += CPU_REG_X; block->mExitRequiredRegs += CPU_REG_X; } + if (areg >= 0) + { + block->mEntryRequiredRegs += CPU_REG_A; + block->mExitRequiredRegs += CPU_REG_A; + } if (block->mTrueJump && !lblocks.Contains(block->mTrueJump)) { block->mTrueJump = block->BuildSingleEntry(proc, block->mTrueJump); + if (areg >= 0 && block->mTrueJump->mEntryRequiredRegs[areg]) + { + if (areg < 256) + block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, areg)); + block->mTrueJump->mEntryRequiredRegs += CPU_REG_A; + } if (yreg >= 0 && block->mTrueJump->mEntryRequiredRegs[yreg]) { block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); @@ -27063,6 +27339,12 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) if (block->mFalseJump && !lblocks.Contains(block->mFalseJump)) { block->mFalseJump = block->BuildSingleEntry(proc, block->mFalseJump); + if (areg >= 0 && block->mFalseJump->mEntryRequiredRegs[areg]) + { + if (areg < 256) + block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, areg)); + block->mFalseJump->mEntryRequiredRegs += CPU_REG_A; + } if (yreg >= 0 && block->mFalseJump->mEntryRequiredRegs[yreg]) { block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); @@ -27080,6 +27362,16 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) if (!lblocks.Contains(block->mEntryBlocks[j])) { block->mEntryBlocks[j] = block->BuildSingleExit(proc, block->mEntryBlocks[j]); + if (areg >= 0 && mEntryRequiredRegs[areg]) + { + if (areg == CPU_REG_X) + block->mEntryBlocks[j]->mIns.Push(NativeCodeInstruction(ASMIT_TXA)); + else if (areg == CPU_REG_Y) + block->mEntryBlocks[j]->mIns.Push(NativeCodeInstruction(ASMIT_TYA)); + else + block->mEntryBlocks[j]->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, areg)); + block->mEntryBlocks[j]->mExitRequiredRegs += CPU_REG_A; + } if (yreg >= 0 && mEntryRequiredRegs[yreg]) { block->mEntryBlocks[j]->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, yreg)); @@ -27145,7 +27437,12 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) break; case ASMIT_LDA: - if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == yreg) + if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == areg) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + } + else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == yreg) { ins.mType = ASMIT_TYA; ins.mMode = ASMIM_IMPLIED; @@ -27157,7 +27454,12 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) } break; case ASMIT_STA: - if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == yreg) + if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == areg) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + } + else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == yreg) { ins.mType = ASMIT_TAY; ins.mMode = ASMIM_IMPLIED; @@ -27181,6 +27483,15 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) case ASMIT_DEX: xoffset--; break; + + case ASMIT_TXA: + if (areg == CPU_REG_X) + ins.mType = ASMIT_NOP; + break; + case ASMIT_TYA: + if (areg == CPU_REG_Y) + ins.mType = ASMIT_NOP; + break; } if (yoffset && yreg >= 0 && !(ins.mLive & LIVE_CPU_REG_Y)) @@ -27225,6 +27536,8 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) ins.mLive |= LIVE_CPU_REG_Y; if (xreg >= 0) ins.mLive |= LIVE_CPU_REG_X; + if (areg >= 0) + ins.mLive |= LIVE_CPU_REG_A; } @@ -30022,6 +30335,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } +#if 1 + else if (pass >= 3 && + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode != ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_CMP && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + NativeCodeInstruction ins(mIns[i + 1]); + mIns[i + 1].CopyMode(mIns[i + 0]); + mIns[i + 0].CopyMode(ins); + if (mIns[i + 1].RequiresXReg()) + mIns[i + 0].mLive |= LIVE_CPU_REG_X; + if (mIns[i + 1].RequiresYReg()) + mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + progress = true; + } +#endif else if ( mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress && (mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR) && !(mIns[i + 0].mLive & LIVE_CPU_REG_A)) @@ -35624,7 +35952,7 @@ void NativeCodeProcedure::RebuildEntry(void) void NativeCodeProcedure::Optimize(void) { - CheckFunc = !strcmp(mInterProc->mIdent->mString, "rscreen_copy"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "rirq_sort"); #if 1 int step = 0; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index f200743..3e523b2 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -405,6 +405,11 @@ public: bool HasTailSTA(int& addr, int& index) const; bool HasTailSTX(int& addr, int& index) const; bool HasTailSTY(int& addr, int& index) const; + + bool IsExitYRegZP(int addr, int& index) const; + bool IsExitXRegZP(int addr, int& index) const; + bool IsExitARegZP(int addr, int& index) const; + bool PropagateSinglePath(void); bool CanChangeTailZPStoreToX(int addr, const NativeCodeBasicBlock * nblock, const NativeCodeBasicBlock* fblock = nullptr) const;