Replace JMP with branch when possible
This commit is contained in:
parent
2a815a9709
commit
9ec2b4fdef
|
@ -79,6 +79,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -5463,6 +5463,20 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
|
||||||
{
|
{
|
||||||
InterInstruction* ins = mInstructions[i];
|
InterInstruction* ins = mInstructions[i];
|
||||||
|
|
||||||
|
// Normalize kommutative operands if one is constant
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (ins->mCode == IC_BINARY_OPERATOR &&
|
||||||
|
(ins->mOperator == IA_MUL || ins->mOperator == IA_ADD || ins->mOperator == IA_AND || ins->mOperator == IA_OR || ins->mOperator == IA_XOR) &&
|
||||||
|
ltvalue[ins->mSrc[1].mTemp] && ltvalue[ins->mSrc[0].mTemp] &&
|
||||||
|
ltvalue[ins->mSrc[1].mTemp]->mCode == IC_CONSTANT && ltvalue[ins->mSrc[0].mTemp]->mCode != IC_CONSTANT)
|
||||||
|
{
|
||||||
|
InterOperand op = ins->mSrc[0];
|
||||||
|
ins->mSrc[0] = ins->mSrc[1];
|
||||||
|
ins->mSrc[1] = op;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_MUL && ins->mDst.mType == IT_INT16 && spareTemps + 1 < tvalid.Size())
|
if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_MUL && ins->mDst.mType == IT_INT16 && spareTemps + 1 < tvalid.Size())
|
||||||
{
|
{
|
||||||
|
@ -5528,6 +5542,66 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
|
||||||
ins->mSrc[0].mTemp = cai->mDst.mTemp;
|
ins->mSrc[0].mTemp = cai->mDst.mTemp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mi0 && mi1 && mi0->mCode == IC_CONSTANT && mi1->mCode == IC_BINARY_OPERATOR && mi1->mOperator == IA_ADD)
|
||||||
|
{
|
||||||
|
InterInstruction* ai0 = ltvalue[mi1->mSrc[0].mTemp], * ai1 = ltvalue[mi1->mSrc[1].mTemp];
|
||||||
|
if (ai0 && ai0->mCode == IC_CONSTANT)
|
||||||
|
{
|
||||||
|
InterInstruction* nai = new InterInstruction();
|
||||||
|
nai->mCode = IC_BINARY_OPERATOR;
|
||||||
|
nai->mOperator = IA_MUL;
|
||||||
|
nai->mSrc[0].mTemp = mi1->mSrc[1].mTemp;
|
||||||
|
nai->mSrc[0].mType = IT_INT16;
|
||||||
|
nai->mSrc[1].mTemp = ins->mSrc[0].mTemp;
|
||||||
|
nai->mSrc[1].mType = IT_INT16;
|
||||||
|
nai->mDst.mTemp = spareTemps++;
|
||||||
|
nai->mDst.mType = IT_INT16;
|
||||||
|
mInstructions.Insert(i, nai);
|
||||||
|
|
||||||
|
ltvalue[nai->mDst.mTemp] = nullptr;
|
||||||
|
|
||||||
|
InterInstruction* cai = new InterInstruction();
|
||||||
|
cai->mCode = IC_CONSTANT;
|
||||||
|
cai->mDst.mTemp = spareTemps++;
|
||||||
|
cai->mDst.mType = IT_INT16;
|
||||||
|
cai->mConst.mIntConst = ai0->mConst.mIntConst * mi0->mConst.mIntConst;
|
||||||
|
mInstructions.Insert(i, cai);
|
||||||
|
|
||||||
|
ltvalue[cai->mDst.mTemp] = nullptr;
|
||||||
|
|
||||||
|
ins->mOperator = IA_ADD;
|
||||||
|
ins->mSrc[0].mTemp = nai->mDst.mTemp;
|
||||||
|
ins->mSrc[1].mTemp = cai->mDst.mTemp;
|
||||||
|
}
|
||||||
|
else if (ai1 && ai1->mCode == IC_CONSTANT)
|
||||||
|
{
|
||||||
|
InterInstruction* nai = new InterInstruction();
|
||||||
|
nai->mCode = IC_BINARY_OPERATOR;
|
||||||
|
nai->mOperator = IA_MUL;
|
||||||
|
nai->mSrc[0].mTemp = mi1->mSrc[0].mTemp;
|
||||||
|
nai->mSrc[0].mType = IT_INT16;
|
||||||
|
nai->mSrc[1].mTemp = ins->mSrc[0].mTemp;
|
||||||
|
nai->mSrc[1].mType = IT_INT16;
|
||||||
|
nai->mDst.mTemp = spareTemps++;
|
||||||
|
nai->mDst.mType = IT_INT16;
|
||||||
|
mInstructions.Insert(i, nai);
|
||||||
|
|
||||||
|
ltvalue[nai->mDst.mTemp] = nullptr;
|
||||||
|
|
||||||
|
InterInstruction* cai = new InterInstruction();
|
||||||
|
cai->mCode = IC_CONSTANT;
|
||||||
|
cai->mDst.mTemp = spareTemps++;
|
||||||
|
cai->mDst.mType = IT_INT16;
|
||||||
|
cai->mConst.mIntConst = ai1->mConst.mIntConst * mi0->mConst.mIntConst;
|
||||||
|
mInstructions.Insert(i, cai);
|
||||||
|
|
||||||
|
ltvalue[cai->mDst.mTemp] = nullptr;
|
||||||
|
|
||||||
|
ins->mOperator = IA_ADD;
|
||||||
|
ins->mSrc[0].mTemp = nai->mDst.mTemp;
|
||||||
|
ins->mSrc[1].mTemp = cai->mDst.mTemp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
|
|
|
@ -666,6 +666,44 @@ void NativeCodeInstruction::ReplaceYRegWithXReg(void)
|
||||||
mLive |= LIVE_CPU_REG_Y;
|
mLive |= LIVE_CPU_REG_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeInstruction::ReplaceXRegWithYReg(void)
|
||||||
|
{
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case ASMIT_LDX:
|
||||||
|
mType = ASMIT_LDY;
|
||||||
|
break;
|
||||||
|
case ASMIT_STX:
|
||||||
|
mType = ASMIT_STY;
|
||||||
|
break;
|
||||||
|
case ASMIT_CPX:
|
||||||
|
mType = ASMIT_CPY;
|
||||||
|
break;
|
||||||
|
case ASMIT_TXA:
|
||||||
|
mType = ASMIT_TYA;
|
||||||
|
break;
|
||||||
|
case ASMIT_TAX:
|
||||||
|
mType = ASMIT_TAY;
|
||||||
|
break;
|
||||||
|
case ASMIT_INX:
|
||||||
|
mType = ASMIT_INY;
|
||||||
|
break;
|
||||||
|
case ASMIT_DEX:
|
||||||
|
mType = ASMIT_DEY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (mMode == ASMIM_ABSOLUTE_X)
|
||||||
|
{
|
||||||
|
assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_Y));
|
||||||
|
mMode = ASMIM_ABSOLUTE_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mLive & LIVE_CPU_REG_Y)
|
||||||
|
mLive |= LIVE_CPU_REG_X;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeInstruction::ChangesYReg(void) const
|
bool NativeCodeInstruction::ChangesYReg(void) const
|
||||||
{
|
{
|
||||||
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR;
|
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR;
|
||||||
|
@ -2914,34 +2952,75 @@ static AsmInsType TransposeBranchCondition(AsmInsType code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target)
|
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int offset)
|
||||||
{
|
{
|
||||||
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
|
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
|
||||||
{
|
{
|
||||||
PutByte(0x60);
|
PutByte(0x60);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
#if 1
|
||||||
|
else if (offset >= -126 && offset <= 129)
|
||||||
{
|
{
|
||||||
PutByte(0x4c);
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
if (mNDataSet.mRegs[CPU_REG_C].mValue)
|
||||||
|
PutByte(AsmInsOpcodes[ASMIT_BCS][ASMIM_RELATIVE]);
|
||||||
|
else
|
||||||
|
PutByte(AsmInsOpcodes[ASMIT_BCC][ASMIM_RELATIVE]);
|
||||||
|
|
||||||
LinkerReference rl;
|
PutByte(offset - 2);
|
||||||
rl.mObject = nullptr;
|
return 2;
|
||||||
rl.mOffset = mCode.Size();
|
}
|
||||||
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
else if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
rl.mRefObject = nullptr;
|
{
|
||||||
rl.mRefOffset = target->mOffset;
|
if (mNDataSet.mRegs[CPU_REG_Z].mValue)
|
||||||
mRelocations.Push(rl);
|
PutByte(AsmInsOpcodes[ASMIT_BNE][ASMIM_RELATIVE]);
|
||||||
|
else
|
||||||
|
PutByte(AsmInsOpcodes[ASMIT_BEQ][ASMIM_RELATIVE]);
|
||||||
|
|
||||||
PutWord(0);
|
PutByte(offset - 2);
|
||||||
return 3;
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
PutByte(0x4c);
|
||||||
|
|
||||||
|
LinkerReference rl;
|
||||||
|
rl.mObject = nullptr;
|
||||||
|
rl.mOffset = mCode.Size();
|
||||||
|
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
||||||
|
rl.mRefObject = nullptr;
|
||||||
|
rl.mRefOffset = target->mOffset;
|
||||||
|
mRelocations.Push(rl);
|
||||||
|
|
||||||
|
PutWord(0);
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target)
|
int NativeCodeBasicBlock::BranchByteSize(int from, int to)
|
||||||
|
{
|
||||||
|
if (to - from >= -126 && to - from <= 129)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int offset)
|
||||||
{
|
{
|
||||||
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
|
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
|
||||||
return 1;
|
return 1;
|
||||||
|
#if 1
|
||||||
|
else if (offset >= -126 && offset <= 129)
|
||||||
|
{
|
||||||
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
||||||
|
return 2;
|
||||||
|
else if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
@ -9112,6 +9191,74 @@ bool NativeCodeBasicBlock::ReduceLocalYPressure(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::ReplaceXRegWithYReg(int start, int end)
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
ins.ReplaceXRegWithYReg();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::ReduceLocalXPressure(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
|
||||||
|
while (start < mIns.Size())
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& ins(mIns[start]);
|
||||||
|
|
||||||
|
if ((ins.mType == ASMIT_LDX || ins.mType == ASMIT_TAX) && ins.mMode != ASMIM_INDIRECT_Y && ins.mMode != ASMIM_ABSOLUTE_Y && !(ins.mLive & LIVE_CPU_REG_Y))
|
||||||
|
{
|
||||||
|
int end = start + 1;
|
||||||
|
while (end < mIns.Size())
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& eins(mIns[end]);
|
||||||
|
if (eins.mType == ASMIT_LDX || eins.mType == ASMIT_TAX)
|
||||||
|
{
|
||||||
|
ReplaceXRegWithYReg(start, end);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (eins.ChangesYReg() || (eins.mMode == ASMIM_ABSOLUTE_X && !HasAsmInstructionMode(eins.mType, ASMIM_ABSOLUTE_Y)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!(eins.mLive & LIVE_CPU_REG_X))
|
||||||
|
{
|
||||||
|
end++;
|
||||||
|
ReplaceXRegWithYReg(start, end);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->ReduceLocalXPressure())
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (mFalseJump && mFalseJump->ReduceLocalXPressure())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::LocalRegisterXYMap(void)
|
bool NativeCodeBasicBlock::LocalRegisterXYMap(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -9919,7 +10066,7 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const Nativ
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int at, int yval)
|
bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index, int at, int yval)
|
||||||
{
|
{
|
||||||
if (!mPatched)
|
if (!mPatched)
|
||||||
{
|
{
|
||||||
|
@ -9938,7 +10085,7 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int at, in
|
||||||
{
|
{
|
||||||
NativeCodeInstruction& ins(mIns[at]);
|
NativeCodeInstruction& ins(mIns[at]);
|
||||||
|
|
||||||
if (ins.mMode == ASMIM_ZERO_PAGE && (ins.mAddress == reg || ins.mAddress == reg + 1))
|
if (ins.mMode == ASMIM_ZERO_PAGE && (ins.mAddress == reg || ins.mAddress == reg + 1 || ins.mAddress == index))
|
||||||
return false;
|
return false;
|
||||||
else if (ins.mMode == ASMIM_INDIRECT_Y && ins.mAddress == reg)
|
else if (ins.mMode == ASMIM_INDIRECT_Y && ins.mAddress == reg)
|
||||||
{
|
{
|
||||||
|
@ -9960,7 +10107,7 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int at, in
|
||||||
return false;
|
return false;
|
||||||
yval = -1;
|
yval = -1;
|
||||||
}
|
}
|
||||||
else if (ins.ChangesZeroPage(base) || ins.ChangesZeroPage(base + 1))
|
else if (ins.ChangesZeroPage(base) || ins.ChangesZeroPage(base + 1) || ins.ChangesZeroPage(index))
|
||||||
return false;
|
return false;
|
||||||
else if (ins.ChangesYReg())
|
else if (ins.ChangesYReg())
|
||||||
yval = -1;
|
yval = -1;
|
||||||
|
@ -9968,16 +10115,16 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int at, in
|
||||||
at++;
|
at++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(reg, base, 0, yval))
|
if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(reg, base, index, 0, yval))
|
||||||
return false;
|
return false;
|
||||||
if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(reg, base, 0, yval))
|
if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(reg, base, index, 0, yval))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int at, int yval)
|
bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int index, int at, int yval)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
@ -10003,7 +10150,7 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int at, in
|
||||||
|
|
||||||
if (ins.mLive & LIVE_CPU_REG_Y)
|
if (ins.mLive & LIVE_CPU_REG_Y)
|
||||||
mIns.Insert(at + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, yval));
|
mIns.Insert(at + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, yval));
|
||||||
mIns.Insert(at, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, reg));
|
mIns.Insert(at, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, index));
|
||||||
at++;
|
at++;
|
||||||
for (int i = 0; i < yval; i++)
|
for (int i = 0; i < yval; i++)
|
||||||
{
|
{
|
||||||
|
@ -10028,9 +10175,9 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int at, in
|
||||||
at++;
|
at++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && mTrueJump->PatchForwardSumYPointer(reg, base, 0, yval))
|
if (mTrueJump && mTrueJump->PatchForwardSumYPointer(reg, base, index, 0, yval))
|
||||||
changed = true;
|
changed = true;
|
||||||
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(reg, base, 0, yval))
|
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(reg, base, index, 0, yval))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14747,6 +14894,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mType == ASMIT_TXA &&
|
mIns[i + 0].mType == ASMIT_TXA &&
|
||||||
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
||||||
{
|
{
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_X;
|
||||||
mIns[i + 1].mType = ASMIT_STX;
|
mIns[i + 1].mType = ASMIT_STX;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14755,6 +14903,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mType == ASMIT_TYA &&
|
mIns[i + 0].mType == ASMIT_TYA &&
|
||||||
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
||||||
{
|
{
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
|
||||||
mIns[i + 1].mType = ASMIT_STY;
|
mIns[i + 1].mType = ASMIT_STY;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14762,6 +14911,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mType == ASMIT_TAX &&
|
mIns[i + 0].mType == ASMIT_TAX &&
|
||||||
mIns[i + 1].mType == ASMIT_STX && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
mIns[i + 1].mType == ASMIT_STX && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
||||||
{
|
{
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[i + 1].mType = ASMIT_STA;
|
mIns[i + 1].mType = ASMIT_STA;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14769,6 +14919,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mType == ASMIT_TAY &&
|
mIns[i + 0].mType == ASMIT_TAY &&
|
||||||
mIns[i + 1].mType == ASMIT_STY && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
mIns[i + 1].mType == ASMIT_STY && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
||||||
{
|
{
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
mIns[i + 1].mType = ASMIT_STA;
|
mIns[i + 1].mType = ASMIT_STA;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14871,7 +15022,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !mIns[i + 1].SameEffectiveAddress(mIns[i + 0]))
|
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !mIns[i + 1].SameEffectiveAddress(mIns[i + 0]))
|
||||||
{
|
{
|
||||||
NativeCodeInstruction ins = mIns[i + 0];
|
NativeCodeInstruction ins = mIns[i + 0];
|
||||||
mIns[i + 0] = mIns[i + 1];
|
mIns[i + 0] = mIns[i + 1]; mIns[i + 0].mLive |= ins.mLive;
|
||||||
mIns[i + 1] = ins;
|
mIns[i + 1] = ins;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14982,7 +15133,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mFlags = iins->mFlags;
|
mIns[i + 0].mFlags = iins->mFlags;
|
||||||
|
|
||||||
if (!(flags & LIVE_CPU_REG_Y) && (flags & LIVE_CPU_REG_X))
|
if (!(flags & LIVE_CPU_REG_Y) && (flags & LIVE_CPU_REG_X))
|
||||||
mIns[i + 0].mType == ASMIT_LDX;
|
mIns[i + 0].mType = ASMIT_LDX;
|
||||||
}
|
}
|
||||||
else if (iins->mAddress == sreg)
|
else if (iins->mAddress == sreg)
|
||||||
{
|
{
|
||||||
|
@ -15009,7 +15160,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 0].mAddress = iins->mAddress;
|
mIns[i + 0].mAddress = iins->mAddress;
|
||||||
|
|
||||||
if (!(flags & LIVE_CPU_REG_Y) && (flags & LIVE_CPU_REG_X))
|
if (!(flags & LIVE_CPU_REG_Y) && (flags & LIVE_CPU_REG_X))
|
||||||
mIns[i + 0].mType == ASMIT_LDX;
|
mIns[i + 0].mType = ASMIT_LDX;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = true;
|
progress = true;
|
||||||
|
@ -15768,6 +15919,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= mIns[i + 2].mLive;
|
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= mIns[i + 2].mLive;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_LDX &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STX &&
|
||||||
|
mIns[i + 2].mType == ASMIT_TXA && !(mIns[i + 2].mLive & LIVE_CPU_REG_X))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_LDY &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STY &&
|
||||||
|
mIns[i + 2].mType == ASMIT_TYA && !(mIns[i + 2].mLive & LIVE_CPU_REG_Y))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (
|
if (
|
||||||
|
@ -15929,6 +16101,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 3].mType == ASMIT_STX && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
|
mIns[i + 3].mType == ASMIT_STX && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||||
!mIns[i + 1].ChangesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].UsesZeroPage(mIns[i + 3].mAddress))
|
!mIns[i + 1].ChangesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].UsesZeroPage(mIns[i + 3].mAddress))
|
||||||
{
|
{
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
|
||||||
mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 3].mAddress));
|
mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 3].mAddress));
|
||||||
|
|
||||||
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||||
|
@ -16671,7 +16845,7 @@ 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;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
if (mIns[i + 0].mType == ASMIT_CLC &&
|
if (mIns[i + 0].mType == ASMIT_CLC &&
|
||||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
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 + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
@ -16682,7 +16856,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
|
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
|
||||||
{
|
{
|
||||||
proc->ResetPatched();
|
proc->ResetPatched();
|
||||||
if (CheckForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, i + 7, -1))
|
if (CheckForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
|
||||||
{
|
{
|
||||||
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
@ -16693,11 +16867,38 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
|
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
proc->ResetPatched();
|
proc->ResetPatched();
|
||||||
if (PatchForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, i + 7, -1))
|
if (PatchForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
if (
|
||||||
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[i + 1].mType == ASMIT_CLC &&
|
||||||
|
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].mAddress != mIns[i + 0].mAddress &&
|
||||||
|
mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 2].mAddress + 1 &&
|
||||||
|
mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mAddress == 0 &&
|
||||||
|
mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 3].mAddress + 1 &&
|
||||||
|
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
|
||||||
|
{
|
||||||
|
proc->ResetPatched();
|
||||||
|
if (CheckForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
|
||||||
|
{
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
|
proc->ResetPatched();
|
||||||
|
if (PatchForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -16920,14 +17121,6 @@ void NativeCodeBasicBlock::Close(NativeCodeBasicBlock* trueJump, NativeCodeBasic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int BranchByteSize(int from, int to)
|
|
||||||
{
|
|
||||||
if (to - from >= -126 && to - from <= 129)
|
|
||||||
return 2;
|
|
||||||
else
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
||||||
{
|
{
|
||||||
if (mBypassed)
|
if (mBypassed)
|
||||||
|
@ -17065,13 +17258,13 @@ bool NativeCodeBasicBlock::CalculateOffset(int& total)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
total += BranchByteSize(total, mTrueJump->mOffset);
|
total += BranchByteSize(total, mTrueJump->mOffset);
|
||||||
total += JumpByteSize(mFalseJump);
|
total += JumpByteSize(mFalseJump, mFalseJump->mOffset - total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mTrueJump)
|
else if (mTrueJump)
|
||||||
{
|
{
|
||||||
if (mTrueJump->mPlace != mPlace + 1)
|
if (mTrueJump->mPlace != mPlace + 1)
|
||||||
total += JumpByteSize(mTrueJump);
|
total += JumpByteSize(mTrueJump, mTrueJump->mOffset - total);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOffset + mSize != total)
|
if (mOffset + mSize != total)
|
||||||
|
@ -17100,13 +17293,13 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
end += PutBranch(proc, mBranch, mTrueJump->mOffset - end);
|
end += PutBranch(proc, mBranch, mTrueJump->mOffset - end);
|
||||||
end += PutJump(proc, mFalseJump);
|
end += PutJump(proc, mFalseJump, mFalseJump->mOffset - end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mTrueJump)
|
else if (mTrueJump)
|
||||||
{
|
{
|
||||||
if (mTrueJump->mPlace != mPlace + 1)
|
if (mTrueJump->mPlace != mPlace + 1)
|
||||||
end += PutJump(proc, mTrueJump);
|
end += PutJump(proc, mTrueJump, mTrueJump->mOffset - end);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(end == next);
|
assert(end == next);
|
||||||
|
@ -17951,11 +18144,12 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
if (step == 4)
|
if (step == 4 || step == 5)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
#if 1
|
#if 1
|
||||||
int xregs[256], yregs[256];
|
int xregs[256], yregs[256];
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
xregs[i] = yregs[i] = 0;
|
xregs[i] = yregs[i] = 0;
|
||||||
|
|
||||||
|
@ -17983,6 +18177,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->GlobalRegisterXYCheck(xregs, yregs);
|
mEntryBlock->GlobalRegisterXYCheck(xregs, yregs);
|
||||||
|
|
||||||
if (xregs[0] >= 0)
|
if (xregs[0] >= 0)
|
||||||
{
|
{
|
||||||
int j = 1;
|
int j = 1;
|
||||||
|
@ -18019,9 +18214,17 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
#endif
|
#endif
|
||||||
if (!changed)
|
if (!changed)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
if (step == 4)
|
||||||
if (mEntryBlock->LocalRegisterXYMap())
|
{
|
||||||
changed = true;
|
ResetVisited();
|
||||||
|
mEntryBlock->ReduceLocalXPressure();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->LocalRegisterXYMap())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -18036,7 +18239,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
changed = true;
|
changed = true;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (!changed && step < 5)
|
if (!changed && step < 6)
|
||||||
{
|
{
|
||||||
step++;
|
step++;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
bool IsShift(void) const;
|
bool IsShift(void) const;
|
||||||
|
|
||||||
void ReplaceYRegWithXReg(void);
|
void ReplaceYRegWithXReg(void);
|
||||||
|
void ReplaceXRegWithYReg(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeCodeBasicBlock
|
class NativeCodeBasicBlock
|
||||||
|
@ -131,8 +132,9 @@ public:
|
||||||
NativeRegisterDataSet mDataSet, mNDataSet;
|
NativeRegisterDataSet mDataSet, mNDataSet;
|
||||||
|
|
||||||
int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
|
int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
|
||||||
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target);
|
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int offset);
|
||||||
int JumpByteSize(NativeCodeBasicBlock * target);
|
int JumpByteSize(NativeCodeBasicBlock * target, int offset);
|
||||||
|
int BranchByteSize(int from, int to);
|
||||||
|
|
||||||
NativeCodeBasicBlock* BypassEmptyBlocks(void);
|
NativeCodeBasicBlock* BypassEmptyBlocks(void);
|
||||||
|
|
||||||
|
@ -237,6 +239,7 @@ public:
|
||||||
bool ReverseLoadCommutativeOpUp(int aload, int aop);
|
bool ReverseLoadCommutativeOpUp(int aload, int aop);
|
||||||
bool ReplaceZeroPageUp(int at);
|
bool ReplaceZeroPageUp(int at);
|
||||||
bool ReplaceYRegWithXReg(int start, int end);
|
bool ReplaceYRegWithXReg(int start, int end);
|
||||||
|
bool ReplaceXRegWithYReg(int start, int end);
|
||||||
|
|
||||||
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
bool FindImmediateStore(int at, int reg, const NativeCodeInstruction*& ains);
|
||||||
|
|
||||||
|
@ -271,6 +274,7 @@ public:
|
||||||
void GlobalRegisterYMap(int reg);
|
void GlobalRegisterYMap(int reg);
|
||||||
bool LocalRegisterXYMap(void);
|
bool LocalRegisterXYMap(void);
|
||||||
bool ReduceLocalYPressure(void);
|
bool ReduceLocalYPressure(void);
|
||||||
|
bool ReduceLocalXPressure(void);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -278,8 +282,8 @@ public:
|
||||||
bool CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
|
bool CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
|
||||||
bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
|
bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
|
||||||
|
|
||||||
bool CheckForwardSumYPointer(int reg, int base, int at, int yval);
|
bool CheckForwardSumYPointer(int reg, int base, int index, int at, int yval);
|
||||||
bool PatchForwardSumYPointer(int reg, int base, int at, int yval);
|
bool PatchForwardSumYPointer(int reg, int base, int index, int at, int yval);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeCodeProcedure
|
class NativeCodeProcedure
|
||||||
|
|
|
@ -171,12 +171,23 @@ void tiles_draw1(char * dp, char * tm)
|
||||||
|
|
||||||
struct Shot
|
struct Shot
|
||||||
{
|
{
|
||||||
byte ty, x, ry, n;
|
byte ty, x, ry, n;
|
||||||
sbyte dx;
|
sbyte dx;
|
||||||
|
Shot * next;
|
||||||
} shots[18];
|
} shots[18];
|
||||||
|
|
||||||
Shot * firstShot;
|
Shot * freeShot;
|
||||||
Shot * lastShot;
|
|
||||||
|
void shot_init(void)
|
||||||
|
{
|
||||||
|
shots[0].next = shots;
|
||||||
|
shots[0].ty = 6;
|
||||||
|
|
||||||
|
freeShot = shots + 1;
|
||||||
|
for(char i=1; i<17; i++)
|
||||||
|
shots[i].next = shots + i + 1;
|
||||||
|
shots[17].next = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline void shot_draw(char * dp, char i, char xp, char yp)
|
inline void shot_draw(char * dp, char i, char xp, char yp)
|
||||||
{
|
{
|
||||||
|
@ -202,16 +213,14 @@ void shot_add(int dx, int sy)
|
||||||
char ey = (py >> 3) & 3;
|
char ey = (py >> 3) & 3;
|
||||||
char ry = py & 7;
|
char ry = py & 7;
|
||||||
|
|
||||||
Shot * s = lastShot - 1;
|
Shot * s = freeShot;
|
||||||
while (s->ty > gy)
|
freeShot = s->next;
|
||||||
{
|
|
||||||
s[1] = s[0];
|
|
||||||
s--;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
|
|
||||||
lastShot++;
|
Shot * p = shots;
|
||||||
lastShot->ty = 6;
|
while (p->next->ty < gy)
|
||||||
|
p = p->next;
|
||||||
|
s->next = p->next;
|
||||||
|
p->next = s;
|
||||||
|
|
||||||
s->ty = gy;
|
s->ty = gy;
|
||||||
s->ry = ry;
|
s->ry = ry;
|
||||||
|
@ -241,7 +250,7 @@ void tiles_draw(unsigned x)
|
||||||
char yl = 0;
|
char yl = 0;
|
||||||
char ci = 0;
|
char ci = 0;
|
||||||
|
|
||||||
Shot * ss = firstShot, * ts = firstShot;
|
Shot * ps = shots;
|
||||||
|
|
||||||
for(int iy=0; iy<5; iy++)
|
for(int iy=0; iy<5; iy++)
|
||||||
{
|
{
|
||||||
|
@ -303,26 +312,27 @@ void tiles_draw(unsigned x)
|
||||||
dp[k] = 0xf8;
|
dp[k] = 0xf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shot *ss = ps->next;
|
||||||
|
|
||||||
while (ss->ty == iy)
|
while (ss->ty == iy)
|
||||||
{
|
{
|
||||||
ss->x += ss->dx;
|
ss->x += ss->dx;
|
||||||
ss->n--;
|
ss->n--;
|
||||||
shot_draw(dp, ci++, ss->x, ss->ry);
|
shot_draw(dp, ci++, ss->x, ss->ry);
|
||||||
if (ss->n)
|
if (ss->n)
|
||||||
|
ps = ss;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (ss != ts)
|
ps->next = ss->next;
|
||||||
*ts = *ss;
|
ss->next = freeShot;
|
||||||
ts++;
|
freeShot = ss;
|
||||||
}
|
}
|
||||||
ss++;
|
ss = ps->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
yl += 4;
|
yl += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastShot = ts;
|
|
||||||
lastShot->ty = 6;
|
|
||||||
|
|
||||||
Font[248 * 8 + 2] = ~(1 << xs);
|
Font[248 * 8 + 2] = ~(1 << xs);
|
||||||
|
|
||||||
vic.ctrl2 = VIC_CTRL2_MCM + xs;
|
vic.ctrl2 = VIC_CTRL2_MCM + xs;
|
||||||
|
@ -336,8 +346,8 @@ struct Enemy
|
||||||
} enemies[5];
|
} enemies[5];
|
||||||
|
|
||||||
int spx = 40;
|
int spx = 40;
|
||||||
int vpx = 16;
|
sbyte vpx = 16;
|
||||||
int ax = 0;
|
sbyte ax = 0;
|
||||||
char spy = 100;
|
char spy = 100;
|
||||||
char fdelay = 0;
|
char fdelay = 0;
|
||||||
char edelay = 5;
|
char edelay = 5;
|
||||||
|
@ -363,7 +373,7 @@ void enemies_move(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enemies_spwan(void)
|
void enemies_spawn(void)
|
||||||
{
|
{
|
||||||
char u = rand();
|
char u = rand();
|
||||||
|
|
||||||
|
@ -420,10 +430,7 @@ int main(void)
|
||||||
for(int i=0; i<24; i++)
|
for(int i=0; i<24; i++)
|
||||||
stars[i] = rand() % 40 + 40 * (i & 3);
|
stars[i] = rand() % 40 + 40 * (i & 3);
|
||||||
|
|
||||||
shots[0].ty = 0;
|
shot_init();
|
||||||
firstShot = shots + 1;
|
|
||||||
lastShot = firstShot;
|
|
||||||
lastShot->ty = 6;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -500,7 +507,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
edelay--;
|
edelay--;
|
||||||
if (edelay < 5)
|
if (edelay < 5)
|
||||||
enemies_spwan();
|
enemies_spawn();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue