From efff725745345a8519b4662e77a038f712df7d31 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 9 Mar 2023 19:29:46 +0100 Subject: [PATCH] Improve labels in disassembler listing, add mlb file for nes --- include/nes/neslib.c | 4 +- oscar64/Compiler.cpp | 10 +- oscar64/Disassembler.cpp | 8 +- oscar64/InterCodeGenerator.cpp | 83 +++++++ oscar64/Linker.cpp | 43 ++++ oscar64/Linker.h | 40 ++-- oscar64/NativeCodeGenerator.cpp | 380 ++++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.h | 5 + 8 files changed, 539 insertions(+), 34 deletions(-) diff --git a/include/nes/neslib.c b/include/nes/neslib.c index c4dfe17..a8af9e1 100644 --- a/include/nes/neslib.c +++ b/include/nes/neslib.c @@ -570,9 +570,9 @@ void flush_vram_update(unsigned char *buf) else { if (c < 0x80) - ppu.control = PPU_CTRL_VAR | 0x04; - else if (c != 0xff) ppu.control = PPU_CTRL_VAR & ~0x04; + else if (c != 0xff) + ppu.control = PPU_CTRL_VAR | 0x04; else return; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 56c4cb9..ce248dc 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -821,10 +821,14 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64) } else if (mCompilerOptions & COPT_TARGET_NES) { + strcpy_s(lblPath, prgPath); + strcat_s(lblPath, "mlb"); + strcat_s(prgPath, "nes"); if (mCompilerOptions & COPT_VERBOSE) printf("Writing <%s>\n", prgPath); mLinker->WriteNesFile(prgPath); + } @@ -852,7 +856,11 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64) if (mCompilerOptions & COPT_VERBOSE) printf("Writing <%s>\n", lblPath); - mLinker->WriteLblFile(lblPath); + + if (mCompilerOptions & COPT_TARGET_NES) + mLinker->WriteMlbFile(lblPath); + else + mLinker->WriteLblFile(lblPath); if (mCompilerOptions & COPT_VERBOSE) printf("Writing <%s>\n", intPath); diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index a8296b6..31f7346 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -756,7 +756,13 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, Linker* lin LinkerObject* obj = linker->FindObjectByAddr(addr); if (obj && obj->mIdent) { - sprintf_s(buffer, 160, "; (%s + %d)", obj->mIdent->mString, addr - obj->mAddress); + int i = 0; + while (i < obj->mRanges.Size() && (addr - obj->mAddress < obj->mRanges[i].mOffset || addr - obj->mAddress - obj->mRanges[i].mOffset >= obj->mRanges[i].mSize)) + i++; + if (i < obj->mRanges.Size()) + sprintf_s(buffer, 160, "; (%s.%s + %d)", obj->mIdent->mString, obj->mRanges[i].mIdent->mString, addr - obj->mAddress - obj->mRanges[i].mOffset); + else + sprintf_s(buffer, 160, "; (%s + %d)", obj->mIdent->mString, addr - obj->mAddress); return buffer; } } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 89ce463..da4e7f7 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -238,6 +238,82 @@ void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration proc->mLocalVars[index]->mIdent = dec->mIdent; } } +static const Ident* StructIdent(const Ident* base, const Ident* item) +{ + if (base) + { + char buffer[200]; + strcpy_s(buffer, base->mString); + strcat_s(buffer, "."); + strcat_s(buffer, item->mString); + return Ident::Unique(buffer); + } + else + return item; +} + +static void AddGlobalVariableRanges(LinkerObject* lo, Declaration* dec, int offset, const Ident* ident) +{ + switch (dec->mType) + { + case DT_TYPE_STRUCT: + { + Declaration* deci = dec->mParams; + while (deci) + { + AddGlobalVariableRanges(lo, deci->mBase, offset + deci->mOffset, StructIdent(ident, deci->mIdent)); + deci = deci->mNext; + } + } break; + case DT_TYPE_INTEGER: + case DT_TYPE_FLOAT: + case DT_TYPE_POINTER: + case DT_TYPE_BOOL: + case DT_TYPE_ENUM: + { + LinkerObjectRange range; + range.mOffset = offset; + range.mSize = dec->mStripe; + switch (dec->mSize) + { + case 1: + range.mIdent = ident; + lo->mRanges.Push(range); + break; + case 2: + range.mIdent = StructIdent(ident, Ident::Unique("lo")); + lo->mRanges.Push(range); + range.mOffset += dec->mStripe; + range.mIdent = StructIdent(ident, Ident::Unique("hi")); + lo->mRanges.Push(range); + break; + case 4: + range.mIdent = StructIdent(ident, Ident::Unique("b0")); + lo->mRanges.Push(range); + range.mOffset += dec->mStripe; + range.mIdent = StructIdent(ident, Ident::Unique("b1")); + lo->mRanges.Push(range); + range.mOffset += dec->mStripe; + range.mIdent = StructIdent(ident, Ident::Unique("b2")); + lo->mRanges.Push(range); + range.mOffset += dec->mStripe; + range.mIdent = StructIdent(ident, Ident::Unique("b3")); + lo->mRanges.Push(range); + break; + } + } break; + + default: + if (ident) + { + LinkerObjectRange range; + range.mIdent = ident; + range.mOffset = offset; + range.mSize = dec->mSize * dec->mStripe; + lo->mRanges.Push(range); + } + } +} void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* dec) { @@ -249,6 +325,13 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment); var->mIdent = dec->mIdent; + Declaration* decb = dec->mBase; + while (decb && decb->mType == DT_TYPE_ARRAY) + decb = decb->mBase; + + if (decb && decb->mStripe != 1) + AddGlobalVariableRanges(var->mLinkerObject, decb, 0, nullptr); + Declaration* type = dec->mBase; while (type->mType == DT_TYPE_ARRAY) type = type->mBase; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 3352637..ff226f0 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -944,6 +944,49 @@ bool Linker::WriteMapFile(const char* filename) return false; } +bool Linker::WriteMlbFile(const char* filename) +{ + FILE* file; + fopen_s(&file, filename, "wb"); + if (file) + { + fprintf(file, "R:%02x-%02x:__ACCU\n", BC_REG_ACCU, BC_REG_ACCU + 3); + fprintf(file, "R:%02x-%02x:__ADDR\n", BC_REG_ADDR, BC_REG_ADDR + 1); + fprintf(file, "R:%02x-%02x:__IP\n", BC_REG_IP, BC_REG_IP + 1); + fprintf(file, "R:%02x-%02x:__SP\n", BC_REG_STACK, BC_REG_STACK + 1); + fprintf(file, "R:%02x-%02x:__FP\n", BC_REG_LOCALS, BC_REG_LOCALS + 1); + fprintf(file, "R:%02x-%02x:__P\n", BC_REG_FPARAMS, BC_REG_FPARAMS_END - 1); + fprintf(file, "R:%02x-%02x:__T\n", BC_REG_TMP, 0x7f); + + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* obj = mObjects[i]; + + if ((obj->mFlags & LOBJF_REFERENCED) && obj->mIdent && obj->mSize > 0) + { + if (obj->mSection->mType == LST_BSS) + fprintf(file, "R:%04x-%04x:%s\n", obj->mAddress, obj->mAddress + obj->mSize - 1, obj->mIdent->mString); + else if (obj->mType == LOT_DATA) + { + if (!obj->mRegion->mCartridgeBanks) + fprintf(file, "P:%04x-%04x:%s\n", obj->mAddress - 0x8000, obj->mAddress - 0x8000 + obj->mSize - 1, obj->mIdent->mString); + } + else if (obj->mType == LOT_NATIVE_CODE) + { + if (!obj->mRegion->mCartridgeBanks) + fprintf(file, "P:%04x:%s\n", obj->mAddress - 0x8000, obj->mIdent->mString); + } + } + } + + fclose(file); + + return true; + } + else + return false; +} + bool Linker::WriteLblFile(const char* filename) { FILE* file; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index a00502e..0b56427 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -151,24 +151,33 @@ static const uint32 LOBJF_RET_REG_A = 0x00010000; static const uint32 LOBJF_RET_REG_X = 0x00020000; +class LinkerObjectRange +{ +public: + const Ident * mIdent; + int mOffset, mSize; +}; + class LinkerObject { public: - Location mLocation; - const Ident * mIdent; - LinkerObjectType mType; - int mID; - int mAddress, mRefAddress; - int mSize, mAlignment; - LinkerSection * mSection; - LinkerRegion * mRegion; - uint8 * mData; - InterCodeProcedure * mProc; - uint32 mFlags; - uint8 mTemporaries[16], mTempSizes[16]; - int mNumTemporaries; - ZeroPageSet mZeroPageSet; - LinkerSection * mStackSection; + Location mLocation; + const Ident * mIdent; + LinkerObjectType mType; + int mID; + int mAddress, mRefAddress; + int mSize, mAlignment; + LinkerSection * mSection; + LinkerRegion * mRegion; + uint8 * mData; + InterCodeProcedure * mProc; + uint32 mFlags; + uint8 mTemporaries[16], mTempSizes[16]; + int mNumTemporaries; + ZeroPageSet mZeroPageSet; + LinkerSection * mStackSection; + + ExpandingArray mRanges; LinkerObject(void); ~LinkerObject(void); @@ -230,6 +239,7 @@ public: bool WriteCrtFile(const char* filename); bool WriteBinFile(const char* filename); bool WriteNesFile(const char* filename); + bool WriteMlbFile(const char* filename); uint64 mCompilerOptions; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index f925c92..3a6fcce 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3235,26 +3235,44 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT } break; case ASMIT_TAX: - data.ResetX(); - data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A]; - if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE) + if (data.mRegs[CPU_REG_X].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z)) { - data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; - data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; + changed = true; } else - data.mRegs[CPU_REG_Z].Reset(); + { + data.ResetX(); + data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A]; + if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); + } break; case ASMIT_TAY: - data.ResetY(); - data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A]; - if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE) + if (data.mRegs[CPU_REG_Y].SameData(data.mRegs[CPU_REG_A]) && !(mLive & LIVE_CPU_REG_Z)) { - data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; - data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; + changed = true; } else - data.mRegs[CPU_REG_Z].Reset(); + { + data.ResetY(); + data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A]; + if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); + } break; } @@ -13139,6 +13157,202 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full) return changed; } +bool NativeCodeBasicBlock::CanCombineSameYtoX(int start, int end) +{ + for (int i = start; i < end; i++) + { + NativeCodeInstruction& ins(mIns[i]); + + if (ins.mMode == ASMIM_INDIRECT_Y) + return false; + + if (ins.mMode == ASMIM_ABSOLUTE_Y && !HasAsmInstructionMode(ins.mType, ASMIM_ABSOLUTE_X)) + return false; + } + + return true; +} + +bool NativeCodeBasicBlock::CanCombineSameXtoY(int start, int end) +{ + for (int i = start; i < end; i++) + { + NativeCodeInstruction& ins(mIns[i]); + + if (ins.mMode == ASMIM_INDIRECT_X) + return false; + + if (ins.mMode == ASMIM_ABSOLUTE_X && !HasAsmInstructionMode(ins.mType, ASMIM_ABSOLUTE_Y)) + return false; + + } + + return true; +} + + + +bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end) +{ + if (xpos < ypos) + { + if (CanCombineSameXtoY(xpos, ypos) && + CanCombineSameXtoY(ypos, end)) + { + ReplaceXRegWithYReg(xpos, ypos); + ReplaceXRegWithYReg(ypos, end); + return true; + } + } + else + { + if (CanCombineSameXtoY(xpos, end)) + { + ReplaceXRegWithYReg(xpos, end); +#if 0 + if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z)) + { + mIns[xpos].mType = ASMIT_NOP; + mIns[xpos].mMode = ASMIM_IMPLIED; + } +#endif + return true; + } + } + + return false; +} + +bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end) +{ + if (ypos < xpos) + { + if (CanCombineSameYtoX(ypos, xpos) && + CanCombineSameYtoX(xpos + 1, end)) + { + ReplaceYRegWithXReg(ypos, xpos); + ReplaceYRegWithXReg(xpos + 1, end); + return true; + } + } + else + { + if (CanCombineSameYtoX(ypos, end)) + { + ReplaceYRegWithXReg(ypos, end); +#if 0 + if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z)) + { + mIns[ypos].mType = ASMIT_NOP; + mIns[ypos].mMode = ASMIM_IMPLIED; + } +#endif + return true; + } + } + + return false; +} + +bool NativeCodeBasicBlock::CombineSameXY(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + int xreg = -1, yreg = -1; + int xpos, ypos; + bool samexy = false; + + for (int i = 0; i < mIns.Size(); i++) + { + NativeCodeInstruction& ins(mIns[i]); + + if (ins.ChangesXReg()) + { + if (samexy && CombineSameXtoY(xpos, ypos, i)) + changed = true; + xreg = -1; + samexy = false; + } + if (ins.ChangesYReg()) + { + if (samexy && CombineSameYtoX(ypos, xpos, i)) + changed = true; + yreg = -1; + samexy = false; + } + + if (ins.mType == ASMIT_TAX) + { + xreg = CPU_REG_A; + xpos = i; + samexy = yreg == xreg; + } + else if (ins.mType == ASMIT_TAY) + { + yreg = CPU_REG_A; + ypos = i; + samexy = xreg == yreg; + } + else if (ins.mType == ASMIT_LDX) + { + if (ins.mMode == ASMIM_ZERO_PAGE) + { + xreg = ins.mAddress; + xpos = i; + samexy = yreg == xreg; + } + else + xreg = -1; + } + else if (ins.mType == ASMIT_LDY) + { + if (ins.mMode == ASMIM_ZERO_PAGE) + { + yreg = ins.mAddress; + ypos = i; + samexy = xreg == yreg; + } + else + yreg = -1; + } + else if (ins.ChangesAccu()) + { + if (xreg == CPU_REG_A) + xreg = -1; + if (yreg == CPU_REG_A) + yreg = -1; + } + else if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress()) + { + if (xreg == ins.mAddress) + xreg = -1; + if (yreg == ins.mAddress) + yreg = -1; + } + } + + + if (samexy) + { + if (!mExitRequiredRegs[CPU_REG_X] && CombineSameXtoY(xpos, ypos, mIns.Size())) + changed = true; + else if (!mExitRequiredRegs[CPU_REG_Y] && CombineSameYtoX(xpos, ypos, mIns.Size())) + changed = true; + } + + if (mTrueJump && mTrueJump->CombineSameXY()) + changed = true; + if (mFalseJump && mFalseJump->CombineSameXY()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::RegisterValueForwarding(void) { bool changed = false; @@ -14920,6 +15134,89 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) break; } + if (mIns[i + 0].mType == ASMIT_TXA && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & LIVE_CPU_REG_X) && + mIns[i + 4].mType == ASMIT_LDA && + mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 && + mIns[i + 6].mType == ASMIT_STA && mIns[i + 4].SameEffectiveAddress(mIns[i + 6]) && + HasAsmInstructionMode(ASMIT_INC, mIns[i + 6].mMode) && + !(mIns[i + 6].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + changed = true; + + NativeCodeBasicBlock* iblock = proc->AllocateBlock(); + NativeCodeBasicBlock* fblock = proc->AllocateBlock(); + + fblock->mTrueJump = mTrueJump; + fblock->mFalseJump = mFalseJump; + fblock->mBranch = mBranch; + + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_INX; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_X; + mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mLive |= LIVE_CPU_REG_Z; + + fblock->mIns.Push(mIns[i + 4]); + + for (int j = i + 7; j < mIns.Size(); j++) + fblock->mIns.Push(mIns[j]); + iblock->mIns.Push(mIns[i + 6]); + + + mIns.SetSize(i + 4); + iblock->mIns[0].mType = ASMIT_INC; + + iblock->mTrueJump = fblock; + iblock->mBranch = ASMIT_JMP; + + mTrueJump = fblock; + mFalseJump = iblock; + mBranch = ASMIT_BNE; + break; + } + + if (mIns[i + 0].mType == ASMIT_TYA && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & LIVE_CPU_REG_Y) && + mIns[i + 4].mType == ASMIT_TXA && + mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 && + mIns[i + 6].mType == ASMIT_TAX && + !(mIns[i + 6].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + changed = true; + + NativeCodeBasicBlock* iblock = proc->AllocateBlock(); + NativeCodeBasicBlock* fblock = proc->AllocateBlock(); + + fblock->mTrueJump = mTrueJump; + fblock->mFalseJump = mFalseJump; + fblock->mBranch = mBranch; + + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_Y; + mIns[i + 3].mType = ASMIT_STY; mIns[i + 3].mLive |= LIVE_CPU_REG_Z; + + fblock->mIns.Push(NativeCodeInstruction(ASMIT_TXA)); + + for (int j = i + 7; j < mIns.Size(); j++) + fblock->mIns.Push(mIns[j]); + iblock->mIns.Push(NativeCodeInstruction(ASMIT_INX)); + + mIns.SetSize(i + 4); + + iblock->mTrueJump = fblock; + iblock->mBranch = ASMIT_JMP; + + mTrueJump = fblock; + mFalseJump = iblock; + mBranch = ASMIT_BNE; + break; + } + if (mIns[i + 0].mType == ASMIT_TYA && mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && @@ -25686,6 +25983,50 @@ bool NativeCodeBasicBlock::OptimizeLoopCarryOver(void) changed = true; } } + + int sz = mIns.Size(); + if (sz > 0) + { + hblock = nullptr; + + if (mTrueJump->mLoopHead) + hblock = mTrueJump; + else if (mFalseJump->mLoopHead) + hblock = mFalseJump; + + if (hblock && hblock->mIns.Size() > 0 && hblock->mNumEntries == 2) + { + NativeCodeBasicBlock* pblock; + if (hblock->mEntryBlocks[0] == this) + pblock = hblock->mEntryBlocks[1]; + else + pblock = hblock->mEntryBlocks[0]; + + if (!pblock->mFalseJump) + { + if (hblock->mIns[0].mType == ASMIT_TAX && mIns[sz - 1].mType == ASMIT_TXA && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z)) + { + pblock->mIns.Push(NativeCodeInstruction(ASMIT_TAX)); + hblock->mIns.Remove(0); + + pblock->mExitRequiredRegs += CPU_REG_X; + hblock->mEntryRequiredRegs += CPU_REG_X; + mExitRequiredRegs += CPU_REG_X; + changed = true; + } + else if (hblock->mIns[0].mType == ASMIT_TAY && mIns[sz - 1].mType == ASMIT_TYA && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z)) + { + pblock->mIns.Push(NativeCodeInstruction(ASMIT_TAY)); + hblock->mIns.Remove(0); + + pblock->mExitRequiredRegs += CPU_REG_Y; + hblock->mEntryRequiredRegs += CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + changed = true; + } + } + } + } } if (mTrueJump && mTrueJump->OptimizeLoopCarryOver()) @@ -32212,6 +32553,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_SEC && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff && + mIns[i + 2].mType == ASMIT_SBC) + { + mIns[i + 2].mType = ASMIT_EOR; + progress = true; + } else if ( mIns[i + 0].mType == ASMIT_EOR && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x80 && mIns[i + 1].mType == ASMIT_SEC && @@ -37389,13 +37738,14 @@ void NativeCodeProcedure::Optimize(void) ResetVisited(); if (mEntryBlock->MoveAccuTrainsDown()) changed = true; + + ResetVisited(); + if (mEntryBlock->CombineSameXY()) + changed = true; } #endif - - - #if 1 if (step == 6) { diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 03e0106..3fd3ce3 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -377,6 +377,11 @@ public: bool ForwardZpXIndex(bool full); bool RegisterValueForwarding(void); + bool CanCombineSameXtoY(int start, int end); + bool CanCombineSameYtoX(int start, int end); + bool CombineSameXY(void); + bool CombineSameXtoY(int xpos, int ypos, int end); + bool CombineSameYtoX(int xpos, int ypos, int end); bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);