Optimize float native code size

This commit is contained in:
drmortalwombat 2021-12-19 16:53:12 +01:00
parent 6d716b9478
commit 4a9c662cc9
7 changed files with 273 additions and 61 deletions

View File

@ -18,7 +18,7 @@ int main(void)
#assign ni ni + 1 #assign ni ni + 1
#until ni == 200 #until ni == 200
int asum = 0, bsum = 0, csum; int asum = 0, bsum = 0, csum = 0;
for(int i=0; i<200; i++) for(int i=0; i<200; i++)
{ {
asum += a[i]; asum += a[i];

View File

@ -2435,6 +2435,7 @@ split_exp:
lda (ip), y lda (ip), y
iny iny
tax tax
split_xexp:
lda $00, x lda $00, x
sta tmp + 0 sta tmp + 0
lda $01, x lda $01, x
@ -3424,6 +3425,7 @@ fru3:
#pragma runtime(fsplita, freg.split_aexp) #pragma runtime(fsplita, freg.split_aexp)
#pragma runtime(fsplitt, freg.split_texp) #pragma runtime(fsplitt, freg.split_texp)
#pragma runtime(fsplitx, freg.split_xexp)
#pragma runtime(fmergea, freg.merge_aexp) #pragma runtime(fmergea, freg.merge_aexp)
#pragma runtime(faddsub, faddsub) #pragma runtime(faddsub, faddsub)
#pragma runtime(fmul, fmul) #pragma runtime(fmul, fmul)

View File

@ -191,6 +191,7 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("mul16by8")); RegisterRuntime(loc, Ident::Unique("mul16by8"));
RegisterRuntime(loc, Ident::Unique("fsplitt")); RegisterRuntime(loc, Ident::Unique("fsplitt"));
RegisterRuntime(loc, Ident::Unique("fsplitx"));
RegisterRuntime(loc, Ident::Unique("fsplita")); RegisterRuntime(loc, Ident::Unique("fsplita"));
RegisterRuntime(loc, Ident::Unique("faddsub")); RegisterRuntime(loc, Ident::Unique("faddsub"));
RegisterRuntime(loc, Ident::Unique("fmul")); RegisterRuntime(loc, Ident::Unique("fmul"));

View File

@ -4425,6 +4425,18 @@ static bool CanBypass(const InterInstruction* lins, const InterInstruction* bins
return true; return true;
} }
static bool IsChained(const InterInstruction* ins, const InterInstruction* nins)
{
if (ins->mDst.mTemp >= 0)
{
for (int i = 0; i < nins->mNumOperands; i++)
if (ins->mDst.mTemp == nins->mSrc[i].mTemp)
return true;
}
return false;
}
static bool CanBypassStore(const InterInstruction * sins, const InterInstruction * bins) static bool CanBypassStore(const InterInstruction * sins, const InterInstruction * bins)
{ {
if (bins->mCode == IC_COPY || bins->mCode == IC_STRCPY || bins->mCode == IC_PUSH_FRAME) if (bins->mCode == IC_COPY || bins->mCode == IC_STRCPY || bins->mCode == IC_PUSH_FRAME)
@ -4892,8 +4904,8 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
#if 1 #if 1
while (i >= 0) while (i >= 0)
{ {
// move loads down // move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD) if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8))
{ {
InterInstruction * ins(mInstructions[i]); InterInstruction * ins(mInstructions[i]);
int j = i; int j = i;
@ -4909,7 +4921,7 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
{ {
InterInstruction* ins(mInstructions[i]); InterInstruction* ins(mInstructions[i]);
int j = i; int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1])) while (j < limit && CanBypass(ins, mInstructions[j + 1]) && !(j + 2 < mInstructions.Size() && IsChained(mInstructions[j + 1], mInstructions[j + 2])))
{ {
mInstructions[j] = mInstructions[j + 1]; mInstructions[j] = mInstructions[j + 1];
j++; j++;

View File

@ -120,8 +120,8 @@ void NativeRegisterDataSet::Intersect(const NativeRegisterDataSet& set)
} while (changed); } while (changed);
} }
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags) NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags, int param)
: mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags) : mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags), mParam(param)
{} {}
bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
@ -159,6 +159,12 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
requiredTemps += BC_REG_ACCU + i; requiredTemps += BC_REG_ACCU + i;
requiredTemps += BC_REG_WORK + i; requiredTemps += BC_REG_WORK + i;
} }
if (mFlags & NCIF_USE_ZP_32_X)
{
for (int i = 0; i < 4; i++)
requiredTemps += mParam + i;
}
} }
else else
{ {
@ -701,7 +707,7 @@ bool NativeCodeInstruction::IsCommutative(void) const
bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
{ {
if (mType == ins.mType && mMode == ins.mMode) if (mType == ins.mType && mMode == ins.mMode && mParam == ins.mParam)
{ {
switch (mMode) switch (mMode)
{ {
@ -2185,6 +2191,14 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
if (!providedTemps[BC_REG_ADDR + i]) if (!providedTemps[BC_REG_ADDR + i])
requiredTemps += BC_REG_ADDR + i; requiredTemps += BC_REG_ADDR + i;
} }
if (mFlags & NCIF_USE_ZP_32_X)
{
for (int i = 0; i < 4; i++)
{
if (!providedTemps[mParam + i])
requiredTemps += mParam + i;
}
}
} }
else else
{ {
@ -2489,6 +2503,11 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
} }
else else
{ {
if (mType == ASMIT_JSR && (mFlags & NCIF_USE_ZP_32_X))
{
block->PutByte(AsmInsOpcodes[ASMIT_LDX][ASMIM_IMMEDIATE]);
block->PutByte(mParam);
}
if (mMode == ASMIM_IMMEDIATE_ADDRESS) if (mMode == ASMIM_IMMEDIATE_ADDRESS)
{ {
@ -4719,12 +4738,31 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
if (ins->mDst.mType == IT_FLOAT) if (ins->mDst.mType == IT_FLOAT)
{ {
int sreg0 = ins->mSrc[0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; int sop0 = 0, sop1 = 1;
bool flipop = false;
if (ins->mSrc[1].mTemp < 0) if (ins->mOperator == IA_ADD || ins->mOperator == IA_MUL || ins->mOperator == IA_SUB)
{
if (!sins0 && ins->mSrc[sop0].mTemp >= 0 && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop0].mTemp]))
{
flipop = true;
sop0 = 1; sop1 = 0;
const InterInstruction* sins = sins0; sins0 = sins1; sins1 = sins;
}
else if (!sins1 && !sins0 && ins->mSrc[sop0].mTemp < 0 && ins->mSrc[sop1].mTemp >= 0 && !CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp]))
{
flipop = true;
sop0 = 1; sop1 = 0;
const InterInstruction* sins = sins0; sins0 = sins1; sins1 = sins;
}
}
int sreg0 = ins->mSrc[sop0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop0].mTemp];
if (ins->mSrc[sop1].mTemp < 0)
{ {
union { float f; unsigned int v; } cc; union { float f; unsigned int v; } cc;
cc.f = ins->mSrc[1].mFloatConst; cc.f = ins->mSrc[sop1].mFloatConst;
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
@ -4739,29 +4777,32 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
{ {
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr); LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
} }
else if (ins->mSrc[1].mFinal && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])) else if (CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp]))
{
if (ins->mSrc[sop1].mFinal)
{ {
// cull previous store from accu to temp using direcrt forwarding // cull previous store from accu to temp using direcrt forwarding
mIns.SetSize(mIns.Size() - 8); mIns.SetSize(mIns.Size() - 8);
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]) }
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp])
sreg0 = BC_REG_ACCU; sreg0 = BC_REG_ACCU;
} }
else else
{ {
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
} }
if (ins->mSrc[0].mTemp < 0) if (ins->mSrc[sop0].mTemp < 0)
{ {
union { float f; unsigned int v; } cc; union { float f; unsigned int v; } cc;
cc.f = ins->mSrc[0].mFloatConst; cc.f = ins->mSrc[sop0].mFloatConst;
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
@ -4771,13 +4812,21 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
} }
else if (sins0) else if (sins0)
{ {
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr); LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
} }
else else
{ {
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_USE_ZP_32_X, sreg0));
#if 0
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 1)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 1));
@ -4786,10 +4835,9 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 3)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
#endif
} }
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
switch (ins->mOperator) switch (ins->mOperator)
{ {
@ -4799,10 +4847,20 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME)); mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
} break; } break;
case IA_SUB: case IA_SUB:
{
if (flipop)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
else
{ {
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80)); mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
}
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub"))); NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME)); mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
} break; } break;
@ -8043,6 +8101,9 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
{ {
mVisited = true; mVisited = true;
int yreg = -1;
int xreg = -1;
for (int i = 0; i < mIns.Size(); i++) for (int i = 0; i < mIns.Size(); i++)
{ {
const NativeCodeInstruction& ins(mIns[i]); const NativeCodeInstruction& ins(mIns[i]);
@ -8058,7 +8119,10 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
break; break;
case ASMIT_LDY: case ASMIT_LDY:
if (yregs[ins.mAddress] >= 0) if (yregs[ins.mAddress] >= 0)
{
yregs[ins.mAddress] += 2; yregs[ins.mAddress] += 2;
yreg = ins.mAddress;
}
for (int i = 1; i < 256; i++) for (int i = 1; i < 256; i++)
if (i != ins.mAddress) if (i != ins.mAddress)
yregs[i] = -1; yregs[i] = -1;
@ -8067,7 +8131,10 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
break; break;
case ASMIT_LDX: case ASMIT_LDX:
if (xregs[ins.mAddress] >= 0) if (xregs[ins.mAddress] >= 0)
{
xregs[ins.mAddress] += 2; xregs[ins.mAddress] += 2;
xreg = ins.mAddress;
}
for (int i = 1; i < 256; i++) for (int i = 1; i < 256; i++)
if (i != ins.mAddress) if (i != ins.mAddress)
xregs[i] = -1; xregs[i] = -1;
@ -8075,6 +8142,11 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
yregs[ins.mAddress] = -1; yregs[ins.mAddress] = -1;
break; break;
case ASMIT_STA: case ASMIT_STA:
if (yreg == ins.mAddress)
yreg = -1;
if (xreg == ins.mAddress)
xreg = -1;
if (ins.mLive & LIVE_CPU_REG_Z) if (ins.mLive & LIVE_CPU_REG_Z)
{ {
xregs[ins.mAddress + 0] = -1; xregs[ins.mAddress + 0] = -1;
@ -8090,6 +8162,11 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
break; break;
case ASMIT_INC: case ASMIT_INC:
case ASMIT_DEC: case ASMIT_DEC:
if (yreg == ins.mAddress)
yreg = -1;
if (xreg == ins.mAddress)
xreg = -1;
if (yregs[ins.mAddress] >= 0) if (yregs[ins.mAddress] >= 0)
yregs[ins.mAddress] += 3; yregs[ins.mAddress] += 3;
if (xregs[ins.mAddress] >= 0) if (xregs[ins.mAddress] >= 0)
@ -8103,6 +8180,10 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
} }
else if (ins.mMode == ASMIM_INDIRECT_Y) else if (ins.mMode == ASMIM_INDIRECT_Y)
{ {
for (int i = 1; i < 256; i++)
if (i != yreg)
yregs[i] = -1;
xregs[ins.mAddress + 0] = -1; xregs[ins.mAddress + 0] = -1;
xregs[ins.mAddress + 1] = -1; xregs[ins.mAddress + 1] = -1;
yregs[ins.mAddress + 0] = -1; yregs[ins.mAddress + 0] = -1;
@ -8114,6 +8195,18 @@ void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
} }
else else
{ {
if (ins.RequiresXReg())
{
for (int i = 1; i < 256; i++)
if (i != xreg)
xregs[i] = -1;
}
if (ins.RequiresYReg())
{
for (int i = 1; i < 256; i++)
if (i != yreg)
yregs[i] = -1;
}
if (ins.ChangesXReg()) if (ins.ChangesXReg())
xregs[0] = -1; xregs[0] = -1;
if (ins.ChangesYReg()) if (ins.ChangesYReg())
@ -8168,6 +8261,9 @@ bool NativeCodeBasicBlock::RemapZeroPage(const uint8* remap)
modified = true; modified = true;
} }
} }
if (mIns[i].mFlags & NCIF_USE_ZP_32_X)
mIns[i].mParam = remap[mIns[i].mParam];
} }
break; break;
} }
@ -8191,6 +8287,24 @@ bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const
return false; return false;
} }
void NativeCodeBasicBlock::AddEntryBlock(NativeCodeBasicBlock* block)
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i] != block)
i++;
if (i == mEntryBlocks.Size())
mEntryBlocks.Push(block);
}
void NativeCodeBasicBlock::RemEntryBlock(NativeCodeBasicBlock* block)
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i] != block)
i++;
if (i < mEntryBlocks.Size())
mEntryBlocks.Remove(i);
}
bool NativeCodeBasicBlock::JoinTailCodeSequences(void) bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
{ {
bool changed = false; bool changed = false;
@ -8198,7 +8312,7 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
if (!mVisited) if (!mVisited)
{ {
mVisited = true; mVisited = true;
#if 1
if (mEntryBlocks.Size() > 1) if (mEntryBlocks.Size() > 1)
{ {
int i = 0; int i = 0;
@ -8229,8 +8343,9 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
} }
} }
} }
#endif
if (mTrueJump && mFalseJump && !mTrueJump->mFalseJump && !mFalseJump->mFalseJump) #if 1
if (mTrueJump && mFalseJump && !mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump)
{ {
if (mTrueJump->mIns.Size() > mFalseJump->mIns.Size()) if (mTrueJump->mIns.Size() > mFalseJump->mIns.Size())
{ {
@ -8239,8 +8354,13 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
i++; i++;
if (i == mFalseJump->mIns.Size()) if (i == mFalseJump->mIns.Size())
{ {
if (mTrueJump->mTrueJump)
mTrueJump->mTrueJump->RemEntryBlock(mTrueJump);
mTrueJump->mTrueJump = mFalseJump; mTrueJump->mTrueJump = mFalseJump;
if (mTrueJump->mTrueJump)
mTrueJump->mTrueJump->AddEntryBlock(mTrueJump);
mTrueJump->mIns.SetSize(offset); mTrueJump->mIns.SetSize(offset);
changed = true; changed = true;
} }
} }
@ -8251,13 +8371,17 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
i++; i++;
if (i == mTrueJump->mIns.Size()) if (i == mTrueJump->mIns.Size())
{ {
if (mFalseJump->mTrueJump)
mFalseJump->mTrueJump->RemEntryBlock(mFalseJump);
mFalseJump->mTrueJump = mTrueJump; mFalseJump->mTrueJump = mTrueJump;
if (mFalseJump->mTrueJump)
mFalseJump->mTrueJump->AddEntryBlock(mFalseJump);
mFalseJump->mIns.SetSize(offset); mFalseJump->mIns.SetSize(offset);
changed = true; changed = true;
} }
} }
} }
#endif
if (mTrueJump && mTrueJump->JoinTailCodeSequences()) if (mTrueJump && mTrueJump->JoinTailCodeSequences())
changed = true; changed = true;
if (mFalseJump && mFalseJump->JoinTailCodeSequences()) if (mFalseJump && mFalseJump->JoinTailCodeSequences())
@ -8954,6 +9078,9 @@ bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreUp(int at)
{ {
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at + 1].mAddress) if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at + 1].mAddress)
{ {
if (mIns[j].mLive & LIVE_CPU_REG_A)
return false;
mIns.Insert(j + 1, mIns[at + 3]); // STA mIns.Insert(j + 1, mIns[at + 3]); // STA
mIns.Insert(j + 1, mIns[at + 3]); // ADC mIns.Insert(j + 1, mIns[at + 3]); // ADC
mIns.Insert(j + 1, mIns[at + 2]); // CLC mIns.Insert(j + 1, mIns[at + 2]); // CLC
@ -11421,6 +11548,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
progress = true; progress = true;
} }
else if (
mIns[i + 0].mType == ASMIT_TYA &&
!mIns[i + 1].ChangesYReg() && !mIns[i + 1].ChangesAccu() &&
mIns[i + 2].mType == ASMIT_TAY && !(mIns[i + 2].mLive & LIVE_CPU_REG_Z))
{
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif #endif
#if 1 #if 1
if ( if (
@ -11704,7 +11839,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
int apos, breg, ireg; int apos, breg, ireg;
if (FindAddressSumY(i, mIns[i + 1].mAddress, apos, breg, ireg)) if (FindAddressSumY(i, mIns[i + 1].mAddress, apos, breg, ireg))
{ {
if (breg == mIns[i + 1].mAddress) if (breg == mIns[i + 1].mAddress || ireg == mIns[i + 1].mAddress)
{ {
mIns[apos + 3].mType = ASMIT_NOP; mIns[apos + 3].mMode = ASMIM_IMPLIED; mIns[apos + 3].mType = ASMIT_NOP; mIns[apos + 3].mMode = ASMIM_IMPLIED;
mIns[apos + 6].mType = ASMIT_NOP; mIns[apos + 6].mMode = ASMIM_IMPLIED; mIns[apos + 6].mType = ASMIT_NOP; mIns[apos + 6].mMode = ASMIM_IMPLIED;
@ -11773,34 +11908,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#endif #endif
} }
#if 0
if (i + 8 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_TYA &&
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 + 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 + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 3].mAddress)
{
mIns[i + 7].mType = ASMIT_NOP;
mIns[i + 7].mMode = ASMIM_IMPLIED;
mIns[i + 8].mAddress = mIns[i + 2].mAddress;
if (mIns[i + 8].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns[i + 9].mLive |= LIVE_CPU_REG_Y;
}
}
}
#endif
#if 1 #if 1
if (i + 7 < mIns.Size()) if (i + 7 < mIns.Size())
{ {
@ -12794,12 +12901,14 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
} }
#endif #endif
#if 1
if (step > 2) if (step > 2)
{ {
ResetVisited(); ResetVisited();
if (mEntryBlock->JoinTailCodeSequences()) if (mEntryBlock->JoinTailCodeSequences())
changed = true; changed = true;
} }
#endif
if (step == 3) if (step == 3)
{ {
ResetVisited(); ResetVisited();

View File

@ -48,15 +48,22 @@ static const uint32 NCIF_YZERO = 0x00000008;
static const uint32 NCIF_VOLATILE = 0x00000010; static const uint32 NCIF_VOLATILE = 0x00000010;
static const uint32 NCIF_LONG = 0x00000020; static const uint32 NCIF_LONG = 0x00000020;
static const uint32 NCIF_USE_CPU_REG_A = 0x00000040;
static const uint32 NCIF_USE_CPU_REG_X = 0x00000080;
static const uint32 NCIF_USE_CPU_REG_Y = 0x00000100;
// use a 32bit zero page register indexed by X for JSR
static const uint32 NCIF_USE_ZP_32_X = 0x00000200;
class NativeCodeInstruction class NativeCodeInstruction
{ {
public: public:
NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, LinkerObject * linkerObject = nullptr, uint32 flags = NCIF_LOWER | NCIF_UPPER); NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, LinkerObject * linkerObject = nullptr, uint32 flags = NCIF_LOWER | NCIF_UPPER, int param = 0);
AsmInsType mType; AsmInsType mType;
AsmInsMode mMode; AsmInsMode mMode;
int mAddress; int mAddress, mParam;
uint32 mFlags; uint32 mFlags;
uint32 mLive; uint32 mLive;
LinkerObject* mLinkerObject; LinkerObject* mLinkerObject;
@ -202,6 +209,9 @@ public:
void CollectEntryBlocks(NativeCodeBasicBlock* block); void CollectEntryBlocks(NativeCodeBasicBlock* block);
void AddEntryBlock(NativeCodeBasicBlock* block);
void RemEntryBlock(NativeCodeBasicBlock* block);
bool JoinTailCodeSequences(void); bool JoinTailCodeSequences(void);
bool SameTail(const NativeCodeInstruction& ins) const; bool SameTail(const NativeCodeInstruction& ins) const;

View File

@ -100,6 +100,18 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_72FE541170AB418781C6087271FD3D74"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_7B3ADAAB82E944EDBA72636B19969B4A"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_7EA67552E0B34B9BA70152AD9E369EA6" "MsmKey" = "8:_7EA67552E0B34B9BA70152AD9E369EA6"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -190,6 +202,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_DA28A07E7836459C99161100D7C102B8"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_E218D776D9014F99BE2B046AEF2D6E8B" "MsmKey" = "8:_E218D776D9014F99BE2B046AEF2D6E8B"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -615,6 +633,46 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "IsolateTo" = "8:"
} }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_72FE541170AB418781C6087271FD3D74"
{
"SourcePath" = "8:..\\include\\c64\\asm6502.c"
"TargetName" = "8:asm6502.c"
"Tag" = "8:"
"Folder" = "8:_247D4CAD3CB843B3A8A4DC2D90F47C28"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7B3ADAAB82E944EDBA72636B19969B4A"
{
"SourcePath" = "8:..\\include\\c64\\memmap.c"
"TargetName" = "8:memmap.c"
"Tag" = "8:"
"Folder" = "8:_247D4CAD3CB843B3A8A4DC2D90F47C28"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7EA67552E0B34B9BA70152AD9E369EA6" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7EA67552E0B34B9BA70152AD9E369EA6"
{ {
"SourcePath" = "8:..\\include\\c64\\joystick.h" "SourcePath" = "8:..\\include\\c64\\joystick.h"
@ -915,6 +973,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "IsolateTo" = "8:"
} }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DA28A07E7836459C99161100D7C102B8"
{
"SourcePath" = "8:..\\include\\c64\\memmap.h"
"TargetName" = "8:memmap.h"
"Tag" = "8:"
"Folder" = "8:_247D4CAD3CB843B3A8A4DC2D90F47C28"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E218D776D9014F99BE2B046AEF2D6E8B" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E218D776D9014F99BE2B046AEF2D6E8B"
{ {
"SourcePath" = "8:..\\include\\stdlib.c" "SourcePath" = "8:..\\include\\stdlib.c"