Bit shift optimizations
This commit is contained in:
parent
253be26335
commit
4cdc501a34
|
@ -403,6 +403,7 @@ bool Compiler::WriteOutputFile(const char* targetPath)
|
||||||
int i = strlen(prgPath);
|
int i = strlen(prgPath);
|
||||||
while (i > 0 && prgPath[i - 1] != '.')
|
while (i > 0 && prgPath[i - 1] != '.')
|
||||||
i--;
|
i--;
|
||||||
|
if (i > 0)
|
||||||
prgPath[i] = 0;
|
prgPath[i] = 0;
|
||||||
|
|
||||||
strcpy_s(mapPath, prgPath);
|
strcpy_s(mapPath, prgPath);
|
||||||
|
|
|
@ -2282,6 +2282,13 @@ bool InterOperand::IsUByte(void) const
|
||||||
mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 256;
|
mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterOperand::IsSByte(void) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= -128 &&
|
||||||
|
mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 128;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterOperand::IsUnsigned(void) const
|
bool InterOperand::IsUnsigned(void) const
|
||||||
{
|
{
|
||||||
if (mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= 0 && mRange.mMaxState == IntegerValueRange::S_BOUND)
|
if (mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= 0 && mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||||
|
@ -5205,6 +5212,36 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
|
||||||
vr.mMaxValue <<= ins->mSrc[0].mIntConst;
|
vr.mMaxValue <<= ins->mSrc[0].mIntConst;
|
||||||
vr.mMinValue <<= ins->mSrc[0].mIntConst;
|
vr.mMinValue <<= ins->mSrc[0].mIntConst;
|
||||||
}
|
}
|
||||||
|
else if (ins->mSrc[0].IsUByte() && ins->mSrc[0].mRange.mMaxValue < 16)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[1].mTemp < 0)
|
||||||
|
{
|
||||||
|
vr.mMinState = IntegerValueRange::S_BOUND;
|
||||||
|
vr.mMaxState = IntegerValueRange::S_BOUND;
|
||||||
|
|
||||||
|
if (ins->mSrc[1].mIntConst < 0)
|
||||||
|
{
|
||||||
|
vr.mMinValue = ins->mSrc[1].mIntConst << ins->mSrc[0].mRange.mMaxValue;
|
||||||
|
vr.mMaxValue = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vr.mMinValue = 0;
|
||||||
|
vr.mMaxValue = ins->mSrc[1].mIntConst << ins->mSrc[0].mRange.mMaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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].mRange.mMaxValue;
|
||||||
|
vr.mMinValue <<= ins->mSrc[0].mRange.mMaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||||
break;
|
break;
|
||||||
|
@ -6317,6 +6354,130 @@ bool InterCodeBasicBlock::RemoveUnusedStoreInstructions(const GrowingVariableArr
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
GrowingInstructionPtrArray ltvalue(tvalue);
|
||||||
|
|
||||||
|
if (mNumEntries > 1)
|
||||||
|
ltvalue.Clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < mInstructions.Size(); i++)
|
||||||
|
{
|
||||||
|
InterInstruction* ins = mInstructions[i];
|
||||||
|
|
||||||
|
switch (ins->mCode)
|
||||||
|
{
|
||||||
|
case IC_BINARY_OPERATOR:
|
||||||
|
{
|
||||||
|
switch (ins->mOperator)
|
||||||
|
{
|
||||||
|
case IA_SHL:
|
||||||
|
#if 1
|
||||||
|
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0 && ltvalue[ins->mSrc[1].mTemp] && ins->mDst.mType == IT_INT16)
|
||||||
|
{
|
||||||
|
InterInstruction* pins = ltvalue[ins->mSrc[1].mTemp];
|
||||||
|
if (pins->mCode == IC_CONVERSION_OPERATOR && pins->mOperator == IA_EXT8TO16U && pins->mSrc[0].IsUByte() && pins->mSrc[0].mTemp >= 0 && ltvalue[pins->mSrc[0].mTemp])
|
||||||
|
{
|
||||||
|
InterInstruction* ains = ltvalue[pins->mSrc[0].mTemp];
|
||||||
|
|
||||||
|
if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
if (spareTemps + 2 >= ltvalue.Size())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
InterInstruction* nins = new InterInstruction();
|
||||||
|
nins->mCode = IC_BINARY_OPERATOR;
|
||||||
|
nins->mOperator = IA_SHL;
|
||||||
|
nins->mSrc[0] = ins->mSrc[0];
|
||||||
|
nins->mSrc[1] = ains->mSrc[1];
|
||||||
|
nins->mDst.mTemp = spareTemps++;
|
||||||
|
nins->mDst.mType = IT_INT16;
|
||||||
|
nins->mDst.mRange = ins->mDst.mRange;
|
||||||
|
mInstructions.Insert(i, nins);
|
||||||
|
|
||||||
|
ins->mOperator = IA_ADD;
|
||||||
|
ins->mSrc[0] = ains->mSrc[0];
|
||||||
|
ins->mSrc[0].mIntConst <<= nins->mSrc[0].mIntConst;
|
||||||
|
ins->mSrc[1] = nins->mDst;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
if (ins->mSrc[1].mTemp < 0 && ins->mSrc[0].mTemp >= 0 && ltvalue[ins->mSrc[0].mTemp] && ins->mDst.mType == IT_INT16)
|
||||||
|
{
|
||||||
|
InterInstruction* pins = ltvalue[ins->mSrc[0].mTemp];
|
||||||
|
if (pins->mCode == IC_CONVERSION_OPERATOR && pins->mOperator == IA_EXT8TO16U && pins->mSrc[0].IsUByte() && pins->mSrc[0].mRange.mMaxValue < 16 && pins->mSrc[0].mTemp >= 0 && ltvalue[pins->mSrc[0].mTemp])
|
||||||
|
{
|
||||||
|
InterInstruction* ains = ltvalue[pins->mSrc[0].mTemp];
|
||||||
|
|
||||||
|
if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0 && ains->mSrc[1].IsUByte())
|
||||||
|
{
|
||||||
|
ins->mSrc[0] = ains->mSrc[1];
|
||||||
|
ins->mSrc[1].mIntConst <<= ains->mSrc[0].mIntConst;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IC_LEA:
|
||||||
|
if (ins->mSrc[1].mTemp < 0 && ins->mSrc[0].mTemp >= 0 && ltvalue[ins->mSrc[0].mTemp])
|
||||||
|
{
|
||||||
|
InterInstruction* ains = ltvalue[ins->mSrc[0].mTemp];
|
||||||
|
|
||||||
|
if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0)
|
||||||
|
{
|
||||||
|
ins->mSrc[0] = ains->mSrc[1];
|
||||||
|
ins->mSrc[1].mIntConst += ains->mSrc[0].mIntConst;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now kill all instructions that referenced the current destination as source, they are
|
||||||
|
// not valid anymore
|
||||||
|
|
||||||
|
int dtemp = ins->mDst.mTemp;
|
||||||
|
|
||||||
|
if (dtemp >= 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ltvalue.Size(); i++)
|
||||||
|
{
|
||||||
|
if (ltvalue[i] && ltvalue[i]->ReferencesTemp(dtemp))
|
||||||
|
ltvalue[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ltvalue[dtemp] = ins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->SimplifyIntegerNumeric(ltvalue, spareTemps))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (mFalseJump && mFalseJump->SimplifyIntegerNumeric(ltvalue, spareTemps))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int& spareTemps, const GrowingVariableArray& staticVars)
|
void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int& spareTemps, const GrowingVariableArray& staticVars)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -7164,6 +7325,35 @@ void InterCodeBasicBlock::MarkRelevantStatics(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const
|
||||||
|
{
|
||||||
|
InterInstruction* ins = mInstructions[ii];
|
||||||
|
|
||||||
|
if (ins->mCode == IC_LOAD)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ii; i++)
|
||||||
|
if (!CanBypassLoadUp(ins, mInstructions[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ins->mCode == IC_STORE)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ii; i++)
|
||||||
|
if (!CanBypassStore(ins, mInstructions[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
|
||||||
|
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ii; i++)
|
||||||
|
if (!CanBypassUp(ins, mInstructions[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
|
bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -7174,19 +7364,27 @@ bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
|
||||||
|
|
||||||
if (mTrueJump && mFalseJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1 && mTrueJump->mInstructions.Size() && mFalseJump->mInstructions.Size())
|
if (mTrueJump && mFalseJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1 && mTrueJump->mInstructions.Size() && mFalseJump->mInstructions.Size())
|
||||||
{
|
{
|
||||||
InterInstruction* tins = mTrueJump->mInstructions[0];
|
int ti = 0;
|
||||||
InterInstruction* fins = mFalseJump->mInstructions[0];
|
while (ti < mTrueJump->mInstructions.Size() && !changed)
|
||||||
|
|
||||||
if (tins->IsEqualSource(fins) &&
|
|
||||||
tins->mCode != IC_BRANCH &&
|
|
||||||
tins->mCode != IC_JUMP &&
|
|
||||||
tins->mCode != IC_RELATIONAL_OPERATOR)
|
|
||||||
{
|
{
|
||||||
|
InterInstruction* tins = mTrueJump->mInstructions[ti];
|
||||||
|
if (tins->mCode != IC_BRANCH && tins->mCode != IC_JUMP && tins->mCode != IC_RELATIONAL_OPERATOR)
|
||||||
|
{
|
||||||
|
int fi = 0;
|
||||||
|
while (fi < mFalseJump->mInstructions.Size() && !tins->IsEqualSource(mFalseJump->mInstructions[fi]))
|
||||||
|
fi++;
|
||||||
|
|
||||||
|
if (fi < mFalseJump->mInstructions.Size())
|
||||||
|
{
|
||||||
|
InterInstruction* fins = mFalseJump->mInstructions[fi];
|
||||||
|
|
||||||
if ((tins->mDst.mTemp == -1 || !mFalseJump->mEntryRequiredTemps[tins->mDst.mTemp]) &&
|
if ((tins->mDst.mTemp == -1 || !mFalseJump->mEntryRequiredTemps[tins->mDst.mTemp]) &&
|
||||||
(fins->mDst.mTemp == -1 || !mTrueJump->mEntryRequiredTemps[fins->mDst.mTemp]))
|
(fins->mDst.mTemp == -1 || !mTrueJump->mEntryRequiredTemps[fins->mDst.mTemp]))
|
||||||
|
{
|
||||||
|
if (mTrueJump->CanMoveInstructionBeforeBlock(ti) && mFalseJump->CanMoveInstructionBeforeBlock(fi))
|
||||||
{
|
{
|
||||||
int tindex = mInstructions.Size() - 1;
|
int tindex = mInstructions.Size() - 1;
|
||||||
if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc->mTemp)
|
if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc[0].mTemp && CanBypassUp(tins, mInstructions[tindex - 1]))
|
||||||
tindex--;
|
tindex--;
|
||||||
|
|
||||||
mInstructions.Insert(tindex, tins);
|
mInstructions.Insert(tindex, tins);
|
||||||
|
@ -7204,12 +7402,17 @@ bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
|
||||||
mInstructions.Insert(tindex, nins);
|
mInstructions.Insert(tindex, nins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mTrueJump->mInstructions.Remove(0);
|
mTrueJump->mInstructions.Remove(ti);
|
||||||
mFalseJump->mInstructions.Remove(0);
|
mFalseJump->mInstructions.Remove(fi);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ti++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mTrueJump && mTrueJump->MergeCommonPathInstructions())
|
if (mTrueJump && mTrueJump->MergeCommonPathInstructions())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -10289,6 +10492,32 @@ void InterCodeProcedure::Close(void)
|
||||||
DisassembleDebug("Simplified range limited relational ops");
|
DisassembleDebug("Simplified range limited relational ops");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
GrowingInstructionPtrArray silvalues(nullptr);
|
||||||
|
int silvused;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
activeSet.Clear();
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->CollectActiveTemporaries(activeSet);
|
||||||
|
|
||||||
|
silvused = activeSet.Num();
|
||||||
|
silvalues.SetSize(silvused + 16, true);
|
||||||
|
|
||||||
|
mTemporaries.SetSize(activeSet.Num(), true);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
} while (mEntryBlock->SimplifyIntegerNumeric(silvalues, silvused));
|
||||||
|
|
||||||
|
DisassembleDebug("SimplifyIntegerNumeric");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (mModule->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
if (mModule->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -257,6 +257,7 @@ public:
|
||||||
bool IsEqual(const InterOperand & op) const;
|
bool IsEqual(const InterOperand & op) const;
|
||||||
|
|
||||||
bool IsUByte(void) const;
|
bool IsUByte(void) const;
|
||||||
|
bool IsSByte(void) const;
|
||||||
bool IsUnsigned(void) const;
|
bool IsUnsigned(void) const;
|
||||||
|
|
||||||
void Disassemble(FILE* file);
|
void Disassemble(FILE* file);
|
||||||
|
@ -417,6 +418,8 @@ public:
|
||||||
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars);
|
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars);
|
||||||
bool EliminateDeadBranches(void);
|
bool EliminateDeadBranches(void);
|
||||||
|
|
||||||
|
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
|
||||||
|
|
||||||
bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory);
|
bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory);
|
||||||
bool SingleAssignmentTempForwarding(const GrowingInstructionPtrArray& tunified, const GrowingInstructionPtrArray& tvalues);
|
bool SingleAssignmentTempForwarding(const GrowingInstructionPtrArray& tunified, const GrowingInstructionPtrArray& tvalues);
|
||||||
|
|
||||||
|
@ -446,6 +449,7 @@ public:
|
||||||
bool IsTempModifiedOnPath(int temp, int at) const;
|
bool IsTempModifiedOnPath(int temp, int at) const;
|
||||||
|
|
||||||
bool PushSinglePathResultInstructions(void);
|
bool PushSinglePathResultInstructions(void);
|
||||||
|
bool CanMoveInstructionBeforeBlock(int ii) const;
|
||||||
bool MergeCommonPathInstructions(void);
|
bool MergeCommonPathInstructions(void);
|
||||||
|
|
||||||
void PeepholeOptimization(void);
|
void PeepholeOptimization(void);
|
||||||
|
|
|
@ -3081,7 +3081,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIM_IMMEDIATE:
|
case ASMIM_IMMEDIATE:
|
||||||
block->PutByte(uint16(mAddress));
|
block->PutByte(uint8(mAddress));
|
||||||
break;
|
break;
|
||||||
case ASMIM_IMMEDIATE_ADDRESS:
|
case ASMIM_IMMEDIATE_ADDRESS:
|
||||||
if (mLinkerObject)
|
if (mLinkerObject)
|
||||||
|
@ -3106,7 +3106,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
block->PutByte(uint16(mAddress));
|
block->PutByte(uint8(mAddress));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIM_ABSOLUTE:
|
case ASMIM_ABSOLUTE:
|
||||||
|
@ -5667,7 +5667,7 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[index].mTemp]));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[index].mTemp]));
|
||||||
}
|
}
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(mul, ins->mSrc[index].mRange.mMaxValue + 1, false)));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_MUL, mul, ins->mSrc[index].mRange.mMaxValue + 1, false)));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg));
|
||||||
if (ins->mDst.IsUByte())
|
if (ins->mDst.IsUByte())
|
||||||
{
|
{
|
||||||
|
@ -5676,7 +5676,7 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(mul, ins->mSrc[index].mRange.mMaxValue + 1, true)));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_MUL, mul, ins->mSrc[index].mRange.mMaxValue + 1, true)));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7406,6 +7406,30 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + l, frt.mLinkerObject));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + l, frt.mLinkerObject));
|
||||||
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)
|
||||||
|
{
|
||||||
|
int size = ins->mSrc[0].mRange.mMaxValue + 1;
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
||||||
|
if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SHL, ins->mSrc[1].mIntConst, size, false)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
|
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_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SHL, ins->mSrc[1].mIntConst, size, true)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
||||||
|
@ -7624,6 +7648,30 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 47 - l, frt.mLinkerObject));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 47 - l, frt.mLinkerObject));
|
||||||
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)
|
||||||
|
{
|
||||||
|
int size = ins->mSrc[0].mRange.mMaxValue + 1;
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
||||||
|
if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SHR, ins->mSrc[1].mIntConst, size, false)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
|
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_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SHR, ins->mSrc[1].mIntConst, size, true)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
||||||
|
@ -7723,6 +7771,21 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
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].IsSByte() && shift != 0 && shift < 5)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||||
|
|
||||||
|
for (int i = 0; i < shift; i++)
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
||||||
|
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (shift == 0)
|
if (shift == 0)
|
||||||
|
@ -7735,6 +7798,16 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (shift == 1)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
|
}
|
||||||
else if (shift == 7)
|
else if (shift == 7)
|
||||||
{
|
{
|
||||||
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]));
|
||||||
|
@ -7851,6 +7924,30 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
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)
|
||||||
|
{
|
||||||
|
int size = ins->mSrc[0].mRange.mMaxValue + 1;
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
||||||
|
if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
|
||||||
|
{
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SAR, ins->mSrc[1].mIntConst, size, false)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||||
|
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_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(IA_SAR, ins->mSrc[1].mIntConst, size, true)));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
||||||
|
@ -11668,6 +11765,11 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(const NativeCodeBasicBlock*
|
||||||
{
|
{
|
||||||
NativeCodeInstruction& ins(mIns[at]);
|
NativeCodeInstruction& ins(mIns[at]);
|
||||||
|
|
||||||
|
if (ains.mMode == ASMIM_ABSOLUTE_X)
|
||||||
|
ins.mLive |= LIVE_CPU_REG_X;
|
||||||
|
if (ains.mMode == ASMIM_ABSOLUTE_Y)
|
||||||
|
ins.mLive |= LIVE_CPU_REG_Y;
|
||||||
|
|
||||||
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
|
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
|
||||||
{
|
{
|
||||||
if (ins.UsesAddress())
|
if (ins.UsesAddress())
|
||||||
|
@ -12453,6 +12555,32 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(mIns[from].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
start = from;
|
||||||
|
while (start > 0 && mIns[start - 1].mType != ASMIT_LDA && (mIns[start - 1].mMode == ASMIM_IMMEDIATE || mIns[start - 1].mMode == ASMIM_IMPLIED))
|
||||||
|
start--;
|
||||||
|
if (start > 0 && mIns[start - 1].mType == ASMIT_LDA && mIns[start - 1].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
for (int i = from + 1; i < to; i++)
|
||||||
|
{
|
||||||
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[start].mAddress && mIns[i].ChangesAddress())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
start--;
|
||||||
|
mIns.Remove(to);
|
||||||
|
for (int i = start; i < from; i++)
|
||||||
|
{
|
||||||
|
mIns.Insert(to, mIns[start]);
|
||||||
|
mIns.Remove(start);
|
||||||
|
}
|
||||||
|
mIns.Remove(start);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to + 1 < mIns.Size() && mIns[to + 1].mType == ASMIT_STA && !(mIns[to + 1].mLive & LIVE_CPU_REG_A))
|
if (to + 1 < mIns.Size() && mIns[to + 1].mType == ASMIT_STA && !(mIns[to + 1].mLive & LIVE_CPU_REG_A))
|
||||||
|
@ -13500,6 +13628,7 @@ bool NativeCodeBasicBlock::MoveLoadImmStoreAbsoluteUp(int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
||||||
{
|
{
|
||||||
int j = at;
|
int j = at;
|
||||||
|
@ -13520,14 +13649,10 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
||||||
|
|
||||||
if (j > 0 && j < at)
|
if (j > 0 && j < at)
|
||||||
{
|
{
|
||||||
for (int i = at; i > j; i--)
|
mIns.Insert(j, mIns[at + 1]);
|
||||||
{
|
|
||||||
mIns[i] = mIns[i - 1];
|
|
||||||
}
|
|
||||||
mIns[j - 1].mLive |= LIVE_CPU_REG_A;
|
mIns[j - 1].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[j] = mIns[at + 1];
|
|
||||||
mIns[j].mLive |= LIVE_CPU_REG_A;
|
mIns[j].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED;
|
mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -14711,12 +14836,24 @@ bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
|
||||||
lb->mIns[lbs - 2].mType = ASMIT_DEX;
|
lb->mIns[lbs - 2].mType = ASMIT_DEX;
|
||||||
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
lb->mBranch = ASMIT_BNE;
|
lb->mBranch = ASMIT_BNE;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lb->mIns[lbs - 1].mMode == ASMIM_IMMEDIATE)
|
else if (lb->mIns[lbs - 1].mMode == ASMIM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
int a = lb->mIns[lbs - 1].mAddress - mIns[li].mAddress;
|
int a = lb->mIns[lbs - 1].mAddress - mIns[li].mAddress;
|
||||||
|
|
||||||
|
if (lbs == 3 && lb->mIns[0].mType == ASMIT_STA && lb->mIns[0].mMode == ASMIM_ABSOLUTE_X && lb->mIns[0].mLinkerObject && a < 128)
|
||||||
|
{
|
||||||
|
lb->mIns[0].mAddress += mIns[li].mAddress;
|
||||||
|
mIns[li].mAddress = a - 1;
|
||||||
|
lb->mIns[1].mType = ASMIT_DEX;
|
||||||
|
lb->mIns[2].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
|
lb->mBranch = ASMIT_BPL;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i + 2 < lbs && !lb->mIns[i].RequiresXReg())
|
while (i + 2 < lbs && !lb->mIns[i].RequiresXReg())
|
||||||
i++;
|
i++;
|
||||||
|
@ -14726,6 +14863,8 @@ bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
|
||||||
lb->mIns[lbs - 2].mType = ASMIT_DEX;
|
lb->mIns[lbs - 2].mType = ASMIT_DEX;
|
||||||
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
lb->mBranch = ASMIT_BNE;
|
lb->mBranch = ASMIT_BNE;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14733,12 +14872,11 @@ bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
|
||||||
}
|
}
|
||||||
else if (lb->mIns[lbs - 1].mType == ASMIT_CPY)
|
else if (lb->mIns[lbs - 1].mType == ASMIT_CPY)
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* lb = mTrueJump;
|
int li = mIns.Size() - 1;
|
||||||
int lbs = lb->mIns.Size();
|
while (li >= 0 && !mIns[li].ReferencesYReg())
|
||||||
|
li--;
|
||||||
|
|
||||||
if (lb->mIns[lbs - 1].mType == ASMIT_CPY)
|
if (li >= 0 && lb->mIns[lbs - 2].mType == ASMIT_INY && mIns[li].mType == ASMIT_LDY && mIns[li].mMode == ASMIM_IMMEDIATE && mIns[li].mAddress == 0)
|
||||||
{
|
|
||||||
if (lb->mIns[lbs - 2].mType == ASMIT_INY && mIns.Last().mType == ASMIT_LDY && mIns.Last().mMode == ASMIM_IMMEDIATE && mIns.Last().mAddress == 0)
|
|
||||||
{
|
{
|
||||||
if (lb->mIns[lbs - 1].mMode == ASMIM_ZERO_PAGE)
|
if (lb->mIns[lbs - 1].mMode == ASMIM_ZERO_PAGE)
|
||||||
{
|
{
|
||||||
|
@ -14749,11 +14887,39 @@ bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
|
||||||
i++;
|
i++;
|
||||||
if (i + 2 == lbs)
|
if (i + 2 == lbs)
|
||||||
{
|
{
|
||||||
mIns[mIns.Size() - 1].mMode = ASMIM_ZERO_PAGE;
|
mIns[li].mMode = ASMIM_ZERO_PAGE;
|
||||||
mIns[mIns.Size() - 1].mAddress = a;
|
mIns[li].mAddress = a;
|
||||||
lb->mIns[lbs - 2].mType = ASMIT_DEY;
|
lb->mIns[lbs - 2].mType = ASMIT_DEY;
|
||||||
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
lb->mBranch = ASMIT_BNE;
|
lb->mBranch = ASMIT_BNE;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lb->mIns[lbs - 1].mMode == ASMIM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
int a = lb->mIns[lbs - 1].mAddress - mIns[li].mAddress;
|
||||||
|
|
||||||
|
if (lbs == 3 && lb->mIns[0].mType == ASMIT_STA && lb->mIns[0].mMode == ASMIM_ABSOLUTE_Y && lb->mIns[0].mLinkerObject && a < 128)
|
||||||
|
{
|
||||||
|
lb->mIns[0].mAddress += mIns[li].mAddress;
|
||||||
|
mIns[li].mAddress = a - 1;
|
||||||
|
lb->mIns[1].mType = ASMIT_DEY;
|
||||||
|
lb->mIns[2].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
|
lb->mBranch = ASMIT_BPL;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i + 2 < lbs && !lb->mIns[i].RequiresYReg())
|
||||||
|
i++;
|
||||||
|
if (i + 2 == lbs)
|
||||||
|
{
|
||||||
|
mIns[li].mAddress = a;
|
||||||
|
lb->mIns[lbs - 2].mType = ASMIT_DEY;
|
||||||
|
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
|
||||||
|
lb->mBranch = ASMIT_BNE;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16601,7 +16767,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
for (int i = 2; i + 1 < mIns.Size(); i++)
|
for (int i = 2; i + 1 < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && (mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE)
|
||||||
{
|
{
|
||||||
if (MoveLoadStoreUp(i))
|
if (MoveLoadStoreUp(i))
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -16687,8 +16853,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
for (int i = 2; i + 1 < mIns.Size(); i++)
|
for (int i = 2; i + 1 < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA &&
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA &&
|
||||||
(mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y) &&
|
(mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y))
|
||||||
!(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
|
|
||||||
{
|
{
|
||||||
if (MoveAbsoluteLoadStoreUp(i))
|
if (MoveAbsoluteLoadStoreUp(i))
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -19262,6 +19427,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 3].mMode = ASMIM_IMPLIED;
|
mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_TXA &&
|
mIns[i + 0].mType == ASMIT_TXA &&
|
||||||
mIns[i + 1].mType == ASMIT_CLC &&
|
mIns[i + 1].mType == ASMIT_CLC &&
|
||||||
|
@ -21689,17 +21855,34 @@ void NativeCodeGenerator::CompleteRuntime(void)
|
||||||
|
|
||||||
for (int j = 0; j < m.mSize; j++)
|
for (int j = 0; j < m.mSize; j++)
|
||||||
{
|
{
|
||||||
m.mLinkerLSB->mData[j] = (uint8)(m.mFactor * j);
|
int val = m.mFactor;
|
||||||
m.mLinkerMSB->mData[j] = (uint8)(m.mFactor * j >> 8);
|
switch (m.mOperator)
|
||||||
|
{
|
||||||
|
case IA_MUL:
|
||||||
|
val *= j;
|
||||||
|
break;
|
||||||
|
case IA_SHL:
|
||||||
|
val <<= j;
|
||||||
|
break;
|
||||||
|
case IA_SHR:
|
||||||
|
val = (val & 0xffff) >> j;
|
||||||
|
break;
|
||||||
|
case IA_SAR:
|
||||||
|
val = (int)(short)val >> j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.mLinkerLSB->mData[j] = (uint8)(val);
|
||||||
|
m.mLinkerMSB->mData[j] = (uint8)(val >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LinkerObject* NativeCodeGenerator::AllocateShortMulTable(int factor, int size, bool msb)
|
LinkerObject* NativeCodeGenerator::AllocateShortMulTable(InterOperator op, int factor, int size, bool msb)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < mMulTables.Size() && mMulTables[i].mFactor != factor)
|
while (i < mMulTables.Size() && (mMulTables[i].mFactor != factor || mMulTables[i].mOperator != op))
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i == mMulTables.Size())
|
if (i == mMulTables.Size())
|
||||||
|
@ -21708,13 +21891,32 @@ LinkerObject* NativeCodeGenerator::AllocateShortMulTable(int factor, int size, b
|
||||||
MulTable mt;
|
MulTable mt;
|
||||||
|
|
||||||
char name[20];
|
char name[20];
|
||||||
sprintf_s(name, "__multab%dL", factor);
|
const char* base = "";
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case IA_MUL:
|
||||||
|
base = "mul";
|
||||||
|
break;
|
||||||
|
case IA_SHL:
|
||||||
|
base = "shl";
|
||||||
|
break;
|
||||||
|
case IA_SHR:
|
||||||
|
base = "shr";
|
||||||
|
break;
|
||||||
|
case IA_SAR:
|
||||||
|
base = "sar";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf_s(name, "__%stab%dL", base, factor);
|
||||||
mt.mLinkerLSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
|
mt.mLinkerLSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
|
||||||
sprintf_s(name, "__multab%dH", factor);
|
sprintf_s(name, "__%stab%dH", base, factor);
|
||||||
mt.mLinkerMSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
|
mt.mLinkerMSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
|
||||||
|
|
||||||
mt.mFactor = factor;
|
mt.mFactor = factor;
|
||||||
mt.mSize = size;
|
mt.mSize = size;
|
||||||
|
mt.mOperator = op;
|
||||||
|
|
||||||
mMulTables.Push(mt);
|
mMulTables.Push(mt);
|
||||||
|
|
||||||
|
|
|
@ -392,9 +392,10 @@ public:
|
||||||
{
|
{
|
||||||
LinkerObject * mLinkerLSB, * mLinkerMSB;
|
LinkerObject * mLinkerLSB, * mLinkerMSB;
|
||||||
int mFactor, mSize;
|
int mFactor, mSize;
|
||||||
|
InterOperator mOperator;
|
||||||
};
|
};
|
||||||
|
|
||||||
LinkerObject* AllocateShortMulTable(int factor, int size, bool msb);
|
LinkerObject* AllocateShortMulTable(InterOperator op, int factor, int size, bool msb);
|
||||||
|
|
||||||
Runtime& ResolveRuntime(const Ident* ident);
|
Runtime& ResolveRuntime(const Ident* ident);
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.5.118");
|
strcpy(strProductVersion, "1.5.119");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,5,118,0
|
FILEVERSION 1,5,119,0
|
||||||
PRODUCTVERSION 1,5,118,0
|
PRODUCTVERSION 1,5,119,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,12 +43,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "oscar64"
|
VALUE "CompanyName", "oscar64"
|
||||||
VALUE "FileDescription", "oscar64 compiler"
|
VALUE "FileDescription", "oscar64 compiler"
|
||||||
VALUE "FileVersion", "1.5.118.0"
|
VALUE "FileVersion", "1.5.119.0"
|
||||||
VALUE "InternalName", "oscar64.exe"
|
VALUE "InternalName", "oscar64.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "oscar64.exe"
|
VALUE "OriginalFilename", "oscar64.exe"
|
||||||
VALUE "ProductName", "oscar64"
|
VALUE "ProductName", "oscar64"
|
||||||
VALUE "ProductVersion", "1.5.118.0"
|
VALUE "ProductVersion", "1.5.119.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -4023,15 +4023,15 @@
|
||||||
{
|
{
|
||||||
"Name" = "8:Microsoft Visual Studio"
|
"Name" = "8:Microsoft Visual Studio"
|
||||||
"ProductName" = "8:oscar64"
|
"ProductName" = "8:oscar64"
|
||||||
"ProductCode" = "8:{608057E0-DAA0-4E03-846A-C1CC3DB0DF23}"
|
"ProductCode" = "8:{B1BF49F7-D667-4323-99B3-BBC698F30A19}"
|
||||||
"PackageCode" = "8:{65A09B39-BEDF-4797-AFF2-480B80A618D0}"
|
"PackageCode" = "8:{4B34FDC5-E807-4B25-8603-B7969A6CF518}"
|
||||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||||
"AspNetVersion" = "8:2.0.50727.0"
|
"AspNetVersion" = "8:2.0.50727.0"
|
||||||
"RestartWWWService" = "11:FALSE"
|
"RestartWWWService" = "11:FALSE"
|
||||||
"RemovePreviousVersions" = "11:TRUE"
|
"RemovePreviousVersions" = "11:TRUE"
|
||||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||||
"InstallAllUsers" = "11:FALSE"
|
"InstallAllUsers" = "11:FALSE"
|
||||||
"ProductVersion" = "8:1.5.118"
|
"ProductVersion" = "8:1.5.119"
|
||||||
"Manufacturer" = "8:oscar64"
|
"Manufacturer" = "8:oscar64"
|
||||||
"ARPHELPTELEPHONE" = "8:"
|
"ARPHELPTELEPHONE" = "8:"
|
||||||
"ARPHELPLINK" = "8:"
|
"ARPHELPLINK" = "8:"
|
||||||
|
|
Loading…
Reference in New Issue