Improve register allocator
This commit is contained in:
parent
931f9e71b9
commit
5d51ea13c5
12
README.md
12
README.md
|
@ -231,6 +231,18 @@ The compiler uses basic zero page space for temporaries, local variables and fun
|
|||
|
||||
__zeropage int a;
|
||||
|
||||
### Prevent inlining
|
||||
|
||||
With compiler option O2 and greater the compiler will try to inline small functions. This may not always be desirable, so the __noinline qualifier can be added to a function to prevent this.
|
||||
|
||||
__noinline byte EzRead(char bank, const char * p)
|
||||
{
|
||||
eflash.bank = bank;
|
||||
byte b = *p;
|
||||
eflash.bank = CodeBank;
|
||||
return b;
|
||||
}
|
||||
|
||||
### Pre-Processor control
|
||||
|
||||
The pre processor has additional commands to control the scanner and allow for dynamic code generation including loops.
|
||||
|
|
|
@ -72,6 +72,7 @@ static const uint64 DTF_EXPORT = (1ULL << 19);
|
|||
static const uint64 DTF_HWINTERRUPT = (1ULL << 20);
|
||||
static const uint64 DTF_STACKCALL = (1ULL << 21);
|
||||
static const uint64 DTF_ZEROPAGE = (1ULL << 22);
|
||||
static const uint64 DTF_PREVENT_INLINE = (1ULL << 23);
|
||||
|
||||
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32);
|
||||
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
|
||||
|
|
|
@ -62,7 +62,14 @@ void GlobalAnalyzer::AutoInline(void)
|
|||
for (int i = 0; i < mFunctions.Size(); i++)
|
||||
{
|
||||
Declaration* f = mFunctions[i];
|
||||
if (!(f->mFlags & DTF_INLINE) && !(f->mBase->mFlags & DTF_VARIADIC) && !(f->mFlags & DTF_FUNC_VARIABLE) && !((f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_REQUEST_INLINE)) && !(f->mFlags & DTF_INTRINSIC) && !(f->mFlags & DTF_FUNC_RECURSIVE) && f->mLocalSize < 100)
|
||||
if (!(f->mFlags & DTF_INLINE) &&
|
||||
!(f->mFlags & DTF_EXPORT) &&
|
||||
!(f->mFlags & DTF_PREVENT_INLINE) &&
|
||||
!(f->mBase->mFlags & DTF_VARIADIC) &&
|
||||
!(f->mFlags & DTF_FUNC_VARIABLE) &&
|
||||
!((f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_REQUEST_INLINE)) &&
|
||||
!(f->mFlags & DTF_INTRINSIC) &&
|
||||
!(f->mFlags & DTF_FUNC_RECURSIVE) && f->mLocalSize < 100)
|
||||
{
|
||||
int nparams = 0;
|
||||
Declaration* dec = f->mBase->mParams;
|
||||
|
|
|
@ -2419,9 +2419,15 @@ bool InterOperand::IsEqual(const InterOperand& op) const
|
|||
if (mMemory != op.mMemory)
|
||||
return false;
|
||||
|
||||
if (mIntConst != op.mIntConst || mFloatConst != op.mFloatConst || mVarIndex != op.mVarIndex || mLinkerObject != op.mLinkerObject)
|
||||
if (mIntConst != op.mIntConst || mFloatConst != op.mFloatConst)
|
||||
return false;
|
||||
|
||||
if (mMemory != IM_NONE && mMemory != IM_INDIRECT)
|
||||
{
|
||||
if (mVarIndex != op.mVarIndex || mLinkerObject != op.mLinkerObject)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5740,10 +5746,13 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
|
|||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_EXT8TO16U:
|
||||
case IA_EXT8TO16S:
|
||||
if (ins->mSrc[0].mTemp >= 0 && (vr.mMaxValue != 255 || vr.mMinValue != 0))
|
||||
mReverseValueRange[ins->mSrc[0].mTemp].Limit(vr);
|
||||
break;
|
||||
case IA_EXT8TO16S:
|
||||
if (ins->mSrc[0].mTemp >= 0 && (vr.mMaxValue != 127 || vr.mMinValue != -128))
|
||||
mReverseValueRange[ins->mSrc[0].mTemp].Limit(vr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IC_BINARY_OPERATOR:
|
||||
|
@ -13005,35 +13014,60 @@ void InterCodeProcedure::MapCallerSavedTemps(void)
|
|||
|
||||
assert(freeCallerSavedTemps <= mCallerSavedTemps);
|
||||
|
||||
mTempOffset.SetSize(0);
|
||||
mTempSizes.SetSize(0);
|
||||
mTempOffset.SetSize(mTemporaries.Size(), true);
|
||||
mTempSizes.SetSize(mTemporaries.Size(), true);
|
||||
|
||||
for (int i = 0; i < mTemporaries.Size(); i++)
|
||||
{
|
||||
int size = InterTypeSize[mTemporaries[i]];
|
||||
if (!callerSaved[i])
|
||||
{
|
||||
int size = InterTypeSize[mTemporaries[i]];
|
||||
|
||||
if (freeTemps + size <= freeCallerSavedTemps && !callerSaved[i])
|
||||
{
|
||||
mTempOffset.Push(freeTemps);
|
||||
mTempSizes.Push(size);
|
||||
freeTemps += size;
|
||||
}
|
||||
else if (callerSavedTemps + size <= maxCallerSavedTemps)
|
||||
{
|
||||
mTempOffset.Push(callerSavedTemps);
|
||||
mTempSizes.Push(size);
|
||||
callerSavedTemps += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTempOffset.Push(calleeSavedTemps);
|
||||
mTempSizes.Push(size);
|
||||
calleeSavedTemps += size;
|
||||
if (freeTemps + size <= freeCallerSavedTemps)
|
||||
{
|
||||
mTempOffset[i] = freeTemps;
|
||||
mTempSizes[i] = size;
|
||||
freeTemps += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (freeTemps > callerSavedTemps)
|
||||
// callerSavedTemps = freeTemps;
|
||||
|
||||
for (int i = 0; i < mTemporaries.Size(); i++)
|
||||
{
|
||||
if (!mTempSizes[i])
|
||||
{
|
||||
int size = InterTypeSize[mTemporaries[i]];
|
||||
|
||||
if (callerSavedTemps + size <= maxCallerSavedTemps)
|
||||
{
|
||||
mTempOffset[i] = callerSavedTemps;
|
||||
mTempSizes[i] = size;
|
||||
callerSavedTemps += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTempOffset[i] = calleeSavedTemps;
|
||||
mTempSizes[i] = size;
|
||||
calleeSavedTemps += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mTempSize = calleeSavedTemps;
|
||||
mCallerSavedTemps = callerSavedTemps;
|
||||
|
||||
#if 0
|
||||
printf("Map %s, %d, %d, %d, %d\n", mIdent->mString, freeTemps, callerSavedTemps, calleeSavedTemps, freeCallerSavedTemps);
|
||||
for (int i = 0; i < mTempOffset.Size(); i++)
|
||||
printf("T%02d : %d, %d\n", i, mTempOffset[i], mTempSizes[i]);
|
||||
#endif
|
||||
|
||||
if (mSaveTempsLinkerObject && mTempSize > 16)
|
||||
mSaveTempsLinkerObject->AddSpace(mTempSize - 16);
|
||||
|
||||
// printf("Map %s, %d, %d, %d, %d\n", mIdent->mString, freeTemps, callerSavedTemps, calleeSavedTemps, freeCallerSavedTemps);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,9 +62,12 @@ void LinkerObject::AddData(const uint8* data, int size)
|
|||
|
||||
uint8* LinkerObject::AddSpace(int size)
|
||||
{
|
||||
mSize = size;
|
||||
mData = new uint8[size];
|
||||
memset(mData, 0, size);
|
||||
if (mSize != size)
|
||||
{
|
||||
mSize = size;
|
||||
mData = new uint8[size];
|
||||
memset(mData, 0, size);
|
||||
}
|
||||
return mData;
|
||||
}
|
||||
|
||||
|
|
|
@ -16294,6 +16294,228 @@ bool NativeCodeBasicBlock::Check16BitSum(int at, NativeRegisterSum16Info& info)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair)
|
||||
{
|
||||
if (at == 0 && mVisited)
|
||||
return false;
|
||||
|
||||
if (!mPatched)
|
||||
{
|
||||
mPatched = true;
|
||||
|
||||
if (at == 0)
|
||||
{
|
||||
mPatched = true;
|
||||
|
||||
if (mNumEntries > 1)
|
||||
{
|
||||
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||
if (!mEntryBlocks[i]->IsDominatedBy(block))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (at < mIns.Size())
|
||||
{
|
||||
if (mIns[at].mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
if (mIns[at].mAddress == to)
|
||||
return false;
|
||||
if (pair && mIns[at].mAddress == to + 1)
|
||||
return false;
|
||||
}
|
||||
else if (mIns[at].mMode == ASMIM_INDIRECT_Y)
|
||||
{
|
||||
if (mIns[at].mAddress == to)
|
||||
return false;
|
||||
if (mIns[at].mAddress + 1 == to)
|
||||
return false;
|
||||
if (pair && mIns[at].mAddress == to + 1)
|
||||
return false;
|
||||
if (!pair && mIns[at].mAddress == from)
|
||||
return false;
|
||||
if (mIns[at].mAddress + 1 == from)
|
||||
return false;
|
||||
if (pair && mIns[at].mAddress == from + 1)
|
||||
return false;
|
||||
}
|
||||
else if (mIns[at].mType == ASMIT_JSR)
|
||||
{
|
||||
LinkerObject* lo = mIns[at].mLinkerObject;
|
||||
if (lo)
|
||||
{
|
||||
for (int i = 0; i < lo->mNumTemporaries; i++)
|
||||
{
|
||||
if (from >= lo->mTemporaries[i] && from < lo->mTemporaries[i] + lo->mTempSizes[i] ||
|
||||
to >= lo->mTemporaries[i] && to < lo->mTemporaries[i] + lo->mTempSizes[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIns[at].mFlags & NCIF_USE_ZP_32_X)
|
||||
{
|
||||
if (to >= mIns[at].mParam && to < mIns[at].mParam + 4 ||
|
||||
from >= mIns[at].mParam && from < mIns[at].mParam + 4)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
at++;
|
||||
}
|
||||
|
||||
if (mTrueJump && !mTrueJump->IsFinalZeroPageUse(block, 0, from, to, pair))
|
||||
return false;
|
||||
if (mFalseJump && !mFalseJump->IsFinalZeroPageUse(block, 0, from, to, pair))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc)
|
||||
{
|
||||
// return false;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
for (int i = 0; i < mIns.Size(); i++)
|
||||
{
|
||||
if (i + 1 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 0].mAddress >= BC_REG_FPARAMS && mIns[i + 0].mAddress < BC_REG_FPARAMS_END &&
|
||||
mIns[i + 1].mAddress >= BC_REG_TMP)
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (IsFinalZeroPageUse(this, i + 2, mIns[i + 1].mAddress, mIns[i + 0].mAddress, false))
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 2, mIns[i + 1].mAddress, mIns[i + 0].mAddress))
|
||||
changed = true;
|
||||
|
||||
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress + 1 &&
|
||||
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
|
||||
mIns[i + 0].mAddress >= BC_REG_FPARAMS && mIns[i + 0].mAddress < BC_REG_FPARAMS_END &&
|
||||
mIns[i + 1].mAddress >= BC_REG_TMP)
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (IsFinalZeroPageUse(this, i + 4, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true))
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 4, mIns[i + 1].mAddress, mIns[i + 0].mAddress))
|
||||
changed = true;
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 4, mIns[i + 3].mAddress, mIns[i + 2].mAddress))
|
||||
changed = true;
|
||||
|
||||
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (i + 5 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_ADC &&
|
||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 0].mAddress + 1 &&
|
||||
mIns[i + 4].mType == ASMIT_ADC && !mIns[i + 4].MayBeSameAddress(mIns[i + 2]) &&
|
||||
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
|
||||
mIns[i + 0].mAddress >= BC_REG_FPARAMS && mIns[i + 0].mAddress < BC_REG_FPARAMS_END &&
|
||||
mIns[i + 2].mAddress >= BC_REG_TMP)
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (IsFinalZeroPageUse(this, i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true))
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress))
|
||||
changed = true;
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 6, mIns[i + 5].mAddress, mIns[i + 3].mAddress))
|
||||
changed = true;
|
||||
|
||||
mIns[i + 2].mAddress = mIns[i + 0].mAddress;
|
||||
mIns[i + 5].mAddress = mIns[i + 3].mAddress;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (i + 4 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_ADC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress + 1 &&
|
||||
mIns[i + 3].mType == ASMIT_ADC && !mIns[i + 3].MayBeSameAddress(mIns[i + 1]) &&
|
||||
mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 1].mAddress + 1 &&
|
||||
mIns[i + 0].mAddress >= BC_REG_FPARAMS && mIns[i + 0].mAddress < BC_REG_FPARAMS_END &&
|
||||
mIns[i + 1].mAddress >= BC_REG_TMP)
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (IsFinalZeroPageUse(this, i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true))
|
||||
{
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress))
|
||||
changed = true;
|
||||
nproc->ResetPatched();
|
||||
if (ForwardReplaceZeroPage(i + 5, mIns[i + 4].mAddress, mIns[i + 2].mAddress))
|
||||
changed = true;
|
||||
|
||||
mIns[i + 1].mAddress = mIns[i + 0].mAddress;
|
||||
mIns[i + 4].mAddress = mIns[i + 2].mAddress;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->ReplaceFinalZeroPageUse(nproc))
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->ReplaceFinalZeroPageUse(nproc))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::ForwardReplaceZeroPage(int at, int from, int to)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mPatched)
|
||||
{
|
||||
mPatched = true;
|
||||
|
||||
for (int i = at; i < mIns.Size(); i++)
|
||||
{
|
||||
if (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_INDIRECT_Y)
|
||||
{
|
||||
if (mIns[i].mAddress == from)
|
||||
{
|
||||
mIns[i].mAddress = to;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->ForwardReplaceZeroPage(0, from, to))
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->ForwardReplaceZeroPage(0, from, to))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::Propagate16BitSum(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
@ -19631,7 +19853,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
|
|||
#endif
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) &&
|
||||
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_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
|
@ -19644,7 +19866,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
|
|||
}
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_SEC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) &&
|
||||
mIns[i + 2].mType == ASMIT_SBC && 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_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
|
@ -19655,6 +19877,67 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
|
|||
j += 3;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 0].mMode) &&
|
||||
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_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
{
|
||||
mIns[j + 0] = mIns[i + 0];
|
||||
mIns[j + 0].mType = ASMIT_LDX;
|
||||
mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress;
|
||||
j += 3;
|
||||
i += 4;
|
||||
}
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 0].mMode) &&
|
||||
mIns[i + 1].mType == ASMIT_SEC &&
|
||||
mIns[i + 2].mType == ASMIT_SBC && 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_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
{
|
||||
mIns[j + 0] = mIns[i + 0];
|
||||
mIns[j + 0].mType = ASMIT_LDX;
|
||||
mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress;
|
||||
j += 3;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 0].mMode) &&
|
||||
mIns[i + 1].mType == ASMIT_CLC &&
|
||||
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 2 &&
|
||||
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
{
|
||||
mIns[j + 0] = mIns[i + 0];
|
||||
mIns[j + 0].mType = ASMIT_LDX;
|
||||
mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 2].mType = ASMIT_INX; mIns[j + 2].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 3].mType = ASMIT_STX; mIns[j + 3].mMode = ASMIM_ZERO_PAGE; mIns[j + 3].mAddress = mIns[i + 3].mAddress;
|
||||
j += 4;
|
||||
i += 4;
|
||||
}
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 0].mMode) &&
|
||||
mIns[i + 1].mType == ASMIT_SEC &&
|
||||
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 2 &&
|
||||
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X)))
|
||||
{
|
||||
mIns[j + 0] = mIns[i + 0];
|
||||
mIns[j + 0].mType = ASMIT_LDX;
|
||||
mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 2].mType = ASMIT_DEX; mIns[j + 2].mMode = ASMIM_IMPLIED;
|
||||
mIns[j + 3].mType = ASMIT_STX; mIns[j + 3].mMode = ASMIM_ZERO_PAGE; mIns[j + 3].mAddress = mIns[i + 3].mAddress;
|
||||
j += 4;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
else if (i + 3 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
|
@ -19679,6 +19962,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
|
|||
j += 2;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
else if (i + 1 < mIns.Size() &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE_X &&
|
||||
mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
||||
|
@ -23321,7 +23605,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mIns[i + 1].mMode) &&
|
||||
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
|
||||
mIns[i + 3].mType == ASMIT_TAY && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
|
||||
{
|
||||
|
@ -23337,7 +23621,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_SEC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mIns[i + 1].mMode) &&
|
||||
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
|
||||
mIns[i + 3].mType == ASMIT_TAY && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
|
||||
{
|
||||
|
@ -23353,7 +23637,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) &&
|
||||
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
|
||||
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
|
||||
{
|
||||
|
@ -23369,7 +23653,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_SEC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) &&
|
||||
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
|
||||
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
|
||||
{
|
||||
|
@ -23659,6 +23943,17 @@ 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_SEC &&
|
||||
mIns[i + 1].mType == ASMIT_SBC &&
|
||||
mIns[i + 2].mType == ASMIT_SEC &&
|
||||
mIns[i + 3].mType == ASMIT_SBC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 1 && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
|
||||
{
|
||||
mIns[i + 0].mType = ASMIT_CLC;
|
||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||
progress = true;
|
||||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
|
@ -24824,6 +25119,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
CheckLive();
|
||||
}
|
||||
}
|
||||
else if (sz >= 2 &&
|
||||
mIns[sz - 2].ChangesAccuAndFlag() &&
|
||||
mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x80 && !mExitRequiredRegs[CPU_REG_Z] && !mExitRequiredRegs[CPU_REG_C])
|
||||
{
|
||||
if (mBranch == ASMIT_BCC)
|
||||
{
|
||||
mBranch = ASMIT_BPL;
|
||||
mIns[sz - 1].mType = ASMIT_NOP; mIns[sz - 1].mMode = ASMIM_IMPLIED;
|
||||
|
||||
CheckLive();
|
||||
}
|
||||
else if (mBranch == ASMIT_BCS)
|
||||
{
|
||||
mBranch = ASMIT_BMI;
|
||||
mIns[sz - 1].mType = ASMIT_NOP; mIns[sz - 1].mMode = ASMIM_IMPLIED;
|
||||
|
||||
CheckLive();
|
||||
}
|
||||
}
|
||||
|
||||
else if (sz >= 4 &&
|
||||
mIns[sz - 4].mType == ASMIT_EOR && mIns[sz - 4].mMode == ASMIM_IMMEDIATE && mIns[sz - 4].mAddress == 0x80 &&
|
||||
|
@ -25392,56 +25706,65 @@ void NativeCodeProcedure::CompressTemporaries(void)
|
|||
remap[i] = i;
|
||||
|
||||
int tpos = BC_REG_TMP + mInterProc->mFreeCallerSavedTemps;
|
||||
// BC_REG_TMP_SAVED;
|
||||
// if (mInterProc->mLeafProcedure)
|
||||
// tpos = BC_REG_TMP;
|
||||
int spos = BC_REG_TMP_SAVED;
|
||||
|
||||
for (int i = 0; i < mInterProc->mTempOffset.Size(); i++)
|
||||
// for (int tsize = 4; tsize > 0; tsize >>= 1)
|
||||
{
|
||||
bool tused = false;
|
||||
|
||||
int reg = BC_REG_TMP + mInterProc->mTempOffset[i];
|
||||
// if (mInterProc->mLeafProcedure || reg >= BC_REG_TMP_SAVED)
|
||||
if (reg >= BC_REG_TMP + mInterProc->mFreeCallerSavedTemps)
|
||||
for (int i = 0; i < mInterProc->mTempOffset.Size(); i++)
|
||||
{
|
||||
int size = mInterProc->mTempSizes[i];
|
||||
int usize = 0;
|
||||
bool tused = false;
|
||||
|
||||
for (int j = 0; j < size; j++)
|
||||
if (used[reg + j])
|
||||
usize = j + 1;
|
||||
|
||||
if (usize)
|
||||
int reg = BC_REG_TMP + mInterProc->mTempOffset[i];
|
||||
// if (mInterProc->mLeafProcedure || reg >= BC_REG_TMP_SAVED)
|
||||
if (reg >= BC_REG_TMP + mInterProc->mFreeCallerSavedTemps)
|
||||
{
|
||||
if (tpos < BC_REG_TMP_SAVED && tpos + usize > BC_REG_TMP + mInterProc->mCallerSavedTemps)
|
||||
tpos = BC_REG_TMP_SAVED;
|
||||
int size = mInterProc->mTempSizes[i];
|
||||
// if (size == tsize)
|
||||
{
|
||||
int usize = 0;
|
||||
|
||||
for (int j = 0; j < usize; j++)
|
||||
remap[reg + j] = tpos + j;
|
||||
for (int j = 0; j < size; j++)
|
||||
if (used[reg + j])
|
||||
usize = j + 1;
|
||||
|
||||
mInterProc->mTempOffset[i] = tpos - BC_REG_TMP;
|
||||
mInterProc->mTempSizes[i] = usize;
|
||||
tpos += usize;
|
||||
if (usize)
|
||||
{
|
||||
int pos = spos;
|
||||
if (tpos + usize <= BC_REG_TMP + mInterProc->mCallerSavedTemps)
|
||||
{
|
||||
pos = tpos;
|
||||
tpos += usize;
|
||||
}
|
||||
else
|
||||
spos += usize;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterProc->mTempOffset[i] = 0;
|
||||
mInterProc->mTempSizes[i] = 0;
|
||||
for (int j = 0; j < usize; j++)
|
||||
remap[reg + j] = pos + j;
|
||||
|
||||
mInterProc->mTempOffset[i] = pos - BC_REG_TMP;
|
||||
mInterProc->mTempSizes[i] = usize;
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterProc->mTempOffset[i] = 0;
|
||||
mInterProc->mTempSizes[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tpos < BC_REG_TMP_SAVED)
|
||||
{
|
||||
// printf("%s, %d -> %d\n", mInterProc->mIdent->mString, mInterProc->mCallerSavedTemps, tpos - BC_REG_TMP);
|
||||
mInterProc->mCallerSavedTemps = tpos - BC_REG_TMP;
|
||||
}
|
||||
mInterProc->mCallerSavedTemps = tpos - BC_REG_TMP;
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->RemapZeroPage(remap);
|
||||
|
||||
mInterProc->mTempSize = tpos - BC_REG_TMP;
|
||||
assert(mInterProc->mTempSize >= tpos - BC_REG_TMP);
|
||||
|
||||
if (spos > BC_REG_TMP_SAVED)
|
||||
mInterProc->mTempSize = spos - BC_REG_TMP;
|
||||
else
|
||||
mInterProc->mTempSize = tpos - BC_REG_TMP;
|
||||
|
||||
if (mNoFrame && !used[BC_REG_STACK] && mInterProc->mTempSize <= 16)
|
||||
mStackExpand = 0;
|
||||
|
@ -26021,6 +26344,13 @@ void NativeCodeProcedure::Optimize(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
if (step == 2)
|
||||
{
|
||||
ResetVisited();
|
||||
mEntryBlock->ReplaceFinalZeroPageUse(this);
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
do
|
||||
{
|
||||
|
|
|
@ -345,6 +345,10 @@ public:
|
|||
bool Check16BitSum(int at, NativeRegisterSum16Info& info);
|
||||
bool Propagate16BitSum(void);
|
||||
|
||||
bool IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair);
|
||||
bool ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc);
|
||||
bool ForwardReplaceZeroPage(int at, int from, int to);
|
||||
|
||||
NativeRegisterDataSet mEntryRegisterDataSet;
|
||||
|
||||
void BuildEntryDataSet(const NativeRegisterDataSet& set);
|
||||
|
|
|
@ -986,6 +986,11 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
|||
storageFlags |= DTF_ZEROPAGE;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else if (mScanner->mToken == TK_NOINLINE)
|
||||
{
|
||||
storageFlags |= DTF_PREVENT_INLINE;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else if (mScanner->mToken == TK_INLINE)
|
||||
{
|
||||
storageFlags |= DTF_REQUEST_INLINE;
|
||||
|
|
|
@ -56,6 +56,7 @@ const char* TokenNames[] =
|
|||
"__fastcall",
|
||||
"__export",
|
||||
"__zeropage",
|
||||
"__noinline",
|
||||
|
||||
"number",
|
||||
"char",
|
||||
|
@ -1341,6 +1342,8 @@ void Scanner::NextRawToken(void)
|
|||
mToken = TK_EXPORT;
|
||||
else if (!strcmp(tkident, "__zeropage"))
|
||||
mToken = TK_ZEROPAGE;
|
||||
else if (!strcmp(tkident, "__noinline"))
|
||||
mToken = TK_NOINLINE;
|
||||
else
|
||||
{
|
||||
mToken = TK_IDENT;
|
||||
|
|
|
@ -54,6 +54,7 @@ enum Token
|
|||
TK_FASTCALL,
|
||||
TK_EXPORT,
|
||||
TK_ZEROPAGE,
|
||||
TK_NOINLINE,
|
||||
|
||||
TK_NUMBER,
|
||||
TK_CHARACTER,
|
||||
|
|
|
@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
|
|||
|
||||
#else
|
||||
strcpy(strProductName, "oscar64");
|
||||
strcpy(strProductVersion, "1.7.141");
|
||||
strcpy(strProductVersion, "1.7.142");
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint32_t length = sizeof(basePath);
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,141,0
|
||||
PRODUCTVERSION 1,7,141,0
|
||||
FILEVERSION 1,7,142,0
|
||||
PRODUCTVERSION 1,7,142,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,12 +43,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "oscar64"
|
||||
VALUE "FileDescription", "oscar64 compiler"
|
||||
VALUE "FileVersion", "1.7.141.0"
|
||||
VALUE "FileVersion", "1.7.142.0"
|
||||
VALUE "InternalName", "oscar64.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||
VALUE "OriginalFilename", "oscar64.exe"
|
||||
VALUE "ProductName", "oscar64"
|
||||
VALUE "ProductVersion", "1.7.141.0"
|
||||
VALUE "ProductVersion", "1.7.142.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -4153,15 +4153,15 @@
|
|||
{
|
||||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{AAAF5F55-0261-47DA-B051-EF84642395A5}"
|
||||
"PackageCode" = "8:{A7501921-EE58-422B-AEE2-4491A2249AC0}"
|
||||
"ProductCode" = "8:{54C9EB87-4154-49FD-B146-2408492EDE3B}"
|
||||
"PackageCode" = "8:{A90AA9BF-452A-4C37-B592-CAF52893124A}"
|
||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||
"AspNetVersion" = "8:2.0.50727.0"
|
||||
"RestartWWWService" = "11:FALSE"
|
||||
"RemovePreviousVersions" = "11:TRUE"
|
||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||
"InstallAllUsers" = "11:FALSE"
|
||||
"ProductVersion" = "8:1.7.141"
|
||||
"ProductVersion" = "8:1.7.142"
|
||||
"Manufacturer" = "8:oscar64"
|
||||
"ARPHELPTELEPHONE" = "8:"
|
||||
"ARPHELPLINK" = "8:"
|
||||
|
|
Loading…
Reference in New Issue