Value range annotation for intermediate code

This commit is contained in:
drmortalwombat 2021-12-22 07:46:06 +01:00
parent b9c477976a
commit 05a6c71698
5 changed files with 934 additions and 76 deletions

View File

@ -77,16 +77,17 @@ int main(void)
a[i] = i % 10;
al[i] = i % 10;
}
#if 0
assert(sum(a, 100) == 450);
copy(b, a, 100);
assert(sum(b, 100) == 450);
reverse(c, a, 100);
assert(sum(c, 100) == 450);
assert(sumb(a, 100) == 450);
#endif
copyb(b, a, 100);
assert(sumb(b, 100) == 450);
#if 0
reverseb(c, a, 100);
assert(sumb(c, 100) == 450);
@ -97,6 +98,6 @@ int main(void)
reversel(cl, al, 100);
assert(suml(cl, 100) == 450);
#endif
return 0;
}

View File

@ -19,6 +19,90 @@ static bool IsIntegerType(InterType type)
return type >= IT_INT8 && type <= IT_INT32;
}
IntegerValueRange::IntegerValueRange(void)
: mMinState(S_UNKNOWN), mMaxState(S_UNKNOWN)
{}
IntegerValueRange::~IntegerValueRange(void)
{}
bool IntegerValueRange::Same(const IntegerValueRange& range) const
{
if (mMinState == range.mMinState && mMaxState == range.mMaxState)
{
if ((mMinState == S_BOUND || mMinState == S_WEAK) && mMinValue != range.mMinValue)
return false;
if ((mMaxState == S_BOUND || mMaxState == S_WEAK) && mMaxValue != range.mMaxValue)
return false;
return true;
}
return false;
}
bool IntegerValueRange::Merge(const IntegerValueRange& range)
{
bool changed = false;
if (mMinState != S_UNBOUND)
{
if (range.mMinState == S_UNKNOWN)
{
if (mMinState == S_BOUND)
mMinState = S_WEAK;
}
else if (range.mMinState == S_UNBOUND)
{
mMinState = S_UNBOUND;
changed = true;
}
else if (mMinState == S_UNKNOWN)
{
mMinState = S_WEAK;
mMinValue = range.mMinValue;
changed = true;
}
else if (range.mMinValue < mMinValue)
{
if (range.mMinState == S_WEAK)
mMinState = S_WEAK;
mMinValue = range.mMinValue;
changed = true;
}
}
if (mMaxState != S_UNBOUND)
{
if (range.mMaxState == S_UNKNOWN)
{
if (mMaxState == S_BOUND)
mMaxState = S_WEAK;
}
else if (range.mMaxState == S_UNBOUND)
{
mMaxState = S_UNBOUND;
changed = true;
}
else if (mMaxState == S_UNKNOWN)
{
mMaxState = S_WEAK;
mMaxValue = range.mMaxValue;
changed = true;
}
else if (range.mMaxValue > mMaxValue)
{
if (range.mMaxState == S_WEAK)
mMaxState = S_WEAK;
mMaxValue = range.mMaxValue;
changed = true;
}
}
return changed;
}
ValueSet::ValueSet(void)
{
mSize = 32;
@ -1485,6 +1569,13 @@ InterOperand::InterOperand(void)
: mTemp(INVALID_TEMPORARY), mType(IT_NONE), mFinal(false), mIntConst(0), mFloatConst(0), mVarIndex(-1), mOperandSize(0), mLinkerObject(nullptr), mMemory(IM_NONE)
{}
bool InterOperand::IsUByte(void) const
{
return
mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= 0 &&
mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 256;
}
bool InterOperand::IsEqual(const InterOperand& op) const
{
if (mType != op.mType || mTemp != op.mTemp)
@ -2202,6 +2293,46 @@ void InterInstruction::SimpleLocalToTemp(int vindex, int temp)
}
}
void InterOperand::Disassemble(FILE* file)
{
static char typechars[] = "NBCILFP";
if (mTemp >= 0)
{
fprintf(file, "R%d(%c)", mTemp, typechars[mType]);
if (mRange.mMinState >= IntegerValueRange::S_WEAK || mRange.mMaxState >= IntegerValueRange::S_WEAK)
{
fprintf(file, "[");
if (mRange.mMinState == IntegerValueRange::S_WEAK)
fprintf(file, "~%d", int(mRange.mMinValue));
else if (mRange.mMinState == IntegerValueRange::S_BOUND)
fprintf(file, "%d", int(mRange.mMinValue));
else if (mRange.mMinState == IntegerValueRange::S_UNKNOWN)
fprintf(file, "?");
fprintf(file, "..");
if (mRange.mMaxState == IntegerValueRange::S_WEAK)
fprintf(file, "~%d", int(mRange.mMaxValue));
else if (mRange.mMaxState == IntegerValueRange::S_BOUND)
fprintf(file, "%d", int(mRange.mMaxValue));
else if (mRange.mMaxState == IntegerValueRange::S_UNKNOWN)
fprintf(file, "?");
fprintf(file, "]");
}
}
else if (mType == IT_POINTER)
{
fprintf(file, "V%d+%d", mVarIndex, int(mIntConst));
}
else if (IsIntegerType(mType) || mType == IT_BOOL)
{
fprintf(file, "C%c:%d", typechars[mType], int(mIntConst));
}
else if (mType == IT_FLOAT)
{
fprintf(file, "C%c:%f", typechars[mType], mFloatConst);
}
}
void InterInstruction::Disassemble(FILE* file)
{
if (this->mCode != IC_NONE)
@ -2285,18 +2416,11 @@ void InterInstruction::Disassemble(FILE* file)
static char typechars[] = "NBCILFP";
fprintf(file, "\t");
if (mDst.mTemp >= 0) fprintf(file, "R%d(%c)", mDst.mTemp, typechars[mDst.mType]);
if (mDst.mTemp >= 0)
mDst.Disassemble(file);
fprintf(file, "\t<-\t");
if (mSrc[2].mTemp >= 0) fprintf(file, "R%d(%c%c), ", mSrc[2].mTemp, typechars[mSrc[2].mType], mSrc[2].mFinal ? 'F' : '-');
if (mSrc[1].mTemp >= 0)
fprintf(file, "R%d(%c%c), ", mSrc[1].mTemp, typechars[mSrc[1].mType], mSrc[1].mFinal ? 'F' : '-');
else if (this->mCode == IC_STORE)
fprintf(file, "V%d+%d, ", mSrc[1].mVarIndex, int(mSrc[1].mIntConst));
if (mSrc[0].mTemp >= 0)
fprintf(file, "R%d(%c%c)", mSrc[0].mTemp, typechars[mSrc[0].mType], mSrc[0].mFinal ? 'F' : '-');
else if (this->mCode == IC_LOAD)
fprintf(file, "V%d+%d", mSrc[0].mVarIndex, int(mSrc[0].mIntConst));
if (this->mCode == IC_CONSTANT)
{
if (mDst.mType == IT_POINTER)
@ -2304,23 +2428,39 @@ void InterInstruction::Disassemble(FILE* file)
fprintf(file, "C%c%d(%d:%d)", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst));
}
else if (mDst.mType == IT_FLOAT)
fprintf(file, "C%f", mConst.mFloatConst);
fprintf(file, "CF:%f", mConst.mFloatConst);
else
{
#ifdef _WIN32
fprintf(file, "C%I64d", mConst.mIntConst);
fprintf(file, "CI:%I64d", mConst.mIntConst);
#else
fprintf(file, "C%lld", mConst.mIntConst);
fprintf(file, "CI:%lld", mConst.mIntConst);
#endif
}
}
else
{
bool first = true;
for (int i = 0; i < mNumOperands; i++)
{
int j = mNumOperands - i - 1;
if (!first)
fprintf(file, ", ");
if (mSrc[j].mType != IT_NONE)
{
mSrc[j].Disassemble(file);
first = false;
}
}
}
fprintf(file, "\n");
}
}
InterCodeBasicBlock::InterCodeBasicBlock(void)
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr)
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr),
mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mEntryBlocks(nullptr)
{
mInPath = false;
mLoopHead = false;
@ -2353,6 +2493,26 @@ void InterCodeBasicBlock::Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlo
}
void InterCodeBasicBlock::CollectEntryBlocks(InterCodeBasicBlock* from)
{
if (from)
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i] != from)
i++;
if (i == mEntryBlocks.Size())
mEntryBlocks.Push(from);
}
if (!mVisited)
{
mVisited = true;
if (mTrueJump) mTrueJump->CollectEntryBlocks(this);
if (mFalseJump) mFalseJump->CollectEntryBlocks(this);
}
}
void InterCodeBasicBlock::CollectEntries(void)
{
mNumEntries++;
@ -3130,6 +3290,392 @@ bool InterCodeBasicBlock::PropagateConstTemps(const GrowingInstructionPtrArray&
return changed;
}
bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
{
bool changed = false;
mNumEntered++;
if (!mLoopHead && mNumEntered < mEntryBlocks.Size())
return false;
mLocalValueRange.Clear();
for (int j = 0; j < mEntryBlocks.Size(); j++)
{
InterCodeBasicBlock* from = mEntryBlocks[j];
GrowingIntegerValueRangeArray& range(this == from->mTrueJump ? from->mTrueValueRange : from->mFalseValueRange);
if (j == 0)
mLocalValueRange = range;
else
{
for (int i = 0; i < mLocalValueRange.Size(); i++)
mLocalValueRange[i].Merge(range[i]);
}
}
for (int i = 0; i < mLocalValueRange.Size(); i++)
if (!mLocalValueRange[i].Same(mEntryValueRange[i]))
changed = true;
if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size())
return changed;
if (!mVisited || changed)
{
mVisited = true;
if (changed)
{
mEntryValueRange = mLocalValueRange;
UpdateLocalIntegerRangeSets();
}
if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets())
changed = true;
if (mFalseJump && mFalseJump->BuildGlobalIntegerRangeSets())
changed = true;
}
return changed;
}
void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
{
mLocalValueRange = mEntryValueRange;
int sz = mInstructions.Size();
for (int i = 0; i < sz; i++)
{
InterInstruction* ins(mInstructions[i]);
for (int i = 0; i < ins->mNumOperands; i++)
{
if (ins->mSrc[i].mTemp >= 0)
ins->mSrc[i].mRange = mLocalValueRange[ins->mSrc[i].mTemp];
}
if (ins->mDst.mTemp >= 0 && IsIntegerType(ins->mDst.mType))
{
IntegerValueRange& vr(mLocalValueRange[ins->mDst.mTemp]);
switch (ins->mCode)
{
case IC_CONSTANT:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = vr.mMaxValue = ins->mConst.mIntConst;
break;
case IC_UNARY_OPERATOR:
{
switch (ins->mOperator)
{
case IA_NEG:
{
IntegerValueRange tr;
IntegerValueRange& sr(mLocalValueRange[ins->mSrc[0].mTemp]);
tr.mMinState = vr.mMaxState;
tr.mMinValue = -vr.mMaxValue;
tr.mMaxState = vr.mMinState;
tr.mMaxValue = -vr.mMinValue;
vr = tr;
}
break;
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
}
break;
}
case IC_CONVERSION_OPERATOR:
switch (ins->mOperator)
{
case IA_EXT8TO16S:
vr = mLocalValueRange[ins->mSrc[0].mTemp];
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -128 || vr.mMaxValue > 127)
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = 127;
}
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < -128 || vr.mMinValue > 127)
{
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = -128;
}
break;
case IA_EXT8TO16U:
vr = mLocalValueRange[ins->mSrc[0].mTemp];
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255)
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = 255;
}
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255)
{
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = 0;
}
break;
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
}
break;
case IC_BINARY_OPERATOR:
switch (ins->mOperator)
{
case IA_ADD:
if (ins->mSrc[0].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (ins->mSrc[0].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (ins->mSrc[0].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue += ins->mSrc[0].mIntConst;
vr.mMinValue += ins->mSrc[0].mIntConst;
}
else if (ins->mSrc[1].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[0].mTemp];
if (ins->mSrc[1].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (ins->mSrc[1].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue += ins->mSrc[1].mIntConst;
vr.mMinValue += ins->mSrc[1].mIntConst;
}
else
{
if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND)
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = ins->mSrc[0].mRange.mMaxValue + ins->mSrc[1].mRange.mMaxValue;
}
else
vr.mMaxState = IntegerValueRange::S_UNBOUND;
if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND)
{
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = ins->mSrc[0].mRange.mMinValue + ins->mSrc[1].mRange.mMinValue;
}
else
vr.mMinState = IntegerValueRange::S_UNBOUND;
}
break;
case IA_SUB:
if (ins->mSrc[0].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (ins->mSrc[0].mIntConst < 0 && vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (ins->mSrc[0].mIntConst > 0 && vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue -= ins->mSrc[0].mIntConst;
vr.mMinValue -= ins->mSrc[0].mIntConst;
}
else if (ins->mSrc[1].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[0].mTemp];
int maxv = vr.mMaxValue, minv = vr.mMinValue;
if (vr.mMaxState == IntegerValueRange::S_WEAK)
{
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
vr.mMinState = IntegerValueRange::S_UNBOUND;
}
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue = ins->mSrc[1].mIntConst - minv;
vr.mMinValue = ins->mSrc[1].mIntConst - maxv;
}
else
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
break;
case IA_MUL:
if (ins->mSrc[0].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (ins->mSrc[0].mIntConst > 0)
{
if (vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue *= ins->mSrc[0].mIntConst;
vr.mMinValue *= ins->mSrc[0].mIntConst;
}
else
{
if (vr.mMaxState == IntegerValueRange::S_WEAK)
{
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
vr.mMinState = IntegerValueRange::S_UNBOUND;
}
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
int maxv = vr.mMaxValue, minv = vr.mMinValue;
vr.mMaxValue = ins->mSrc[0].mIntConst * minv;
vr.mMinValue = ins->mSrc[0].mIntConst * maxv;
}
}
else if (ins->mSrc[1].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[0].mTemp];
if (ins->mSrc[1].mIntConst > 0)
{
if (vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue *= ins->mSrc[1].mIntConst;
vr.mMinValue *= ins->mSrc[1].mIntConst;
}
else
{
if (vr.mMaxState == IntegerValueRange::S_WEAK)
{
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
vr.mMinState = IntegerValueRange::S_UNBOUND;
}
if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
int maxv = vr.mMaxValue, minv = vr.mMinValue;
vr.mMaxValue = ins->mSrc[1].mIntConst * minv;
vr.mMinValue = ins->mSrc[1].mIntConst * maxv;
}
}
else
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
break;
case IA_SHL:
if (ins->mSrc[0].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue <<= ins->mSrc[0].mIntConst;
vr.mMinValue <<= ins->mSrc[0].mIntConst;
}
else
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
break;
case IA_AND:
if (ins->mSrc[0].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (ins->mSrc[0].mIntConst >= 0)
{
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMaxValue = ins->mSrc[0].mIntConst;
vr.mMinValue = 0;
}
}
else if (ins->mSrc[1].mTemp < 0)
{
vr = mLocalValueRange[ins->mSrc[0].mTemp];
if (ins->mSrc[1].mIntConst >= 0)
{
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMaxValue = ins->mSrc[1].mIntConst;
vr.mMinValue = 0;
}
}
else
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
break;
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
}
break;
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
}
ins->mDst.mRange = vr;
}
}
for (int i = 0; i < mLocalValueRange.Size(); i++)
if (!mExitRequiredTemps[i])
mLocalValueRange[i].mMinState = mLocalValueRange[i].mMaxState = IntegerValueRange::S_UNKNOWN;
mTrueValueRange = mLocalValueRange;
mFalseValueRange = mLocalValueRange;
if (sz >= 2)
{
if (mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[sz - 1]->mSrc[0].mTemp == mInstructions[sz - 2]->mDst.mTemp)
{
if (mInstructions[sz - 2]->mOperator == IA_CMPLS)
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPLU)
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = 0;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
}
}
}
}
}
void InterCodeBasicBlock::BuildLocalIntegerRangeSets(int num)
{
int i;
if (!mVisited)
{
mVisited = true;
mEntryValueRange.SetSize(num, true);
mTrueValueRange.SetSize(num, true);
mFalseValueRange.SetSize(num, true);
mLocalValueRange.SetSize(num, true);
UpdateLocalIntegerRangeSets();
if (mTrueJump) mTrueJump->BuildLocalIntegerRangeSets(num);
if (mFalseJump) mFalseJump->BuildLocalIntegerRangeSets(num);
}
}
void InterCodeBasicBlock::BuildLocalTempSets(int num)
{
int i;
@ -5926,13 +6472,27 @@ void InterCodeProcedure::Close(void)
ResetVisited();
mEntryBlock->CollectActiveTemporaries(activeSet);
mTemporaries.SetSize(activeSet.Num(), true);
ResetVisited();
mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries);
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
BuildDataFlowSets();
ResetVisited();
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size());
do {
DisassembleDebug("tt");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets());
DisassembleDebug("Estimated value range");
MapVariables();
DisassembleDebug("mapped variabled");

View File

@ -128,6 +128,30 @@ typedef GrowingArray<InterVariable * > GrowingVariableArray;
#define INVALID_TEMPORARY (-1)
class IntegerValueRange
{
public:
IntegerValueRange(void);
~IntegerValueRange(void);
int64 mMinValue, mMaxValue;
enum State
{
S_UNKNOWN,
S_UNBOUND,
S_WEAK,
S_BOUND
} mMinState, mMaxState;
bool Same(const IntegerValueRange& range) const;
bool Merge(const IntegerValueRange& range);
};
typedef GrowingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
class ValueSet
{
protected:
@ -300,10 +324,15 @@ public:
int mVarIndex, mOperandSize;
LinkerObject * mLinkerObject;
InterMemory mMemory;
IntegerValueRange mRange;
InterOperand(void);
bool IsEqual(const InterOperand & op) const;
bool IsUByte(void) const;
void Disassemble(FILE* file);
};
class InterInstruction
@ -430,6 +459,10 @@ public:
NumberSet mEntryRequiredParams, mEntryProvidedParams;
NumberSet mExitRequiredParams, mExitProvidedParams;
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange;
GrowingArray<InterCodeBasicBlock*> mEntryBlocks;
GrowingInstructionPtrArray mMergeTValues;
ValueSet mMergeValues;
TempForwardingTable mMergeForwardingTable;
@ -441,6 +474,7 @@ public:
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
void CollectEntries(void);
void CollectEntryBlocks(InterCodeBasicBlock* from);
void GenerateTraces(bool expand);
void LocalToTemp(int vindex, int temp);
@ -467,6 +501,10 @@ public:
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
void BuildLocalIntegerRangeSets(int num);
void UpdateLocalIntegerRangeSets(void);
bool BuildGlobalIntegerRangeSets(void);
GrowingIntArray mEntryRenameTable;
GrowingIntArray mExitRenameTable;

