Value range annotation for intermediate code
This commit is contained in:
parent
b9c477976a
commit
05a6c71698
|
@ -77,16 +77,17 @@ int main(void)
|
||||||
a[i] = i % 10;
|
a[i] = i % 10;
|
||||||
al[i] = i % 10;
|
al[i] = i % 10;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
assert(sum(a, 100) == 450);
|
assert(sum(a, 100) == 450);
|
||||||
copy(b, a, 100);
|
copy(b, a, 100);
|
||||||
assert(sum(b, 100) == 450);
|
assert(sum(b, 100) == 450);
|
||||||
reverse(c, a, 100);
|
reverse(c, a, 100);
|
||||||
assert(sum(c, 100) == 450);
|
assert(sum(c, 100) == 450);
|
||||||
|
|
||||||
assert(sumb(a, 100) == 450);
|
assert(sumb(a, 100) == 450);
|
||||||
|
#endif
|
||||||
copyb(b, a, 100);
|
copyb(b, a, 100);
|
||||||
assert(sumb(b, 100) == 450);
|
assert(sumb(b, 100) == 450);
|
||||||
|
#if 0
|
||||||
reverseb(c, a, 100);
|
reverseb(c, a, 100);
|
||||||
assert(sumb(c, 100) == 450);
|
assert(sumb(c, 100) == 450);
|
||||||
|
|
||||||
|
@ -97,6 +98,6 @@ int main(void)
|
||||||
|
|
||||||
reversel(cl, al, 100);
|
reversel(cl, al, 100);
|
||||||
assert(suml(cl, 100) == 450);
|
assert(suml(cl, 100) == 450);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,90 @@ static bool IsIntegerType(InterType type)
|
||||||
return type >= IT_INT8 && type <= IT_INT32;
|
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)
|
ValueSet::ValueSet(void)
|
||||||
{
|
{
|
||||||
mSize = 32;
|
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)
|
: 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
|
bool InterOperand::IsEqual(const InterOperand& op) const
|
||||||
{
|
{
|
||||||
if (mType != op.mType || mTemp != op.mTemp)
|
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)
|
void InterInstruction::Disassemble(FILE* file)
|
||||||
{
|
{
|
||||||
if (this->mCode != IC_NONE)
|
if (this->mCode != IC_NONE)
|
||||||
|
@ -2285,18 +2416,11 @@ void InterInstruction::Disassemble(FILE* file)
|
||||||
static char typechars[] = "NBCILFP";
|
static char typechars[] = "NBCILFP";
|
||||||
|
|
||||||
fprintf(file, "\t");
|
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");
|
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 (this->mCode == IC_CONSTANT)
|
||||||
{
|
{
|
||||||
if (mDst.mType == IT_POINTER)
|
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));
|
fprintf(file, "C%c%d(%d:%d)", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst));
|
||||||
}
|
}
|
||||||
else if (mDst.mType == IT_FLOAT)
|
else if (mDst.mType == IT_FLOAT)
|
||||||
fprintf(file, "C%f", mConst.mFloatConst);
|
fprintf(file, "CF:%f", mConst.mFloatConst);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
fprintf(file, "C%I64d", mConst.mIntConst);
|
fprintf(file, "CI:%I64d", mConst.mIntConst);
|
||||||
#else
|
#else
|
||||||
fprintf(file, "C%lld", mConst.mIntConst);
|
fprintf(file, "CI:%lld", mConst.mIntConst);
|
||||||
#endif
|
#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");
|
fprintf(file, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InterCodeBasicBlock::InterCodeBasicBlock(void)
|
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;
|
mInPath = false;
|
||||||
mLoopHead = 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)
|
void InterCodeBasicBlock::CollectEntries(void)
|
||||||
{
|
{
|
||||||
mNumEntries++;
|
mNumEntries++;
|
||||||
|
@ -3130,6 +3290,392 @@ bool InterCodeBasicBlock::PropagateConstTemps(const GrowingInstructionPtrArray&
|
||||||
return changed;
|
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)
|
void InterCodeBasicBlock::BuildLocalTempSets(int num)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -5926,13 +6472,27 @@ void InterCodeProcedure::Close(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CollectActiveTemporaries(activeSet);
|
mEntryBlock->CollectActiveTemporaries(activeSet);
|
||||||
|
|
||||||
|
|
||||||
mTemporaries.SetSize(activeSet.Num(), true);
|
mTemporaries.SetSize(activeSet.Num(), true);
|
||||||
|
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries);
|
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();
|
MapVariables();
|
||||||
|
|
||||||
DisassembleDebug("mapped variabled");
|
DisassembleDebug("mapped variabled");
|
||||||
|
|
|
@ -128,6 +128,30 @@ typedef GrowingArray<InterVariable * > GrowingVariableArray;
|
||||||
|
|
||||||
#define INVALID_TEMPORARY (-1)
|
#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
|
class ValueSet
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -300,10 +324,15 @@ public:
|
||||||
int mVarIndex, mOperandSize;
|
int mVarIndex, mOperandSize;
|
||||||
LinkerObject * mLinkerObject;
|
LinkerObject * mLinkerObject;
|
||||||
InterMemory mMemory;
|
InterMemory mMemory;
|
||||||
|
IntegerValueRange mRange;
|
||||||
|
|
||||||
InterOperand(void);
|
InterOperand(void);
|
||||||
|
|
||||||
bool IsEqual(const InterOperand & op) const;
|
bool IsEqual(const InterOperand & op) const;
|
||||||
|
|
||||||
|
bool IsUByte(void) const;
|
||||||
|
|
||||||
|
void Disassemble(FILE* file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InterInstruction
|
class InterInstruction
|
||||||
|
@ -430,6 +459,10 @@ public:
|
||||||
NumberSet mEntryRequiredParams, mEntryProvidedParams;
|
NumberSet mEntryRequiredParams, mEntryProvidedParams;
|
||||||
NumberSet mExitRequiredParams, mExitProvidedParams;
|
NumberSet mExitRequiredParams, mExitProvidedParams;
|
||||||
|
|
||||||
|
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange;
|
||||||
|
|
||||||
|
GrowingArray<InterCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
GrowingInstructionPtrArray mMergeTValues;
|
GrowingInstructionPtrArray mMergeTValues;
|
||||||
ValueSet mMergeValues;
|
ValueSet mMergeValues;
|
||||||
TempForwardingTable mMergeForwardingTable;
|
TempForwardingTable mMergeForwardingTable;
|
||||||
|
@ -441,6 +474,7 @@ public:
|
||||||
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
||||||
|
|
||||||
void CollectEntries(void);
|
void CollectEntries(void);
|
||||||
|
void CollectEntryBlocks(InterCodeBasicBlock* from);
|
||||||
void GenerateTraces(bool expand);
|
void GenerateTraces(bool expand);
|
||||||
|
|
||||||
void LocalToTemp(int vindex, int temp);
|
void LocalToTemp(int vindex, int temp);
|
||||||
|
@ -467,6 +501,10 @@ public:
|
||||||
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
|
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
|
||||||
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
|
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
|
||||||
|
|
||||||
|
void BuildLocalIntegerRangeSets(int num);
|
||||||
|
void UpdateLocalIntegerRangeSets(void);
|
||||||
|
bool BuildGlobalIntegerRangeSets(void);
|
||||||
|
|
||||||
GrowingIntArray mEntryRenameTable;
|
GrowingIntArray mEntryRenameTable;
|
||||||
GrowingIntArray mExitRenameTable;
|
GrowingIntArray mExitRenameTable;
|
||||||
|
|
||||||
|
|
|
@ -5624,9 +5624,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
if (InterTypeSize[ins->mDst.mType] > 1)
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
if (ins->mDst.IsUByte())
|
||||||
mIns.Push(insh);
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
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));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
if (InterTypeSize[ins->mDst.mType] > 1)
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
if (ins->mDst.IsUByte())
|
||||||
mIns.Push(insh);
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
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)
|
if (ins->mSrc[0].mTemp < 0)
|
||||||
{
|
{
|
||||||
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||||
|
|
||||||
int shift = ins->mSrc[0].mIntConst & 15;
|
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]));
|
if (sreg != treg)
|
||||||
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_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (shift == 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]));
|
if (ins->mSrc[1].mTemp != ins->mDst.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, sreg));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
}
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
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_LDA, ASMIM_IMMEDIATE, 0));
|
||||||
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_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
|
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_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
for (int i = 8; i < shift; i++)
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
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));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
{
|
||||||
}
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
for (int i = 1; i < shift; i++)
|
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_ASL, ASMIM_ZERO_PAGE, treg));
|
}
|
||||||
|
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));
|
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))
|
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;
|
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)
|
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 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 (i + 7 < mIns.Size())
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
|
@ -12042,7 +12227,79 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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 (i + 9 < mIns.Size())
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -197,6 +197,8 @@ public:
|
||||||
bool MoveLoadAddImmStoreUp(int at);
|
bool MoveLoadAddImmStoreUp(int at);
|
||||||
bool MoveCLCLoadAddZPStoreUp(int at);
|
bool MoveCLCLoadAddZPStoreUp(int at);
|
||||||
bool MoveLoadAddZPStoreUp(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 FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);
|
||||||
bool FindGlobalAddress(int at, int reg, int& apos);
|
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);
|
bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags);
|
||||||
|
|
Loading…
Reference in New Issue