diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ead4dac..2ce8eba 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -41,6 +41,44 @@ bool IntegerValueRange::Same(const IntegerValueRange& range) const return false; } +void IntegerValueRange::LimitMin(int64 value) +{ + if (mMinState != S_BOUND || mMinValue < value) + { + mMinState = S_BOUND; + mMinValue = value; + } +} + +void IntegerValueRange::LimitMax(int64 value) +{ + if (mMaxState != S_BOUND || mMaxValue > value) + { + mMaxState = S_BOUND; + mMaxValue = value; + } +} + +void IntegerValueRange::LimitMinWeak(int64 value) +{ + if (mMinState == S_UNBOUND || mMinValue < value) + { + mMinState = S_BOUND; + mMinValue = value; + } + +} + +void IntegerValueRange::LimitMaxWeak(int64 value) +{ + if (mMaxState == S_UNBOUND || mMaxValue > value) + { + mMaxState = S_BOUND; + mMaxValue = value; + } +} + + bool IntegerValueRange::Merge(const IntegerValueRange& range) { bool changed = false; @@ -3367,6 +3405,10 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void) if (mInstructions[sz - 2]->mSrc[1].IsUnsigned()) mInstructions[sz - 2]->mOperator = IA_CMPLU; } + else if (mInstructions[sz - 2]->mSrc[0].IsUnsigned() && mInstructions[sz - 2]->mSrc[1].IsUnsigned()) + { + mInstructions[sz - 2]->mOperator = IA_CMPLU; + } } } #endif @@ -3427,6 +3469,32 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void) return changed; } +static int64 SignedTypeMin(InterType type) +{ + switch (type) + { + case IT_INT8: + return -128; + case IT_INT16: + return -32768; + default: + return -0x80000000LL; + } +} + +static int64 SignedTypeMax(InterType type) +{ + switch (type) + { + case IT_INT8: + return 127; + case IT_INT16: + return 32767; + default: + return 0x7fffffff; + } +} + void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) { mLocalValueRange = mEntryValueRange; @@ -3793,14 +3861,28 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) { 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; + int s1 = mInstructions[sz - 2]->mSrc[1].mTemp, s0 = mInstructions[sz - 2]->mSrc[0].mTemp; - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + if (s0 < 0) + { + mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); + mTrueValueRange[s1].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[1].mType)); + + mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); + } + else if (s1 < 0) + { + mTrueValueRange[s0].LimitMin(mInstructions[sz - 2]->mSrc[1].mIntConst + 1); + mTrueValueRange[s0].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[0].mType)); + + mFalseValueRange[s0].LimitMax(mInstructions[sz - 2]->mSrc[1].mIntConst); + } + else + { + if (mLocalValueRange[s0].mMaxState == IntegerValueRange::S_BOUND) + mTrueValueRange[s1].LimitMax(mLocalValueRange[s0].mMaxValue - 1); + if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND) + mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue); } } else if (mInstructions[sz - 2]->mOperator == IA_CMPLES) @@ -3808,11 +3890,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) 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; - - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1; + mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); + mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); } } else if (mInstructions[sz - 2]->mOperator == IA_CMPGS) @@ -3820,11 +3899,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) { int t = mInstructions[sz - 2]->mSrc[1].mTemp; - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1; - - mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); + mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); } } else if (mInstructions[sz - 2]->mOperator == IA_CMPGES) @@ -3832,11 +3908,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) { int t = mInstructions[sz - 2]->mSrc[1].mTemp; - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; - - mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1; + mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); + mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); } } else if (mInstructions[sz - 2]->mOperator == IA_CMPLU) @@ -3846,28 +3919,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) int t = mInstructions[sz - 2]->mSrc[1].mTemp; if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) { - 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; + mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); + mTrueValueRange[t].LimitMin(0); if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) { - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); } } else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) { - mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1; - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = 0; + mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1); + mTrueValueRange[t].LimitMin(0); if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) { - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue; + mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue); } } } @@ -3877,15 +3944,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) 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; - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = 0; + mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); + mTrueValueRange[t].LimitMin(0); if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) { - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1; + mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); } } } @@ -3896,14 +3960,11 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) int t = mInstructions[sz - 2]->mSrc[1].mTemp; // if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0) { - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1; + mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); } - mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst; - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = 0; + mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); + mFalseValueRange[t].LimitMin(0); } } else if (mInstructions[sz - 2]->mOperator == IA_CMPGEU) @@ -3913,14 +3974,11 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void) int t = mInstructions[sz - 2]->mSrc[1].mTemp; if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0) { - mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; + mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); } - mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1; - mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND; - mFalseValueRange[t].mMinValue = 0; + mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); + mFalseValueRange[t].LimitMin(0); } } } @@ -6928,7 +6986,12 @@ void InterCodeProcedure::SingleAssignmentForwarding(void) ResetVisited(); mEntryBlock->SingleAssignmentTempForwarding(tunified, tvalues); + BuildDataFlowSets(); + TempForwarding(); + RemoveUnusedInstructions(); + DisassembleDebug("single assignment forwarding"); + } void InterCodeProcedure::TempForwarding(void) @@ -7277,6 +7340,7 @@ void InterCodeProcedure::Close(void) DisassembleDebug("Peephole optimized"); bool changed = false; +#if 1 do { BuildDataFlowSets(); @@ -7287,7 +7351,7 @@ void InterCodeProcedure::Close(void) DisassembleDebug("Pushed single path result"); } while (changed); - +#endif BuildDataFlowSets(); @@ -7341,7 +7405,7 @@ void InterCodeProcedure::Close(void) mEntryBlock->CollectEntryBlocks(nullptr); BuildDataFlowSets(); - +#if 1 ResetVisited(); mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size()); @@ -7357,7 +7421,7 @@ void InterCodeProcedure::Close(void) mEntryBlock->SimplifyIntegerRangeRelops(); DisassembleDebug("Simplified range limited relational ops"); - +#endif MapVariables(); DisassembleDebug("mapped variabled"); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index e58e0e1..158691b 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -146,6 +146,12 @@ public: bool Same(const IntegerValueRange& range) const; bool Merge(const IntegerValueRange& range); + + void LimitMin(int64 value); + void LimitMax(int64 value); + + void LimitMinWeak(int64 value); + void LimitMaxWeak(int64 value); }; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 6cd03aa..b6995bd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -6037,9 +6037,19 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); if (InterTypeSize[ins->mDst.mType] > 1) { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); +#if 1 + if (ins->mDst.IsUByte()) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else +#endif + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } } @@ -7708,9 +7718,11 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff)); +#if 1 if (ins->mSrc[0].IsUByte()) mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); else +#endif mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); } @@ -7720,9 +7732,11 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER)); +#if 1 if (ins->mSrc[0].IsUByte()) mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); else +#endif mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); } @@ -9975,6 +9989,43 @@ bool NativeCodeBasicBlock::MoveLoadAddZPStoreUp(int at) return false; } +bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at) +{ + int j = at + 4; + while (j < mIns.Size()) + { + if (mIns[j].mType == ASMIT_LDA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at + 3].mAddress) + { + if (j == at + 4) + return false; + if (mIns[j].mLive & LIVE_CPU_REG_C) + return false; + + mIns.Insert(j, mIns[at + 3]); // STA + mIns.Insert(j, mIns[at + 2]); // ADC + mIns.Insert(j, mIns[at + 1]); // LDA + mIns.Insert(j, mIns[at + 0]); // CLC + + mIns[at + 0].mType = ASMIT_NOP; mIns[at + 0].mMode = ASMIM_IMPLIED; + mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED; + mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED; + mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED; + return true; + } + + if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress)) + return false; + if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress)) + return false; + if (mIns[j].UsesZeroPage(mIns[at + 3].mAddress)) + return false; + + j++; + } + + return false; +} + bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bool global) { bool changed = false; @@ -10148,6 +10199,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prevBlock, NativeCodeBasicBlock* exitBlock) { + return false; + bool changed = false; int ai = 0; @@ -11354,6 +11407,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(void) carryClear = carrySet = false; } +#if 1 if (carryClear || carrySet) { int i = 0; @@ -11367,7 +11421,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(void) mIns.Remove(i); } } - +#endif if (mTrueJump) mTrueJump->BlockSizeReduction(); if (mFalseJump) @@ -11515,6 +11569,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } #endif +#if 1 + // move simple add down to consumer + + if (!changed) + { + for (int i = 0; i + 4 < mIns.Size(); i++) + { + if ( + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && (mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)) == 0) + { + if (MoveCLCLoadAddZPStoreDown(i)) + changed = true; + } + } + } +#endif + // // shorten x/y register livetime @@ -12978,6 +13052,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) progress = true; } #endif +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_ADC && + mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && !(mIns[i + 3].mLive & LIVE_CPU_REG_C)) + { + mIns[i + 0].mAddress += mIns[i + 3].mAddress; + + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; + + progress = true; + } +#endif else if ( mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) && diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 477f947..66abb9f 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -206,6 +206,7 @@ public: bool MoveLoadAddImmStoreUp(int at); bool MoveCLCLoadAddZPStoreUp(int at); bool MoveLoadAddZPStoreUp(int at); + bool MoveCLCLoadAddZPStoreDown(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);