Fix IEC code for non interrupt usage
This commit is contained in:
parent
42eea7f8f4
commit
5ccfab0342
|
@ -2,7 +2,8 @@
|
|||
#include <c64/cia.h>
|
||||
#include <c64/vic.h>
|
||||
|
||||
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++;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue