Optimize single use of global variables in function

This commit is contained in:
drmortalwombat 2022-02-27 17:19:51 +01:00
parent 756245694f
commit fbdb513697
6 changed files with 405 additions and 61 deletions

View File

@ -114,6 +114,9 @@ rem @echo off
@call :test structmembertest.c @call :test structmembertest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test structarraycopy.c
@if %errorlevel% neq 0 goto :error
@call :test randsumtest.c @call :test randsumtest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

View File

@ -0,0 +1,49 @@
struct Point
{
int x, y;
};
Point tcorners[8], pcorners[8];
int bm_line(void)
{
}
void drawCube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
bm_line();
if (!(i & 2))
bm_line();
if (!(i & 4))
bm_line();
pcorners[i] = tcorners[i];
}
}
int main(void)
{
for(int i=0; i<8; i++)
{
tcorners[i].x = (i + 1) * 3;
tcorners[i].y = (i + 1) * 7;
}
drawCube();
int sum = 0;
for(int i=0; i<8; i++)
{
sum += pcorners[i].x;
sum -= tcorners[i].y;
}
return sum + 144;
}

View File

@ -10,6 +10,8 @@ static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 0x00000020;
static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 0x00000040; static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 0x00000040;
static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080; static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080;
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00000100;
static const uint64 COPT_TARGET_PRG = 0x100000000ULL; static const uint64 COPT_TARGET_PRG = 0x100000000ULL;
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL; static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL; static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;
@ -24,7 +26,7 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE |
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE;
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS; static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS;

View File

@ -690,6 +690,42 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const
return true; return true;
else if (mMode == ASMIM_INDIRECT_Y && (mAddress == address || mAddress + 1 == address)) else if (mMode == ASMIM_INDIRECT_Y && (mAddress == address || mAddress + 1 == address))
return true; return true;
else if (mType == ASMIT_JSR)
{
if (address >= BC_REG_ACCU && address < BC_REG_ACCU + 4)
return true;
if (address >= BC_REG_WORK && address < BC_REG_WORK + 4)
return true;
if (mFlags & NCIF_RUNTIME)
{
if (mFlags & NCIF_USE_ZP_32_X)
{
if (address >= mParam && address < mParam + 4)
return true;
}
if (mFlags & NCIF_FEXEC)
{
if (address >= BC_REG_FPARAMS && address < BC_REG_FPARAMS_END)
return true;
}
}
else
{
if (mLinkerObject)
{
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++)
{
if (address >= mLinkerObject->mTemporaries[i] && address < mLinkerObject->mTemporaries[i] + mLinkerObject->mTempSizes[i])
return true;
}
}
}
return false;
}
else else
return false; return false;
} }
@ -778,6 +814,20 @@ bool NativeCodeInstruction::ChangesAccu(void) const
bool NativeCodeInstruction::UsesAddress(void) const
{
if (mMode != ASMIM_IMPLIED)
{
return
mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR ||
mType == ASMIT_LDA || mType == ASMIT_LDX || mType == ASMIT_LDY ||
mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY ||
mType == ASMIT_ADC || mType == ASMIT_SBC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR;
}
else
return false;
}
bool NativeCodeInstruction::ChangesAddress(void) const bool NativeCodeInstruction::ChangesAddress(void) const
{ {
if (mMode != ASMIM_IMPLIED) if (mMode != ASMIM_IMPLIED)
@ -4897,7 +4947,14 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc,
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
int size = ins->mConst.mOperandSize; int size = ins->mConst.mOperandSize;
if (size < 4) int msize = 4;
if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
msize = 8;
else if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
msize = 2;
if (size <= msize)
{ {
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
@ -9559,6 +9616,33 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc)
pblock->mIns.Push(mIns[0]); pblock->mIns.Push(mIns[0]);
mIns.Remove(0); mIns.Remove(0);
changed = true;
}
}
else if (mIns[0].mType == ASMIT_LDX && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_CPU_REG_A))
{
if (lblock->mIns[ls - 2].mType == ASMIT_LDA && lblock->mIns[ls - 2].mMode == ASMIM_ZERO_PAGE && lblock->mIns[ls - 2].mAddress == mIns[0].mAddress &&
lblock->mIns[ls - 1].mType == ASMIT_CMP && !(lblock->mIns[ls - 1].mLive & LIVE_CPU_REG_A))
{
lblock->mIns[ls - 2].mType = ASMIT_LDX; lblock->mIns[ls - 2].mLive |= LIVE_CPU_REG_X;
lblock->mIns[ls - 1].mType = ASMIT_CPX; lblock->mIns[ls - 1].mLive |= LIVE_CPU_REG_X;
pblock->mIns.Push(mIns[0]);
mIns.Remove(0);
changed = true;
}
}
else if (mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE)
{
if (lblock->mIns[ls - 2].mType == ASMIT_LDA && lblock->mIns[ls - 2].mMode == ASMIM_ZERO_PAGE && lblock->mIns[ls - 2].mAddress == mIns[0].mAddress &&
lblock->mIns[ls - 1].mType == ASMIT_CMP)
{
pblock->mIns.Push(mIns[0]);
mIns.Remove(0);
lblock->mIns[ls - 1].mLive |= LIVE_CPU_REG_A;
changed = true; changed = true;
} }
} }
@ -9737,6 +9821,103 @@ bool NativeCodeBasicBlock::FindImmediateStore(int at, int reg, const NativeCodeI
return false; return false;
} }
bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains)
{
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg])
return true;
if (mNumEntries > 1)
return false;
}
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.UsesAddress())
{
if (ins.ChangesAddress())
return false;
return !(ins.mLive & LIVE_MEM);
}
else
return true;
}
else if (ins.mType == ASMIT_JSR)
{
if (ins.mFlags & NCIF_RUNTIME)
{
if (ins.UsesZeroPage(reg))
return false;
}
else
return false;
}
else if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress + 1 == reg))
return false;
else if (ins.ChangesZeroPage(reg))
return true;
else if (ains.MayBeChangedOnAddress(ins))
return false;
at++;
}
if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains))
return false;
if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains)
{
bool changed = false;
if (!mPatched)
{
mPatched = true;
if (at == 0 && !mEntryRequiredRegs[reg])
return false;
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.UsesAddress())
{
assert(!(ins.mLive & LIVE_MEM));
ins.CopyMode(ains);
return true;
}
return false;
}
at++;
}
if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(reg, 0, ains))
changed = true;
if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(reg, 0, ains))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yval) bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yval)
{ {
@ -9744,6 +9925,15 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
{ {
mPatched = true; mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg] && !mEntryRequiredRegs[reg + 1])
return true;
if (mNumEntries > 1)
yval = -1;
}
while (at < mIns.Size()) while (at < mIns.Size())
{ {
NativeCodeInstruction& ins(mIns[at]); NativeCodeInstruction& ins(mIns[at]);
@ -9764,6 +9954,12 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
yval = (yval + 1) & 255; yval = (yval + 1) & 255;
else if (ins.mType == ASMIT_DEY && yval >= 0) else if (ins.mType == ASMIT_DEY && yval >= 0)
yval = (yval - 1) & 255; yval = (yval - 1) & 255;
else if (ins.mType == ASMIT_JSR)
{
if (ins.UsesZeroPage(reg) || ins.UsesZeroPage(reg + 1))
return false;
yval = -1;
}
else if (ins.ChangesYReg()) else if (ins.ChangesYReg())
yval = -1; yval = -1;
@ -9786,6 +9982,8 @@ bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(int reg, int at, int yv
if (!mPatched) if (!mPatched)
{ {
mPatched = true; mPatched = true;
if (at == 0 && !mEntryRequiredRegs[reg] && !mEntryRequiredRegs[reg + 1])
return false;
while (at < mIns.Size()) while (at < mIns.Size())
{ {
@ -10838,6 +11036,10 @@ bool NativeCodeBasicBlock::MoveLoadStoreOutOfXYRangeUp(int at)
return false; return false;
if (mIns[j].ChangesAddress() && mIns[j].SameEffectiveAddress(mIns[at + 1])) if (mIns[j].ChangesAddress() && mIns[j].SameEffectiveAddress(mIns[at + 1]))
return false; return false;
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_X && mIns[j].ChangesXReg())
return false;
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg())
return false;
if (mIns[j].mType == ASMIT_LDA) if (mIns[j].mType == ASMIT_LDA)
{ {
@ -10973,32 +11175,54 @@ bool NativeCodeBasicBlock::MoveStoreXUp(int at)
{ {
bool done = false; bool done = false;
int n = 0, inc = 0;;
int reg = mIns[at].mAddress;
while (at > 0) while (at > 0)
{ {
if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX) if (mIns[at - 1].mType == ASMIT_INX)
return done;
if (mIns[at].mMode == ASMIM_ZERO_PAGE)
{ {
if ((mIns[at - 1].mMode == ASMIM_ZERO_PAGE || mIns[at - 1].mMode == ASMIM_INDIRECT_Y) && mIns[at - 1].mAddress == mIns[at].mAddress) n++;
return done; inc++;
if (mIns[at - 1].mMode == ASMIM_INDIRECT_Y && mIns[at - 1].mAddress + 1 == mIns[at].mAddress) }
return done; else if (mIns[at - 1].mType == ASMIT_DEX)
{
n++;
inc--;
} }
else else
{ {
if (mIns[at - 1].mMode == ASMIM_ABSOLUTE && mIns[at - 1].mLinkerObject == mIns[at].mLinkerObject && mIns[at - 1].mAddress == mIns[at].mAddress) if (mIns[at - 1].mType == ASMIT_LDX || mIns[at - 1].mType == ASMIT_TAX)
return done; return done;
else if ((mIns[at - 1].mMode == ASMIM_ABSOLUTE_X || mIns[at - 1].mMode == ASMIM_ABSOLUTE_Y) && mIns[at - 1].mLinkerObject == mIns[at].mLinkerObject) else if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX)
return done; return done;
else if (mIns[at + n].mMode == ASMIM_ZERO_PAGE)
{
if ((mIns[at - 1].mMode == ASMIM_ZERO_PAGE || mIns[at - 1].mMode == ASMIM_INDIRECT_Y) && mIns[at - 1].mAddress == reg)
return done;
if (mIns[at - 1].mMode == ASMIM_INDIRECT_Y && mIns[at - 1].mAddress + 1 == reg)
return done;
}
else
{
if (mIns[at - 1].mMode == ASMIM_ABSOLUTE && mIns[at - 1].mLinkerObject == mIns[at + n].mLinkerObject && mIns[at - 1].mAddress == mIns[at + n].mAddress)
return done;
else if ((mIns[at - 1].mMode == ASMIM_ABSOLUTE_X || mIns[at - 1].mMode == ASMIM_ABSOLUTE_Y) && mIns[at - 1].mLinkerObject == mIns[at + n].mLinkerObject)
return done;
}
mIns[at].mLive |= mIns[at - 1].mLive;
NativeCodeInstruction ins = mIns[at - 1];
if (ins.mMode == ASMIM_ABSOLUTE_X)
ins.mAddress -= inc;
for (int i = 0; i <= n; i++)
mIns[at - 1 + i] = mIns[at + i];
mIns[at + n] = ins;
done = true;
} }
mIns[at].mLive |= mIns[at - 1].mLive;
NativeCodeInstruction ins = mIns[at - 1];
mIns[at - 1] = mIns[at];
mIns[at] = ins;
at--; at--;
done = true;
} }
return done; return done;
@ -13857,8 +14081,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#if 1 #if 1
for (int i = 0; i + 2 < mIns.Size(); i++) for (int i = 0; i + 2 < mIns.Size(); i++)
{ {
if ((mIns[i + 0].mType == ASMIT_TAX || mIns[i + 0].mType == ASMIT_TAY) && if (mIns[i + 0].mType == ASMIT_TAX &&
mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A)))
{
if (MoveLoadStoreOutOfXYRangeUp(i))
changed = true;
}
else if (
mIns[i + 0].mType == ASMIT_TAY &&
mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A))) mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A)))
{ {
if (MoveLoadStoreOutOfXYRangeUp(i)) if (MoveLoadStoreOutOfXYRangeUp(i))
@ -15790,6 +16022,41 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true; progress = true;
} }
#endif #endif
else if (
mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 2].mAddress == 2)
mIns[i + 2].mType = ASMIT_INX;
else
mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
mIns[i + 3].mType = ASMIT_TXA;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_SEC &&
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 &&
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 2].mAddress == 2)
mIns[i + 2].mType = ASMIT_DEX;
else
mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
mIns[i + 3].mType = ASMIT_TXA;
progress = true;
}
else if ( else if (
mIns[i + 0].mType == ASMIT_TYA && mIns[i + 0].mType == ASMIT_TYA &&
mIns[i + 1].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_CLC &&
@ -16183,6 +16450,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
} }
} }
#endif #endif
if (i + 1 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE &&
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)))
{
proc->ResetPatched();
if (CheckSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i]))
{
proc->ResetPatched();
if (PatchSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i]))
progress = true;
}
}
}
if (i + 5 < mIns.Size()) if (i + 5 < mIns.Size())
{ {
if ( if (
@ -16221,7 +16504,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED; mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); proc->ResetPatched();
progress = PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress); if (PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress))
progress = true;
} }
} }
#endif #endif

View File

@ -84,6 +84,7 @@ public:
bool LoadsAccu(void) const; bool LoadsAccu(void) const;
bool ChangesAccuAndFlag(void) const; bool ChangesAccuAndFlag(void) const;
bool ChangesAddress(void) const; bool ChangesAddress(void) const;
bool UsesAddress(void) const;
bool ChangesAccu(void) const; bool ChangesAccu(void) const;
bool UsesAccu(void) const; bool UsesAccu(void) const;
bool ChangesCarry(void) const; bool ChangesCarry(void) const;
@ -273,6 +274,9 @@ public:
bool CheckGlobalAddressSumYPointer(int reg, int at, int yval); bool CheckGlobalAddressSumYPointer(int reg, int at, int yval);
bool PatchGlobalAddressSumYPointer(int reg, int at, int yval, LinkerObject * lobj, int address); bool PatchGlobalAddressSumYPointer(int reg, int at, int yval, LinkerObject * lobj, int address);
bool CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
}; };
class NativeCodeProcedure class NativeCodeProcedure

View File

@ -330,59 +330,53 @@ struct Enemy
int px; int px;
byte py; byte py;
sbyte dx; sbyte dx;
byte n;
} enemies[5]; } enemies[5];
int spx = 40; int spx = 40;
int vpx = 16; int vpx = 16;
int ax = 0; int ax = 0;
char spy = 100; char spy = 100;
char fdelay = 0; char fdelay = 0;
char edelay = 5;
char ecount = 0;
void enemies_move(void) void enemies_move(void)
{ {
bool elive = false;
for(char i=0; i<5; i++) for(char i=0; i<5; i++)
{ {
if (enemies[i].n) if (enemies[i].dx)
{ {
enemies[i].n--;
enemies[i].px += enemies[i].dx; enemies[i].px += enemies[i].dx;
int rx = enemies[i].px - spx; int rx = enemies[i].px - spx;
if (enemies[i].dx < 0) if (rx < -192 || rx >= 480)
{ {
if (rx < -24) enemies[i].dx = 0;
enemies[i].n = 0; ecount--;
}
else
{
if (rx > 320)
enemies[i].n = 0;
} }
spr_move(2 + i, rx + 24, enemies[i].py + 50); spr_move(2 + i, rx + 24, enemies[i].py + 50);
elive = true;
} }
} }
}
if (!elive) void enemies_spwan(void)
{ {
for(char i=0; i<5; i++) char u = rand();
{
sbyte v = 4 + (rand() & 1);
enemies[i].py = 20 + 30 * i;
enemies[i].dx = vpx < 0 ? v : -v;
enemies[i].px = (vpx < 0 ? spx - 56 : spx + 320) + (rand() & 31);
enemies[i].n = 100;
int rx = enemies[i].px - spx; char e = ecount;
spr_set(2 + i, true, rx + 24, enemies[i].py + 50, 96, VCOL_YELLOW, true, false, false); __assume(e < 5);
}
} sbyte v = 1 + (u & 3);
enemies[ecount].py = 20 + 30 * e;
enemies[ecount].dx = vpx < 0 ? v : -v;
enemies[ecount].px = (vpx < 0 ? spx - 56 : spx + 320) + ((u >> 1) & 31);
int rx = enemies[ecount].px - spx;
spr_set(2 + ecount, true, rx + 24, enemies[ecount].py + 50, vpx < 0 ? 97 : 96, VCOL_YELLOW, true, false, false);
ecount++;
} }
int main(void) int main(void)
@ -430,7 +424,7 @@ int main(void)
spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false); spr_set(0, true, 160, 100, 64, VCOL_BLUE, true, false, false);
spr_set(7, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false); spr_set(7, true, 160, 100, 64 + 16, VCOL_MED_GREY, true, false, false);
vic.spr_priority = 2; vic.spr_priority = 0x80;
vpx = 2; vpx = 2;
for(;;) for(;;)
@ -497,15 +491,23 @@ int main(void)
vic.color_border++; vic.color_border++;
vic_waitLine(82); vic_waitLine(82);
vic.color_border++; vic.color_border++;
tiles_draw(spx); tiles_draw(spx & 4095);
vic.color_border--; vic.color_border--;
enemies_move(); if (edelay)
{
edelay--;
if (edelay < 5)
enemies_spwan();
}
else
{
enemies_move();
if (!ecount)
edelay = 64 + (rand() & 63);
}
vic.color_border--; vic.color_border--;
spx += vpx >> 1; spx += vpx >> 2;
spx &= 4095;
} }
return 0; return 0;