From 5ccfab034249b10b8460f450e8ad94ea818b4529 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:12:29 +0200 Subject: [PATCH] Fix IEC code for non interrupt usage --- include/c64/iecbus.c | 176 ++++++++++++++++------- include/c64/iecbus.h | 3 +- oscar64/InterCode.cpp | 171 +++++++++++++++++++++- oscar64/InterCode.h | 4 + oscar64/NativeCodeGenerator.cpp | 243 ++++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 9 +- 7 files changed, 539 insertions(+), 68 deletions(-) diff --git a/include/c64/iecbus.c b/include/c64/iecbus.c index cb9420e..bfd18de 100644 --- a/include/c64/iecbus.c +++ b/include/c64/iecbus.c @@ -2,7 +2,8 @@ #include #include -IEC_STATUS iec_status; +IEC_STATUS iec_status; +char iec_queue; #define CIA2B_ATNOUT 0x08 #define CIA2B_CLKOUT 0x10 @@ -25,45 +26,55 @@ static void delay(char n) } } -static inline void data_low(void) +static inline void data_true(void) { cia2.pra &= ~CIA2B_DATAOUT; } -static inline void data_high(void) +static inline void data_false(void) { cia2.pra |= CIA2B_DATAOUT; } -static inline void clock_low(void) +static inline void clock_true(void) { cia2.pra &= ~CIA2B_CLKOUT; } -static inline void cdata_low(void) +static inline void cdata_true(void) { cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT); } -static inline void clock_high(void) +static inline void clock_false(void) { cia2.pra |= CIA2B_CLKOUT; } -static inline void atn_low(void) +static inline void atn_true(void) { cia2.pra &= ~CIA2B_ATNOUT; } -static inline void atn_high(void) +static inline void atn_false(void) { cia2.pra |= CIA2B_ATNOUT; } +static inline bool data_in(void) +{ + return (cia2.pra & CIA2B_DATAIN) != 0; +} + +static inline bool clock_in(void) +{ + return (cia2.pra & CIA2B_CLKIN) != 0; +} + static bool data_check(void) { char cnt = 100; - while (cnt > 0 && (cia2.pra & CIA2B_DATAIN)) + while (cnt > 0 && data_in()) cnt--; if (cnt) @@ -75,68 +86,106 @@ static bool data_check(void) } } -bool iec_eoi(void) +static bool iec_eoib(void) { - cdata_low(); + clock_true(); + + while (!data_in()); - while (!(cia2.pra & CIA2B_DATAIN)) - ; delay(40); return data_check(); } +static bool iec_writeb(char b) +{ + clock_true(); + + while (!data_in()); + + for(char i=0; i<8; i++) + { + delay(8); + clock_false(); + delay(8); + if (b & 1) + data_true(); + else + data_false(); + clock_true(); + b >>= 1; + } + delay(8); + clock_false(); + data_true(); + + return data_check(); +} + bool iec_write(char b) { - cdata_low(); - - while (!(cia2.pra & CIA2B_DATAIN)) - ; - - clock_high(); - - for(char i=0; i<8; i++) + if (iec_status == IEC_QUEUED) { - if (b & 1) - data_low(); - else - data_high(); - delay(5); - clock_low(); - b >>= 1; - delay(5); - clock_high(); - data_low(); + __asm + { + php + sei + } + + iec_status = IEC_OK; + iec_writeb(iec_queue); + + __asm + { + plp + } + } + if (iec_status < IEC_ERROR) + { + iec_queue = b; + iec_status = IEC_QUEUED; + return true; } - return data_check(); + return false; } char iec_read(void) { - while (!(cia2.pra & CIA2B_CLKIN)) - ; + while (!clock_in()); - data_low(); + __asm + { + php + sei + } + + data_true(); char cnt = 100; - while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) + while (cnt > 0 && clock_in()) cnt--; if (cnt == 0) { iec_status = IEC_EOF; - data_high(); + data_false(); delay(4); - data_low(); + data_true(); cnt = 200; - while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) + while (cnt > 0 && clock_in()) cnt--; if (cnt == 0) { iec_status = IEC_TIMEOUT; + + __asm + { + plp + } + return 0; } } @@ -155,25 +204,32 @@ char iec_read(void) ; } - data_high(); + data_false(); + __asm + { + plp + } + return b; } void iec_atn(char dev, char sec) -{ - cdata_low(); - atn_high(); - clock_high(); +{ + clock_true(); + data_true(); + atn_false(); + clock_false(); delay(200); - iec_write(dev); - if (sec != 0xff) - iec_write(sec); + while (data_in()); - data_high(); - atn_low(); + iec_writeb(dev); + if (sec != 0xff) + iec_writeb(sec); + + atn_true(); } @@ -182,7 +238,7 @@ void iec_talk(char dev, char sec) iec_status = IEC_OK; iec_atn(dev | 0x40, sec | 0x60); - clock_low(); + clock_true(); delay(10); } @@ -201,7 +257,25 @@ void iec_listen(char dev, char sec) void iec_unlisten(void) { + __asm + { + php + sei + } + + if (iec_status == IEC_QUEUED) + { + iec_eoib(); + iec_writeb(iec_queue); + } + iec_atn(0x3f, 0xff); + clock_true(); + + __asm + { + plp + } } void iec_open(char dev, char sec, const char * fname) @@ -213,8 +287,6 @@ void iec_open(char dev, char sec, const char * fname) char i = 0; while (fname[i]) { - if (!fname[i + 1]) - iec_eoi(); iec_write(fname[i]); i++; } diff --git a/include/c64/iecbus.h b/include/c64/iecbus.h index 814b96d..39fc668 100644 --- a/include/c64/iecbus.h +++ b/include/c64/iecbus.h @@ -5,6 +5,7 @@ enum IEC_STATUS { IEC_OK = 0x00, IEC_EOF = 0x01, + IEC_QUEUED = 0x02, IEC_ERROR = 0x80, IEC_TIMEOUT, @@ -13,8 +14,6 @@ enum IEC_STATUS extern IEC_STATUS iec_status; -bool iec_eoi(void); - bool iec_write(char b); char iec_read(void); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 21958f7..64ee598 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -14136,6 +14136,157 @@ bool SameExitCondition(InterCodeBasicBlock* b1, InterCodeBasicBlock* b2) return false; } +InterCodeBasicBlock* InterCodeBasicBlock::CheckIsConstBranch(const GrowingInstructionPtrArray& cins) +{ + if (!mFalseJump || mInstructions.Size() < 1 || mInstructions[mInstructions.Size() - 1]->mCode != IC_BRANCH) + return nullptr; + + GrowingInstructionPtrArray tins(cins); + for (int i = 0; i < mInstructions.Size() - 1; i++) + { + InterInstruction* ins(mInstructions[i]); + InterInstruction* nins = nullptr; + if (IsObservable(ins->mCode)) + return nullptr; + if (ins->mDst.mTemp >= 0) + { + if (ins->mCode == IC_CONSTANT) + nins = ins; + else if (ins->mCode == IC_LOAD && !ins->mVolatile) + { + int k = 0; + while (k < tins.Size() && !(tins[k]->mCode == IC_STORE && SameMemAndSize(ins->mSrc[0], tins[k]->mSrc[1]))) + k++; + if (k < tins.Size()) + { + nins = new InterInstruction(ins->mLocation, IC_CONSTANT); + nins->mDst = ins->mDst; + nins->mConst = tins[k]->mSrc[0]; + } + } + + if (ins->mDst.mTemp >= 0) + { + int k = 0; + while (k < tins.Size() && tins[k]->mDst.mTemp != ins->mDst.mTemp) + k++; + if (k < tins.Size()) + tins.Remove(k); + } + + if (nins) + tins.Push(nins); + } + } + + InterInstruction* bins = mInstructions[mInstructions.Size() - 1]; + + int k = 0; + while (k < tins.Size() && tins[k]->mDst.mTemp != bins->mSrc[0].mTemp) + k++; + + if (k < tins.Size() && tins[k]->mCode == IC_CONSTANT) + { + InterCodeBasicBlock* tblock = tins[k]->mConst.mIntConst ? mTrueJump : mFalseJump; + + InterCodeBasicBlock* xblock = this->Clone(); + InterInstruction* bins = xblock->mInstructions.Pop(); + InterInstruction* jins = new InterInstruction(bins->mLocation, IC_JUMP); + xblock->mInstructions.Push(jins); + xblock->mTrueJump = tblock; + tblock->mEntryBlocks.Push(xblock); + tblock->mNumEntries++; + return xblock; + } + + return nullptr; +} + +bool InterCodeBasicBlock::ShortcutConstBranches(const GrowingInstructionPtrArray& cins) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + GrowingInstructionPtrArray tins(cins); + if (mNumEntries > 1) + tins.SetSize(0); + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins(mInstructions[i]); + InterInstruction* nins = nullptr; + + if (ins->mCode == IC_CONSTANT) + nins = ins; + else + { + if (IsObservable(ins->mCode)) + { + int k = 0; + while (k < tins.Size()) + { + if (tins[k]->mCode == IC_STORE && DestroyingMem(tins[k], ins)) + tins.Remove(k); + else + k++; + } + } + + if (ins->mCode == IC_STORE && !ins->mVolatile && ins->mSrc[0].mTemp < 0) + nins = ins; + } + + if (ins->mDst.mTemp >= 0) + { + int k = 0; + while (k < tins.Size() && tins[k]->mDst.mTemp != ins->mDst.mTemp) + k++; + if (k < tins.Size()) + tins.Remove(k); + } + + if (nins) + tins.Push(nins); + } + + + if (mTrueJump) + { + InterCodeBasicBlock* tblock = mTrueJump->CheckIsConstBranch(tins); + if (tblock) + { + mTrueJump->mEntryBlocks.RemoveAll(this); + mTrueJump->mNumEntries--; + tblock->mEntryBlocks.Push(this); + tblock->mNumEntries++; + mTrueJump = tblock; + } + if (mTrueJump->ShortcutConstBranches(tins)) + changed = true; + } + if (mFalseJump) + { + InterCodeBasicBlock* tblock = mFalseJump->CheckIsConstBranch(tins); + if (tblock) + { + mFalseJump->mEntryBlocks.RemoveAll(this); + mFalseJump->mNumEntries--; + tblock->mEntryBlocks.Push(this); + tblock->mNumEntries++; + mFalseJump = tblock; + } + if (mFalseJump->ShortcutConstBranches(tins)) + changed = true; + } + } + + return changed; +} + + bool InterCodeBasicBlock::MergeLoopTails(void) { bool modified = false; @@ -20143,6 +20294,22 @@ void InterCodeProcedure::CheckUsedDefinedTemps(void) #endif } +void InterCodeProcedure::ShortcutConstBranches(void) +{ + GrowingInstructionPtrArray cins(nullptr); + + BuildDataFlowSets(); + TempForwarding(); + RemoveUnusedInstructions(); + + do { + ResetVisited(); + } while (mEntryBlock->ShortcutConstBranches(cins)); + + Disassemble("ShortcutConstBranches"); +} + + void InterCodeProcedure::MoveConditionsOutOfLoop(void) { BuildTraces(false); @@ -20831,7 +20998,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "read_decompress"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -21589,6 +21756,8 @@ void InterCodeProcedure::Close(void) TempForwarding(); RemoveUnusedInstructions(); + ShortcutConstBranches(); + DisassembleDebug("Global Constant Prop 1"); BuildDataFlowSets(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index f27077a..54fca35 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -604,6 +604,9 @@ public: bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); bool MergeLoopTails(void); + InterCodeBasicBlock* CheckIsConstBranch(const GrowingInstructionPtrArray& cins); + bool ShortcutConstBranches(const GrowingInstructionPtrArray& cins); + InterCodeBasicBlock* BuildLoopPrefix(void); void BuildLoopSuffix(void); @@ -744,6 +747,7 @@ protected: void WarnInvalidValueRanges(void); void PropagateMemoryAliasingInfo(void); void MoveConditionsOutOfLoop(void); + void ShortcutConstBranches(void); void CollapseDispatch(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 51ec116..cf168ca 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -4293,7 +4293,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT mMode = ASMIM_IMPLIED; changed = true; } - else if (data.mRegs[CPU_REG_A].mMode == NRDM_UNKNOWN) + else if (final || data.mRegs[CPU_REG_A].mMode == NRDM_UNKNOWN) { data.ResetAbsolute(mLinkerObject, mAddress); data.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE; @@ -16678,6 +16678,47 @@ bool NativeCodeBasicBlock::GlobalSwapXY(void) return changed; } +bool NativeCodeBasicBlock::AlternateXXUsage(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i + 3 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_X && + mIns[i + 2].mType == ASMIT_LDX && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ABSOLUTE_X && + !(mIns[i + 3].mLive & LIVE_CPU_REG_Y)) + { + mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; + changed = true; + } + else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y && + mIns[i + 2].mType == ASMIT_LDY && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ABSOLUTE_Y && + !(mIns[i + 3].mLive & LIVE_CPU_REG_X)) + { + mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= LIVE_CPU_REG_X; + mIns[i + 1].mMode = ASMIM_ABSOLUTE_X; + changed = true; + } + } + + if (mTrueJump && mTrueJump->AlternateXXUsage()) + changed = true; + if (mFalseJump && mFalseJump->AlternateXXUsage()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::UntangleXYUsage(void) { bool changed = false; @@ -20001,6 +20042,32 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } + if (mIns.Size() >= 3 && mFalseJump && (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE)) + { + int sz = mIns.Size(); + if ((mIns[sz - 3].mType == ASMIT_INC || mIns[sz - 3].mType == ASMIT_DEC) && + mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].SameEffectiveAddress(mIns[sz - 3]) && + mIns[sz - 1].mType == ASMIT_ORA && + !(mIns[sz - 1].mLive & LIVE_CPU_REG_A)) + { + mIns[sz - 3].mLive |= LIVE_CPU_REG_Z; + + NativeCodeBasicBlock* tblock = this->SplitAt(sz - 2); + + if (tblock->mBranch == ASMIT_BEQ) + mTrueJump = tblock->mFalseJump; + else + mTrueJump = tblock->mTrueJump; + + mBranch = ASMIT_BNE; + mFalseJump = tblock; + mTrueJump->mNumEntries++; + mTrueJump->mEntryBlocks.Push(this); + changed = true; + } + + } + if (mIns.Size() >= 8 && mFalseJump && (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ)) { int sz = mIns.Size(); @@ -20235,6 +20302,33 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } #endif + // Simple diamond split + if (mFalseJump && !mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1) + { + if (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS) + { + if (mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1) + { + if (mTrueJump->mIns[0].mType == ASMIT_AND && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && + mFalseJump->mIns[0].mType == ASMIT_ORA && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE && + (mTrueJump->mIns[0].mAddress ^ mFalseJump->mIns[0].mAddress) == 0xff) + { + mIns.Push(mTrueJump->mIns[0]); + mTrueJump->mIns.SetSize(0); + changed = true; + } + else if (mTrueJump->mIns[0].mType == ASMIT_ORA && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && + mFalseJump->mIns[0].mType == ASMIT_AND && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE && + (mTrueJump->mIns[0].mAddress ^ mFalseJump->mIns[0].mAddress) == 0xff) + { + mIns.Push(mTrueJump->mIns[0]); + mTrueJump->mIns.SetSize(0); + changed = true; + } + } + } + } + if (mFalseJump && mTrueJump->mTrueJump == mFalseJump && !mTrueJump->mFalseJump && mTrueJump->mNumEntries == 1) { int sz = mIns.Size(); @@ -34760,6 +34854,58 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc } } + si = 0, ei = mIns.Size() - 1; + while (si < mIns.Size() && !mIns[si].ReferencesXReg()) + si++; + while (ei > si && !(mIns[ei].ChangesXReg() || mIns[ei].mType == ASMIT_STX)) + ei--; + + if (si < ei && mIns[si].mType == ASMIT_LDX && mIns[ei].mType == ASMIT_STX && mIns[si].mMode == ASMIM_ZERO_PAGE && mIns[ei].mMode == ASMIM_ZERO_PAGE && mIns[si].mAddress == mIns[ei].mAddress) + { + int i = 0; + while (i < si && !mIns[i].ChangesZeroPage(mIns[si].mAddress)) + i++; + + if (i == si) + { + i = ei + 1; + while (i < mIns.Size() && !mIns[i].ChangesZeroPage(mIns[si].mAddress)) + i++; + + if (i == mIns.Size()) + { + if (!prevBlock) + return OptimizeSimpleLoopInvariant(proc, full); + + i = 0; + while (i < si) + { + mIns[i].mLive |= LIVE_CPU_REG_X; + i++; + } + + i = ei; + while (i < mIns.Size()) + { + mIns[i].mLive |= LIVE_CPU_REG_X; + i++; + } + + prevBlock->mIns.Push(mIns[si]); + mIns.Remove(si); + + mEntryRequiredRegs += CPU_REG_X; + mExitRequiredRegs += CPU_REG_X; + + CheckLive(); + + return true; + } + } + } + + + si = 0; ei = mIns.Size() - 1; while (si < mIns.Size() && !mIns[si].ReferencesXReg()) @@ -43065,6 +43211,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 2].mMode = ASMIM_ABSOLUTE_X; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_TAX && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_X && + mIns[i + 2].mType == ASMIT_TAX && !(mIns[i + 2].mLive & LIVE_CPU_REG_Y)) + { + mIns[i + 0].mType = ASMIT_TAY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns[i + 1].mType = ASMIT_LDX; mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; mIns[i + 1].mLive |= LIVE_CPU_REG_X; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_TAY && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y && + mIns[i + 2].mType == ASMIT_TAY && !(mIns[i + 2].mLive & LIVE_CPU_REG_X)) + { + mIns[i + 0].mType = ASMIT_TAX; mIns[i + 0].mLive |= LIVE_CPU_REG_X; + mIns[i + 1].mType = ASMIT_LDY; mIns[i + 1].mMode = ASMIM_ABSOLUTE_X; mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( (mIns[i + 0].mType == ASMIT_INX || mIns[i + 0].mType == ASMIT_DEX) && @@ -44727,6 +44894,34 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_STY && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_LDA && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].SameEffectiveAddress(mIns[i + 0])) + { + mIns[i + 3].CopyMode(mIns[i + 2]); + mIns[i + 2].mType = ASMIT_TYA; + mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_STX && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_LDA && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].SameEffectiveAddress(mIns[i + 0])) + { + mIns[i + 3].CopyMode(mIns[i + 2]); + mIns[i + 2].mType = ASMIT_TXA; + mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 0].mLive |= LIVE_CPU_REG_X; + mIns[i + 1].mLive |= LIVE_CPU_REG_X; + progress = true; } #endif @@ -47951,12 +48146,23 @@ void NativeCodeBasicBlock::ShortcutTailRecursion() if (!mVisited) { mVisited = true; - if (!mFalseJump && mTrueJump && mTrueJump->mIns.Size() == 1 && mTrueJump->mIns[0].mType == ASMIT_RTS && mIns.Size() > 0 && mIns.Last().IsSimpleJSR()) + if (!mFalseJump && mTrueJump && mTrueJump->mIns.Size() == 1 && mTrueJump->mIns[0].mType == ASMIT_RTS) { - this->mCode[this->mCode.Size() - 3] = 0x4c; - mTrueJump->mNumEntries--; - mTrueJump = nullptr; - ShortcutJump(this->mCode.Size() - 3); + if (mIns.Size() > 0 && mIns.Last().IsSimpleJSR()) + { + this->mCode[this->mCode.Size() - 3] = 0x4c; + mTrueJump->mNumEntries--; + mTrueJump = nullptr; + ShortcutJump(this->mCode.Size() - 3); + } +#if 0 + else + { + this->mCode.Push(0x60); + mTrueJump->mNumEntries--; + mTrueJump = nullptr; + } +#endif } else if (!mFalseJump && !mTrueJump) { @@ -48293,7 +48499,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mInterProc = proc; mInterProc->mLinkerObject->mNativeProc = this; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "read_decompress"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "flossiec_read_lzo"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -48829,7 +49035,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) void NativeCodeProcedure::Assemble(void) { - CheckFunc = !strcmp(mInterProc->mIdent->mString, "longor"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "data_check"); if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) { @@ -49362,7 +49568,7 @@ void NativeCodeProcedure::Optimize(void) CheckBlocks(); #if 1 - if (step == 3 || step == 4) + if (step == 3 || step == 4 || (step == 15 && cnt > 0)) { #if 1 ResetVisited(); @@ -49874,7 +50080,22 @@ void NativeCodeProcedure::Optimize(void) } #endif - if (step == 15) +#if 1 + if (step == 15 && cnt == 0) + { + ResetVisited(); + mEntryBlock->RemoveUnusedResultInstructions(); + + BuildDataFlowSets(); + + ResetVisited(); + if (mEntryBlock->AlternateXXUsage()) + changed = true; + } +#endif + + + if (step == 16) { if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_INLINE) { @@ -49903,7 +50124,7 @@ void NativeCodeProcedure::Optimize(void) } #if 1 - if (!changed && step < 15) + if (!changed && step < 16) { ResetIndexFlipped(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index fb4f239..f07b4da 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -673,6 +673,7 @@ public: bool GlobalSwapXY(void); bool LocalSwapXY(void); bool UntangleXYUsage(void); + bool AlternateXXUsage(void); bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex); bool PropagateCommonSubExpression(void); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 991065e..f179a91 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3307,7 +3307,7 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) { Declaration* adec = new Declaration(fdec->mLocation, DT_ARGUMENT); - if (fdec->mBase->mType == DT_TYPE_STRUCT) + if (fdec->mBase && fdec->mBase->mType == DT_TYPE_STRUCT) adec->mVarIndex = 2; else adec->mVarIndex = 0; @@ -5103,7 +5103,10 @@ Expression* Parser::ParseLambdaExpression(void) cdec->mParams = mdec; } else + { mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method"); + mdec->mBase = TheVoidTypeDeclaration; + } mdec->mOffset = cdec->mSize; mdec->mSize = mdec->mBase->mSize; @@ -8651,7 +8654,9 @@ Expression* Parser::ParseFunction(Declaration * dec) } } - if (dec->mBase->mType == DT_TYPE_AUTO) + if (!dec->mBase) + dec->mBase = TheVoidTypeDeclaration; + else if (dec->mBase->mType == DT_TYPE_AUTO) dec->mBase->mType = DT_TYPE_VOID; mScope->End(mScanner->mLocation);