View File

@ -5624,9 +5624,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
if (InterTypeSize[ins->mDst.mType] > 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
if (ins->mDst.IsUByte())
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
}
}
@ -5645,9 +5653,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
if (InterTypeSize[ins->mDst.mType] > 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
if (ins->mDst.IsUByte())
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
}
}
@ -5929,77 +5945,131 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
if (ins->mSrc[0].mTemp < 0)
{
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
int shift = ins->mSrc[0].mIntConst & 15;
if (shift == 0)
if (ins->mDst.IsUByte())
{
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
if (shift == 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
if (sreg != treg)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
}
}
}
else if (shift == 1)
{
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
else if (shift == 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
}
}
else if (shift >= 8)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else if (shift > 5)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
for(int i=shift; i<8; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0xff << shift));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg ));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
for (int i = 0; i < shift; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
}
}
else if (shift == 7)
{
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0));
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else if (shift >= 8)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
for (int i = 8; i < shift; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else
{
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
if (shift == 0)
{
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (shift == 1)
{
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (shift == 7)
{
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0));
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else if (shift >= 8)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
for (int i = 8; i < shift; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
}
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
for (int i = 1; i < shift; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
}
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
for (int i = 1; i < shift; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff))
@ -8699,6 +8769,109 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i
return false;
}
bool NativeCodeBasicBlock::PatchDirectAddressSumY(int at, int reg, int apos, int breg)
{
int yindex = 0;
int last = at;
while (last < mIns.Size())
{
if (mIns[last].mType == ASMIT_LDY && mIns[last].mMode == ASMIM_IMMEDIATE && (mIns[last].mAddress == yindex || mIns[last].mAddress == yindex + 1))
yindex = mIns[last].mAddress;
else if (mIns[last].ChangesYReg())
return false;
else if (mIns[last].mMode == ASMIM_ZERO_PAGE && (mIns[last].mAddress == breg || mIns[last].mAddress == breg + 1 || mIns[last].mAddress == reg || mIns[last].mAddress == reg + 1) && mIns[last].ChangesAddress())
return false;
else if (mIns[last].mMode == ASMIM_INDIRECT_Y && mIns[last].mAddress == reg)
{
if (!(mIns[last].mLive & LIVE_MEM))
break;
}
else if (mIns[last].RequiresYReg())
return false;
last++;
}
if (last == mIns.Size())
return false;
mIns[apos].mType = ASMIT_TAY;
for (int i = 0; i < 5; i++)
{
mIns[apos + i + 1].mType = ASMIT_NOP;
mIns[apos + i + 1].mMode = ASMIM_IMPLIED;
}
yindex = 0;
for (int i = apos; i <= last; i++)
{
mIns[i].mLive | LIVE_CPU_REG_Y;
if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE)
{
if (mIns[i].mAddress == yindex)
{
mIns[i].mType = ASMIT_NOP;
mIns[i].mMode = ASMIM_IMPLIED;
}
else
{
mIns[i].mType = ASMIT_INY;
mIns[i].mMode = ASMIM_IMPLIED;
yindex++;
}
}
else if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == reg)
{
mIns[i].mAddress = breg;
}
}
return true;
}
bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int& breg)
{
int j = at - 6;
while (j >= 0)
{
if (
mIns[j + 0].mType == ASMIT_CLC &&
mIns[j + 1].mType == ASMIT_ADC && mIns[j + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[j + 2].mType == ASMIT_STA && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && mIns[j + 2].mAddress == reg &&
mIns[j + 3].mType == ASMIT_LDA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == mIns[j + 1].mAddress + 1 &&
mIns[j + 4].mType == ASMIT_ADC && mIns[j + 4].mMode == ASMIM_IMMEDIATE && mIns[j + 4].mAddress == 0 &&
mIns[j + 5].mType == ASMIT_STA && mIns[j + 5].mMode == ASMIM_ZERO_PAGE && mIns[j + 5].mAddress == reg + 1)
{
breg = mIns[j + 1].mAddress;
int k = j + 6;
while (k < at)
{
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1) && mIns[k].ChangesAddress())
return false;
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1))
return false;
if (mIns[k].mMode == ASMIM_INDIRECT_Y && mIns[k].mAddress == breg)
return false;
k++;
}
apos = j;
return true;
}
if (mIns[j + 5].mMode == ASMIM_ZERO_PAGE && (mIns[j + 5].mAddress == reg || mIns[j + 5].mAddress == reg + 1) && mIns[j + 5].ChangesAddress() || mIns[j + 5].ChangesYReg() || mIns[j + 5].RequiresYReg())
return false;
j--;
}
return false;
}
bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg)
{
@ -12011,6 +12184,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
}
#if 1
if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
{
int apos, breg;
if (FindDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
{
if (PatchDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
progress = true;
}
}
#endif
#if 0
if (i + 7 < mIns.Size())
{
if (
@ -12042,7 +12227,79 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
}
}
#endif
#if 1
#if 0
if (i + 8 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
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 + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress && !(mIns[i + 8].mLive & LIVE_MEM))
{
for (int j = 0; j < 6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 8].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns[i + 9].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 0].mType = ASMIT_TAY;
mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#if 0
if (i + 11 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
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 + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress &&
!mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 9].RequiresYReg() &&
mIns[i + 10].mType == ASMIT_LDY && mIns[i + 10].mMode == ASMIM_IMMEDIATE && mIns[i + 10].mAddress == 1 &&
mIns[i + 11].mMode == ASMIM_INDIRECT_Y && mIns[i + 11].mAddress == mIns[i + 2].mAddress &&
!(mIns[i + 11].mLive & LIVE_MEM))
{
for (int j = 0; j < 6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 11].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 12, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 1));
mIns[i + 12].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 0].mType = ASMIT_TAY;
mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
mIns[i + 10].mType = ASMIT_INY; mIns[i + 10].mMode = ASMIM_IMPLIED;
mIns[i + 11].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#if 0
if (i + 9 < mIns.Size())
{
if (

View File

@ -197,6 +197,8 @@ public:
bool MoveLoadAddImmStoreUp(int at);
bool MoveCLCLoadAddZPStoreUp(int at);
bool MoveLoadAddZPStoreUp(int at);
bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg);
bool PatchDirectAddressSumY(int at, int reg, int apos, int breg);
bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);
bool FindGlobalAddress(int at, int reg, int& apos);
bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags);