Fix IEC code for non interrupt usage

This commit is contained in:
drmortalwombat 2024-06-11 12:12:29 +02:00
parent 42eea7f8f4
commit 5ccfab0342
7 changed files with 539 additions and 68 deletions

View File

@ -3,6 +3,7 @@
#include <c64/vic.h> #include <c64/vic.h>
IEC_STATUS iec_status; IEC_STATUS iec_status;
char iec_queue;
#define CIA2B_ATNOUT 0x08 #define CIA2B_ATNOUT 0x08
#define CIA2B_CLKOUT 0x10 #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; cia2.pra &= ~CIA2B_DATAOUT;
} }
static inline void data_high(void) static inline void data_false(void)
{ {
cia2.pra |= CIA2B_DATAOUT; cia2.pra |= CIA2B_DATAOUT;
} }
static inline void clock_low(void) static inline void clock_true(void)
{ {
cia2.pra &= ~CIA2B_CLKOUT; cia2.pra &= ~CIA2B_CLKOUT;
} }
static inline void cdata_low(void) static inline void cdata_true(void)
{ {
cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT); cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT);
} }
static inline void clock_high(void) static inline void clock_false(void)
{ {
cia2.pra |= CIA2B_CLKOUT; cia2.pra |= CIA2B_CLKOUT;
} }
static inline void atn_low(void) static inline void atn_true(void)
{ {
cia2.pra &= ~CIA2B_ATNOUT; cia2.pra &= ~CIA2B_ATNOUT;
} }
static inline void atn_high(void) static inline void atn_false(void)
{ {
cia2.pra |= CIA2B_ATNOUT; 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) static bool data_check(void)
{ {
char cnt = 100; char cnt = 100;
while (cnt > 0 && (cia2.pra & CIA2B_DATAIN)) while (cnt > 0 && data_in())
cnt--; cnt--;
if (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); delay(40);
return data_check(); 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) bool iec_write(char b)
{ {
cdata_low(); if (iec_status == IEC_QUEUED)
while (!(cia2.pra & CIA2B_DATAIN))
;
clock_high();
for(char i=0; i<8; i++)
{ {
if (b & 1) __asm
data_low(); {
else php
data_high(); sei
delay(5);
clock_low();
b >>= 1;
delay(5);
clock_high();
data_low();
} }
return data_check(); 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 false;
} }
char iec_read(void) char iec_read(void)
{ {
while (!(cia2.pra & CIA2B_CLKIN)) while (!clock_in());
;
data_low(); __asm
{
php
sei
}
data_true();
char cnt = 100; char cnt = 100;
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) while (cnt > 0 && clock_in())
cnt--; cnt--;
if (cnt == 0) if (cnt == 0)
{ {
iec_status = IEC_EOF; iec_status = IEC_EOF;
data_high(); data_false();
delay(4); delay(4);
data_low(); data_true();
cnt = 200; cnt = 200;
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) while (cnt > 0 && clock_in())
cnt--; cnt--;
if (cnt == 0) if (cnt == 0)
{ {
iec_status = IEC_TIMEOUT; iec_status = IEC_TIMEOUT;
__asm
{
plp
}
return 0; return 0;
} }
} }
@ -155,25 +204,32 @@ char iec_read(void)
; ;
} }
data_high(); data_false();
__asm
{
plp
}
return b; return b;
} }
void iec_atn(char dev, char sec) void iec_atn(char dev, char sec)
{ {
cdata_low(); clock_true();
atn_high(); data_true();
clock_high(); atn_false();
clock_false();
delay(200); delay(200);
iec_write(dev); while (data_in());
if (sec != 0xff)
iec_write(sec);
data_high(); iec_writeb(dev);
atn_low(); if (sec != 0xff)
iec_writeb(sec);
atn_true();
} }
@ -182,7 +238,7 @@ void iec_talk(char dev, char sec)
iec_status = IEC_OK; iec_status = IEC_OK;
iec_atn(dev | 0x40, sec | 0x60); iec_atn(dev | 0x40, sec | 0x60);
clock_low(); clock_true();
delay(10); delay(10);
} }
@ -201,7 +257,25 @@ void iec_listen(char dev, char sec)
void iec_unlisten(void) void iec_unlisten(void)
{ {
__asm
{
php
sei
}
if (iec_status == IEC_QUEUED)
{
iec_eoib();
iec_writeb(iec_queue);
}
iec_atn(0x3f, 0xff); iec_atn(0x3f, 0xff);
clock_true();
__asm
{
plp
}
} }
void iec_open(char dev, char sec, const char * fname) 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; char i = 0;
while (fname[i]) while (fname[i])
{ {
if (!fname[i + 1])
iec_eoi();
iec_write(fname[i]); iec_write(fname[i]);
i++; i++;
} }

View File

@ -5,6 +5,7 @@ enum IEC_STATUS
{ {
IEC_OK = 0x00, IEC_OK = 0x00,
IEC_EOF = 0x01, IEC_EOF = 0x01,
IEC_QUEUED = 0x02,
IEC_ERROR = 0x80, IEC_ERROR = 0x80,
IEC_TIMEOUT, IEC_TIMEOUT,
@ -13,8 +14,6 @@ enum IEC_STATUS
extern IEC_STATUS iec_status; extern IEC_STATUS iec_status;
bool iec_eoi(void);
bool iec_write(char b); bool iec_write(char b);
char iec_read(void); char iec_read(void);

View File

@ -14136,6 +14136,157 @@ bool SameExitCondition(InterCodeBasicBlock* b1, InterCodeBasicBlock* b2)
return false; 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 InterCodeBasicBlock::MergeLoopTails(void)
{ {
bool modified = false; bool modified = false;
@ -20143,6 +20294,22 @@ void InterCodeProcedure::CheckUsedDefinedTemps(void)
#endif #endif
} }
void InterCodeProcedure::ShortcutConstBranches(void)
{
GrowingInstructionPtrArray cins(nullptr);
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
do {
ResetVisited();
} while (mEntryBlock->ShortcutConstBranches(cins));
Disassemble("ShortcutConstBranches");
}
void InterCodeProcedure::MoveConditionsOutOfLoop(void) void InterCodeProcedure::MoveConditionsOutOfLoop(void)
{ {
BuildTraces(false); BuildTraces(false);
@ -20831,7 +20998,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "main"); CheckFunc = !strcmp(mIdent->mString, "read_decompress");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -21589,6 +21756,8 @@ void InterCodeProcedure::Close(void)
TempForwarding(); TempForwarding();
RemoveUnusedInstructions(); RemoveUnusedInstructions();
ShortcutConstBranches();
DisassembleDebug("Global Constant Prop 1"); DisassembleDebug("Global Constant Prop 1");
BuildDataFlowSets(); BuildDataFlowSets();

View File

@ -604,6 +604,9 @@ public:
bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
bool MergeLoopTails(void); bool MergeLoopTails(void);
InterCodeBasicBlock* CheckIsConstBranch(const GrowingInstructionPtrArray& cins);
bool ShortcutConstBranches(const GrowingInstructionPtrArray& cins);
InterCodeBasicBlock* BuildLoopPrefix(void); InterCodeBasicBlock* BuildLoopPrefix(void);
void BuildLoopSuffix(void); void BuildLoopSuffix(void);
@ -744,6 +747,7 @@ protected:
void WarnInvalidValueRanges(void); void WarnInvalidValueRanges(void);
void PropagateMemoryAliasingInfo(void); void PropagateMemoryAliasingInfo(void);
void MoveConditionsOutOfLoop(void); void MoveConditionsOutOfLoop(void);
void ShortcutConstBranches(void);
void CollapseDispatch(void); void CollapseDispatch(void);

View File

@ -4293,7 +4293,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
mMode = ASMIM_IMPLIED; mMode = ASMIM_IMPLIED;
changed = true; 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.ResetAbsolute(mLinkerObject, mAddress);
data.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE; data.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE;
@ -16678,6 +16678,47 @@ bool NativeCodeBasicBlock::GlobalSwapXY(void)
return changed; 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 NativeCodeBasicBlock::UntangleXYUsage(void)
{ {
bool changed = false; 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)) if (mIns.Size() >= 8 && mFalseJump && (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ))
{ {
int sz = mIns.Size(); int sz = mIns.Size();
@ -20235,6 +20302,33 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
} }
#endif #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) if (mFalseJump && mTrueJump->mTrueJump == mFalseJump && !mTrueJump->mFalseJump && mTrueJump->mNumEntries == 1)
{ {
int sz = mIns.Size(); 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; si = 0;
ei = mIns.Size() - 1; ei = mIns.Size() - 1;
while (si < mIns.Size() && !mIns[si].ReferencesXReg()) 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; mIns[i + 2].mMode = ASMIM_ABSOLUTE_X;
progress = true; 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 ( else if (
(mIns[i + 0].mType == ASMIT_INX || mIns[i + 0].mType == ASMIT_DEX) && (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; 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; progress = true;
} }
#endif #endif
@ -47951,13 +48146,24 @@ void NativeCodeBasicBlock::ShortcutTailRecursion()
if (!mVisited) if (!mVisited)
{ {
mVisited = true; 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)
{
if (mIns.Size() > 0 && mIns.Last().IsSimpleJSR())
{ {
this->mCode[this->mCode.Size() - 3] = 0x4c; this->mCode[this->mCode.Size() - 3] = 0x4c;
mTrueJump->mNumEntries--; mTrueJump->mNumEntries--;
mTrueJump = nullptr; mTrueJump = nullptr;
ShortcutJump(this->mCode.Size() - 3); ShortcutJump(this->mCode.Size() - 3);
} }
#if 0
else
{
this->mCode.Push(0x60);
mTrueJump->mNumEntries--;
mTrueJump = nullptr;
}
#endif
}
else if (!mFalseJump && !mTrueJump) else if (!mFalseJump && !mTrueJump)
{ {
int ns = mIns.Size(); int ns = mIns.Size();
@ -48293,7 +48499,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc = proc; mInterProc = proc;
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "read_decompress"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "flossiec_read_lzo");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -48829,7 +49035,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
void NativeCodeProcedure::Assemble(void) void NativeCodeProcedure::Assemble(void)
{ {
CheckFunc = !strcmp(mInterProc->mIdent->mString, "longor"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "data_check");
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
{ {
@ -49362,7 +49568,7 @@ void NativeCodeProcedure::Optimize(void)
CheckBlocks(); CheckBlocks();
#if 1 #if 1
if (step == 3 || step == 4) if (step == 3 || step == 4 || (step == 15 && cnt > 0))
{ {
#if 1 #if 1
ResetVisited(); ResetVisited();
@ -49874,7 +50080,22 @@ void NativeCodeProcedure::Optimize(void)
} }
#endif #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) if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_INLINE)
{ {
@ -49903,7 +50124,7 @@ void NativeCodeProcedure::Optimize(void)
} }
#if 1 #if 1
if (!changed && step < 15) if (!changed && step < 16)
{ {
ResetIndexFlipped(); ResetIndexFlipped();

View File

@ -673,6 +673,7 @@ public:
bool GlobalSwapXY(void); bool GlobalSwapXY(void);
bool LocalSwapXY(void); bool LocalSwapXY(void);
bool UntangleXYUsage(void); bool UntangleXYUsage(void);
bool AlternateXXUsage(void);
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex); bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
bool PropagateCommonSubExpression(void); bool PropagateCommonSubExpression(void);

View File

@ -3307,7 +3307,7 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis)
{ {
Declaration* adec = new Declaration(fdec->mLocation, DT_ARGUMENT); 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; adec->mVarIndex = 2;
else else
adec->mVarIndex = 0; adec->mVarIndex = 0;
@ -5103,7 +5103,10 @@ Expression* Parser::ParseLambdaExpression(void)
cdec->mParams = mdec; cdec->mParams = mdec;
} }
else else
{
mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method"); mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method");
mdec->mBase = TheVoidTypeDeclaration;
}
mdec->mOffset = cdec->mSize; mdec->mOffset = cdec->mSize;
mdec->mSize = mdec->mBase->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; dec->mBase->mType = DT_TYPE_VOID;
mScope->End(mScanner->mLocation); mScope->End(mScanner->mLocation);