Prepare compressed embedded data

This commit is contained in:
drmortalwombat 2022-04-17 18:41:53 +02:00
parent 72d2fc1fac
commit 41a4db4402
7 changed files with 601 additions and 34 deletions

View File

@ -1353,6 +1353,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1380,6 +1381,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mSrc[0].mTemp;
ins->mSrc[0].mType = mInstructions[i]->mSrc[0].mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
}
@ -1473,6 +1475,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1498,6 +1501,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1532,6 +1536,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1557,6 +1562,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1595,6 +1601,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[0].mType = ins->mSrc[1].mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
UpdateValue(ins, tvalue, aliasedLocals, aliasedParams, staticVars);
@ -1633,6 +1640,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
UpdateValue(ins, tvalue, aliasedLocals, aliasedParams, staticVars);
@ -1690,6 +1698,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
UpdateValue(ins, tvalue, aliasedLocals, aliasedParams, staticVars);
@ -1714,6 +1723,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1744,6 +1754,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1773,6 +1784,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1806,6 +1818,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1830,6 +1843,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1861,6 +1875,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -1884,6 +1899,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = mInstructions[i]->mDst.mTemp;
ins->mSrc[0].mType = mInstructions[i]->mDst.mType;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -3102,6 +3118,7 @@ void InterInstruction::SimpleLocalToTemp(int vindex, int temp)
mCode = IC_LOAD_TEMPORARY;
mSrc[0].mTemp = temp;
mSrc[0].mType = mDst.mType;
mNumOperands = 1;
assert(mSrc[0].mTemp >= 0);
@ -3119,6 +3136,7 @@ void InterInstruction::SimpleLocalToTemp(int vindex, int temp)
else
{
mCode = IC_LOAD_TEMPORARY;
mNumOperands = 1;
assert(mSrc[0].mTemp >= 0);
}
@ -3517,11 +3535,16 @@ void InterCodeBasicBlock::BuildDominatorTree(InterCodeBasicBlock* from)
if (from == this)
return;
else if (!mDominator)
{
assert(!from || mIndex != 0);
mDominator = from;
}
else if (from == mDominator)
return;
else
{
assert(mIndex != 0);
GrowingInterCodeBasicBlockPtrArray d1(nullptr), d2(nullptr);
InterCodeBasicBlock* b = mDominator;
@ -3832,6 +3855,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
ins->mSrc[0].mType = ins->mSrc[1].mType;
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else
@ -3886,6 +3910,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mSrc[0].mType == ins->mDst.mType)
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (TypeInteger(ins->mSrc[0].mType) && ins->mDst.mType == IT_POINTER)
@ -3960,6 +3985,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mOperator == IA_ADD && ins->mSrc[1].mFloatConst == 0)
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mOperator == IA_MUL)
@ -3967,6 +3993,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mSrc[1].mFloatConst == 1.0)
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mSrc[1].mFloatConst == 0.0)
@ -3995,6 +4022,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mOperator == IA_MUL)
@ -4004,6 +4032,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mSrc[0].mFloatConst == 0.0)
@ -4042,6 +4071,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mOperator == IA_ADD && ins->mSrc[1].mIntConst == 0)
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mOperator == IA_MUL)
@ -4049,6 +4079,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mSrc[1].mIntConst == 1)
{
ins->mCode = IC_LOAD_TEMPORARY;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mSrc[1].mIntConst == 2)
@ -4090,6 +4121,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mOperator == IA_MUL)
@ -4099,6 +4131,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
ins->mCode = IC_LOAD_TEMPORARY;
ins->mSrc[0].mTemp = ins->mSrc[1].mTemp;
ins->mSrc[1].mTemp = -1;
ins->mNumOperands = 1;
assert(ins->mSrc[0].mTemp >= 0);
}
else if (ins->mSrc[0].mIntConst == 2)
@ -9586,7 +9619,7 @@ void InterCodeProcedure::DisassembleDebug(const char* name)
Disassemble(name);
}
void InterCodeProcedure::BuildTraces(bool expand)
void InterCodeProcedure::BuildTraces(bool expand, bool dominators)
{
// Count number of entries
//
@ -9612,6 +9645,7 @@ void InterCodeProcedure::BuildTraces(bool expand)
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mDominator = nullptr;
if (dominators)
mEntryBlock->BuildDominatorTree(nullptr);
}
@ -10395,7 +10429,7 @@ void InterCodeProcedure::Close(void)
// Optimize for size
MergeBasicBlocks();
BuildTraces(false);
BuildTraces(false, false);
DisassembleDebug("Final Merged basic blocks");
}

View File

@ -526,7 +526,7 @@ public:
void Disassemble(FILE* file);
void Disassemble(const char* name, bool dumpSets = false);
protected:
void BuildTraces(bool expand);
void BuildTraces(bool expand, bool dominators = true);
void BuildDataFlowSets(void);
void RenameTemporaries(void);
void TempForwarding(void);

View File

@ -852,6 +852,7 @@ bool NativeCodeInstruction::ChangesZFlag(void) const
mType == ASMIT_INC || mType == ASMIT_DEC ||
mType == ASMIT_INY || mType == ASMIT_DEY ||
mType == ASMIT_INX || mType == ASMIT_DEX ||
mType == ASMIT_TAX || mType == ASMIT_TAY || mType == ASMIT_TXA || mType == ASMIT_TYA ||
mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY ||
mType == ASMIT_LDA || mType == ASMIT_LDX || mType == ASMIT_LDY ||
mType == ASMIT_JSR;
@ -1807,6 +1808,8 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
{
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
data.ResetZeroPage(i);
for(int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
data.ResetZeroPage(i);
}
return false;
@ -2450,9 +2453,21 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
}
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE)
{
#if 1
if (data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode == NRDM_UNKNOWN && mAddress >= BC_REG_FPARAMS && mAddress < BC_REG_FPARAMS_END)
{
data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode = NRDM_ZERO_PAGE;
data.mRegs[data.mRegs[CPU_REG_A].mValue].mValue = mAddress;
data.mRegs[mAddress].mMode = NRDM_UNKNOWN;
}
else
#endif
{
data.mRegs[mAddress].mMode = NRDM_ZERO_PAGE;
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue;
}
}
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE)
{
data.mRegs[mAddress] = data.mRegs[CPU_REG_A];
@ -4205,6 +4220,33 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr
}
void NativeCodeBasicBlock::LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp]));
for (int i = 0; i < InterTypeSize[rins->mDst.mType]; i++)
{
if (i != 0)
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[iins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp] + i));
}
}
void NativeCodeBasicBlock::StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* wins)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp]));
for (int i = 0; i < InterTypeSize[wins->mSrc[0].mType]; i++)
{
if (i != 0)
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp] + i));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[iins->mSrc[1].mTemp]));
}
}
void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins)
{
int size = InterTypeSize[wins->mSrc[0].mType];
@ -5515,6 +5557,15 @@ void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg,
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg + 0));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, reg + 1));
}
else if (shift >= 8)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
for (int i = 8; i < shift; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
}
else if (shift >= 5)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
@ -9229,6 +9280,111 @@ void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
}
}
bool NativeCodeBasicBlock::IsSame(const NativeCodeBasicBlock* block) const
{
if (block->mIns.Size() != mIns.Size())
return false;
if (block->mBranch != mBranch)
return false;
if (mTrueJump)
{
if (!block->mTrueJump)
return false;
if (mTrueJump == this)
{
if (block->mTrueJump != block)
return false;
}
else if (mTrueJump != block->mTrueJump)
return false;
}
else if (block->mTrueJump)
return false;
if (mFalseJump)
{
if (!block->mFalseJump)
return false;
if (mFalseJump == this)
{
if (block->mFalseJump != block)
return false;
}
else if (mFalseJump != block->mFalseJump)
return false;
}
else if (block->mFalseJump)
return false;
for (int i = 0; i < mIns.Size(); i++)
if (!mIns[i].IsSame(block->mIns[i]))
return false;
return true;
}
bool NativeCodeBasicBlock::FindSameBlocks(NativeCodeProcedure* nproc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (!mSameBlock)
{
for (int i = 0; i < nproc->mBlocks.Size(); i++)
{
if (nproc->mBlocks[i]->IsSame(this))
{
nproc->mBlocks[i]->mSameBlock = this;
changed = true;
}
}
}
if (mTrueJump && mTrueJump->FindSameBlocks(nproc))
changed = true;
if (mFalseJump && mFalseJump->FindSameBlocks(nproc))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::MergeSameBlocks(NativeCodeProcedure* nproc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && mTrueJump->mSameBlock)
{
mTrueJump = mTrueJump->mSameBlock;
changed = true;
}
if (mFalseJump && mFalseJump->mSameBlock)
{
mFalseJump = mFalseJump->mSameBlock;
changed = true;
}
if (mTrueJump && mTrueJump->MergeSameBlocks(nproc))
changed = true;
if (mFalseJump && mFalseJump->MergeSameBlocks(nproc))
changed = true;
}
return true;
}
bool NativeCodeBasicBlock::MergeBasicBlocks(void)
{
bool changed = false;
@ -9289,7 +9445,7 @@ bool NativeCodeBasicBlock::MergeBasicBlocks(void)
changed = true;
}
while (mFalseJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this && mFalseJump->mTrueJump != mFalseJump)
while (mFalseJump && mFalseJump->mTrueJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this && mFalseJump->mTrueJump != mFalseJump)
{
mFalseJump->mNumEntries--;
mFalseJump = mFalseJump->mTrueJump;
@ -10411,6 +10567,49 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
for (int i = 0; i < mIns.Size(); i++)
{
if (i + 6 < mIns.Size())
{
if (mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 1].SameEffectiveAddress(mIns[i + 3]) &&
mIns[i + 4].mType == ASMIT_LDA &&
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 + 4].SameEffectiveAddress(mIns[i + 6]) &&
HasAsmInstructionMode(ASMIT_INC, mIns[i + 3].mMode) &&
HasAsmInstructionMode(ASMIT_INC, mIns[i + 6].mMode) &&
!(mIns[i + 6].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
{
changed = true;
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
fblock->mTrueJump = mTrueJump;
fblock->mFalseJump = mFalseJump;
fblock->mBranch = mBranch;
mIns[i + 0].mType = ASMIT_NOP;
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_INC; mIns[i + 3].mLive |= LIVE_CPU_REG_Z;
for (int j = i + 7; j < mIns.Size(); j++)
fblock->mIns.Push(mIns[j]);
iblock->mIns.Push(mIns[i + 6]);
mIns.SetSize(i + 4);
iblock->mIns[0].mType = ASMIT_INC;
iblock->mTrueJump = fblock;
iblock->mBranch = ASMIT_JMP;
mTrueJump = fblock;
mFalseJump = iblock;
mBranch = ASMIT_BNE;
break;
}
}
if (i + 2 < mIns.Size())
{
if (mIns[i + 0].mType == ASMIT_LDA &&
@ -10441,6 +10640,34 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
mBranch = ASMIT_BCC;
break;
}
else if (mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_SBC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 2]) &&
HasAsmInstructionMode(ASMIT_DEC, mIns[i + 2].mMode) &&
!(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
{
changed = true;
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
fblock->mTrueJump = mTrueJump;
fblock->mFalseJump = mFalseJump;
fblock->mBranch = mBranch;
for (int j = i + 3; j < mIns.Size(); j++)
fblock->mIns.Push(mIns[j]);
iblock->mIns.Push(mIns[i + 2]);
mIns.SetSize(i);
iblock->mIns[0].mType = ASMIT_DEC;
iblock->mTrueJump = fblock;
iblock->mBranch = ASMIT_JMP;
mTrueJump = fblock;
mFalseJump = iblock;
mBranch = ASMIT_BCS;
break;
}
}
}
@ -12180,6 +12407,29 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
}
mIns.Remove(start);
return true;
}
else if (mIns[start + 0].mType == ASMIT_LDY && mIns[start + 0].mMode == ASMIM_IMMEDIATE &&
mIns[start + 1].mType == ASMIT_LDA && mIns[start + 1].mMode == ASMIM_INDIRECT_Y &&
!(mIns[start + 1].mLive & LIVE_CPU_REG_Y) && !(mIns[to].mLive & LIVE_CPU_REG_Y))
{
for (int i = from + 1; i < to; i++)
{
if (mIns[i].mMode == ASMIM_ZERO_PAGE && (mIns[i].mAddress == mIns[start + 1].mAddress || mIns[i].mAddress == mIns[start + 1].mAddress + 1) && mIns[i].ChangesAddress())
return false;
if (mIns[i].ChangesGlobalMemory())
return false;
}
mIns.Remove(to);
for (int i = start; i < from; i++)
{
mIns.Insert(to, mIns[start]);
mIns.Remove(start);
}
mIns.Remove(start);
return true;
}
}
@ -12226,6 +12476,34 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
bool NativeCodeBasicBlock::JoinTAYARange(int from, int to)
{
int start = from;
if (from >= 2)
{
start = from - 2;
if (mIns[start + 0].mType == ASMIT_LDY && mIns[start + 0].mMode == ASMIM_IMMEDIATE &&
mIns[start + 1].mType == ASMIT_LDA && mIns[start + 1].mMode == ASMIM_INDIRECT_Y)
{
for (int i = from + 1; i < to; i++)
{
if (mIns[i].mMode == ASMIM_ZERO_PAGE && (mIns[i].mAddress == mIns[start + 1].mAddress || mIns[i].mAddress == mIns[start + 1].mAddress + 1) && mIns[i].ChangesAddress())
return false;
if (mIns[i].ChangesGlobalMemory())
return false;
}
mIns.Remove(to);
for (int i = start; i < from; i++)
{
mIns.Insert(to, mIns[start]);
mIns.Remove(start);
}
mIns.Remove(start);
return true;
}
}
return false;
}
@ -13874,6 +14152,9 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
{
bool changed = false;
if (mBranch == ASMIT_JMP)
return false;
int sz = mIns.Size();
if (sz == 2 && (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE) && mIns[0].mType == ASMIT_LDA && mIns[1].mType == ASMIT_CMP && !(mIns[1].mFlags & NCIF_VOLATILE) && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
@ -14481,6 +14762,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
bool changed = false;
int sz = mIns.Size();
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
#if 1
if (sz > 3 &&
mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_IMMEDIATE &&
@ -14952,11 +15235,15 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
}
#if 1
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
if (!changed)
changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr);
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
#endif
}
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
if (mTrueJump && mTrueJump->OptimizeSimpleLoop(proc))
changed = true;
if (mFalseJump && mFalseJump->OptimizeSimpleLoop(proc))
@ -15264,6 +15551,8 @@ bool NativeCodeBasicBlock::OptimizeSelect(NativeCodeProcedure* proc)
{
mVisited = true;
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
if (mFalseJump && mIns.Size() > 0 && mIns.Last().ChangesAccuAndFlag() &&
mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 &&
!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump &&
@ -15290,6 +15579,8 @@ bool NativeCodeBasicBlock::OptimizeSelect(NativeCodeProcedure* proc)
}
}
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
if (mTrueJump && mTrueJump->OptimizeSelect(proc))
changed = true;
if (mFalseJump && mFalseJump->OptimizeSelect(proc))
@ -15589,6 +15880,19 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
j += 4;
i += 7;
}
else if (i + 4 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x01 &&
mIns[i + 3].mType == ASMIT_CLC &&
mIns[i + 4].mType == ASMIT_ADC && !(mIns[i + 4].mLive & LIVE_CPU_REG_C | LIVE_CPU_REG_Z))
{
mIns[j + 0] = mIns[i + 0]; mIns[j + 0].mType = ASMIT_SEC;
mIns[j + 1] = mIns[i + 1];
mIns[j + 2] = mIns[i + 4];
j += 3;
i += 5;
}
else if (i + 2 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
@ -16018,6 +16322,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
i = 0;
j = 0;
int accuVal = 0, accuMask = 0;
bool accuFlags = false;
while (i < mIns.Size())
{
bool skip = false;
@ -16050,9 +16355,11 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
case ASMIT_ADC:
case ASMIT_SBC:
accuMask = 0;
accuFlags = true;
case ASMIT_CMP:
carryClear = false;
carrySet = false;
accuFlags = false;
break;
case ASMIT_AND:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
@ -16065,15 +16372,19 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
}
else
accuMask = 0;
accuFlags = true;
break;
case ASMIT_ORA:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
{
if (mIns[i].mAddress == 0 && accuFlags)
skip = true;
accuVal = 0xff;
accuMask = mIns[i].mAddress;
}
else
accuMask = 0;
accuFlags = true;
break;
case ASMIT_LDA:
if (mIns[i].mMode == ASMIM_IMMEDIATE)
@ -16083,6 +16394,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
}
else
accuMask = 0x00;
accuFlags = true;
break;
case ASMIT_ASL:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x80))
@ -16107,6 +16419,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
carryClear = false;
carrySet = false;
}
accuFlags = mIns[i].mMode == ASMIM_IMPLIED;
break;
case ASMIT_LSR:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x01))
@ -16131,6 +16444,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
carryClear = false;
carrySet = false;
}
accuFlags = mIns[i].mMode == ASMIM_IMPLIED;
break;
case ASMIT_ROL:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x80))
@ -16155,6 +16469,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
carryClear = false;
carrySet = false;
}
accuFlags = mIns[i].mMode == ASMIM_IMPLIED;
break;
case ASMIT_ROR:
if (mIns[i].mMode == ASMIM_IMPLIED && (accuMask & 0x01))
@ -16179,6 +16494,11 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
carryClear = false;
carrySet = false;
}
accuFlags = mIns[i].mMode == ASMIM_IMPLIED;
break;
case ASMIT_TAX:
case ASMIT_TAY:
accuFlags = true;
break;
default:
if (mIns[i].ChangesCarry())
@ -16188,7 +16508,14 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc)
}
if (mIns[i].ChangesAccu())
{
accuMask = 0;
accuFlags = false;
}
else if (mIns[i].ChangesZFlag())
{
accuFlags = false;
}
}
if (!skip)
@ -16242,6 +16569,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
if (!mVisited)
{
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
bool changed = RemoveNops();
@ -18298,9 +18626,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & LIVE_CPU_REG_Y) &&
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 0].mLive & LIVE_CPU_REG_Y) &&
!mIns[i + 1].UsesZeroPage(mIns[i + 0].mAddress) &&
mIns[i + 2].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & (LIVE_MEM | LIVE_CPU_REG_Z)))
mIns[i + 2].mType == ASMIT_LDY && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & (LIVE_MEM | LIVE_CPU_REG_Z)))
{
mIns[i + 0].mType = ASMIT_TAY; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
@ -18308,9 +18636,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & LIVE_CPU_REG_X) &&
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 0].mLive & LIVE_CPU_REG_X) &&
!mIns[i + 1].UsesZeroPage(mIns[i + 0].mAddress) &&
mIns[i + 2].mType == ASMIT_LDX && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & (LIVE_MEM | LIVE_CPU_REG_Z)))
mIns[i + 2].mType == ASMIT_LDX && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & (LIVE_MEM | LIVE_CPU_REG_Z)))
{
mIns[i + 0].mType = ASMIT_TAX; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
mIns[i + 1].mLive |= LIVE_CPU_REG_X;
@ -19684,6 +20012,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
changed = true;
}
}
if (sz >= 1 &&
mIns[sz - 1].mType == ASMIT_AND && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x80 && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A) &&
(mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE))
{
mIns[sz - 1].mType = ASMIT_ORA;
mIns[sz - 1].mAddress = 0x00;
if (mBranch == ASMIT_BEQ)
mBranch = ASMIT_BPL;
else
mBranch = ASMIT_BMI;
changed = true;
}
#endif
#if 1
if (mTrueJump && mFalseJump && !mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump &&
@ -19798,7 +20141,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
{
if (mBypassed)
return this;
else if (!mFalseJump && mCode.Size() == 0 && this != mTrueJump)
else if (mTrueJump && !mFalseJump && mCode.Size() == 0 && this != mTrueJump)
return mTrueJump->BypassEmptyBlocks();
else
{
@ -19875,7 +20218,7 @@ void NativeCodeBasicBlock::BuildPlacement(GrowingArray<NativeCodeBasicBlock*>& p
mFalseJump->BuildPlacement(placement);
}
#if 1
else if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mFalseJump->mFalseJump && !mTrueJump->mTrueJump->mPlaced && mTrueJump->mTrueJump->mNumEntries > 1)
else if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mFalseJump->mFalseJump && !mTrueJump->mTrueJump->mPlaced && mTrueJump->mTrueJump->mNumEntries > 1 && mTrueJump->mTrueJump->mTrueJump != mTrueJump->mTrueJump)
{
mTrueJump->mPlaced = true;
mTrueJump->mPlace = placement.Size();
@ -20557,9 +20900,21 @@ void NativeCodeProcedure::Optimize(void)
mBlocks[i]->mLoopHead = false;
mBlocks[i]->mFromJump = nullptr;
mBlocks[i]->mDominator = nullptr;
mBlocks[i]->mSameBlock = nullptr;
}
ResetEntryBlocks();
if (step > 3)
{
ResetVisited();
if (mEntryBlock->FindSameBlocks(this))
{
ResetVisited();
changed = mEntryBlock->MergeSameBlocks(this);
}
}
ResetVisited();
ResetEntryBlocks();
mEntryBlock->CountEntries(nullptr);
ResetVisited();
@ -21059,8 +21414,28 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
else if (iblock->mInstructions[i + 1]->mCode == IC_STORE && iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp)
avalid = true;
}
if (i + 1 < iblock->mInstructions.Size() &&
iblock->mInstructions[i + 1]->mCode == IC_LOAD && iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal &&
iblock->mInstructions[i + 0]->mSrc[1].mTemp >= 0 && iblock->mInstructions[i + 0]->mSrc[0].IsUByte() &&
iblock->mInstructions[i + 1]->mSrc[0].mIntConst == 0)
{
block->LoadByteIndexedValue(iproc, ins, iblock->mInstructions[i + 1]);
i++;
}
else if (i + 1 < iblock->mInstructions.Size() &&
iblock->mInstructions[i + 1]->mCode == IC_STORE && iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal &&
iblock->mInstructions[i + 0]->mSrc[1].mTemp >= 0 && iblock->mInstructions[i + 0]->mSrc[0].IsUByte() &&
iblock->mInstructions[i + 1]->mSrc[1].mIntConst == 0 && iblock->mInstructions[i + 1]->mSrc[0].mTemp >= 0)
{
block->StoreByteIndexedValue(iproc, ins, iblock->mInstructions[i + 1]);
i++;
}
else
{
block->LoadEffectiveAddress(iproc, ins, nullptr, nullptr, avalid);
}
}
break;
case IC_CONSTANT:
block->LoadConstant(iproc, ins);

View File

@ -137,7 +137,7 @@ public:
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail;
NativeCodeBasicBlock * mDominator;
NativeCodeBasicBlock * mDominator, * mSameBlock;
NativeCodeBasicBlock* mLoopHeadBlock;
@ -201,6 +201,9 @@ public:
NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc);
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins);
void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
@ -219,6 +222,10 @@ public:
bool BuildGlobalRequiredRegSet(NumberSet& fromRequiredTemps);
bool RemoveUnusedResultInstructions(void);
bool IsSame(const NativeCodeBasicBlock* block) const;
bool FindSameBlocks(NativeCodeProcedure* nproc);
bool MergeSameBlocks(NativeCodeProcedure* nproc);
void CountEntries(NativeCodeBasicBlock* fromJump);
bool MergeBasicBlocks(void);
void MarkLoopHead(void);

View File

@ -1,6 +1,7 @@
#include "Preprocessor.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
SourcePath::SourcePath(const char* path)
{
@ -19,12 +20,141 @@ SourcePath::~SourcePath(void)
}
bool SourceFile::ReadLineRLE(char* line)
{
assert(mFill >= 0 && mFill < 256);
int c;
while (mLimit && mFill < 256 && (c = fgetc(mFile)) >= 0)
{
mLimit--;
mBuffer[mFill++] = c;
}
assert(mFill >= 0 && mFill <= 256);
if (mFill)
{
if (mFill >= 3 && mBuffer[0] == mBuffer[1] && mBuffer[1] == mBuffer[2])
{
int cnt = 1;
while (cnt < 64 && cnt < mFill && mBuffer[cnt] == mBuffer[cnt - 1])
cnt++;
if (cnt <= 8 && cnt < mFill)
{
int rcnt = 1;
int rep = 1;
while (rcnt < 16 && cnt + rcnt < mFill && rep < 3)
{
if (mBuffer[cnt + rcnt] == mBuffer[cnt + rcnt - 1])
rep++;
else
rep = 1;
rcnt++;
}
if (cnt + rcnt < mFill && rep >= 3)
rcnt -= rep;
if (rcnt > 0)
{
sprintf_s(line, 1024, "0x%02x, 0x%02x, ", 0x80 + ((cnt - 1) << 4) + (rcnt - 1), (unsigned char)mBuffer[0]);
assert(mFill >= 0 && mFill <= 256);
for (int i = 0; i < rcnt; i++)
{
char buffer[16];
sprintf_s(buffer, 16, "0x%02x, ", (unsigned char)mBuffer[cnt + i]);
assert(mFill >= 0 && mFill <= 256);
strcat_s(line, 1024, buffer);
assert(mFill >= 0 && mFill <= 256);
}
assert(mFill >= cnt + rcnt);
assert(mFill >= 0 && mFill <= 256);
memmove(mBuffer, mBuffer + cnt + rcnt, mFill - cnt - rcnt);
mFill -= cnt + rcnt;
assert(mFill >= 0 && mFill < 256);
}
else
{
sprintf_s(line, 1024, "0x%02x, 0x%02x, ", 0x00 + (cnt - 1), (unsigned char)mBuffer[0]);
memmove(mBuffer, mBuffer + cnt, mFill - cnt);
mFill -= cnt;
assert(mFill >= 0 && mFill < 256);
}
}
else
{
sprintf_s(line, 1024, "0x%02x, 0x%02x, ", 0x00 + (cnt - 1), (unsigned char)mBuffer[0]);
memmove(mBuffer, mBuffer + cnt, mFill - cnt);
mFill -= cnt;
assert(mFill >= 0 && mFill < 256);
}
if (mFill == 0)
strcat_s(line, 1024, "0x00, ");
return true;
}
else
{
int cnt = 1;
int rep = 1;
while (cnt < 64 && cnt < mFill && rep < 3)
{
if (mBuffer[cnt] == mBuffer[cnt - 1])
rep++;
else
rep = 1;
cnt++;
}
if (cnt < mFill && rep >= 3)
cnt -= rep;
sprintf_s(line, 1024, "0x%02x, ", 0x40 + (cnt - 1));
for (int i = 0; i < cnt; i++)
{
char buffer[16];
sprintf_s(buffer, 16, "0x%02x, ", (unsigned char)mBuffer[i]);
strcat_s(line, 1024, buffer);
}
memmove(mBuffer, mBuffer + cnt, mFill - cnt);
mFill -= cnt;
assert(mFill >= 0 && mFill < 256);
if (mFill == 0)
strcat_s(line, 1024, "0x00, ");
return true;
}
}
return false;
}
bool SourceFile::ReadLine(char* line)
{
if (mFile)
{
if (mBinary)
switch (mMode)
{
case SFM_TEXT:
if (fgets(line, 1024, mFile))
return true;
break;
case SFM_BINARY:
if (mLimit)
{
mLimit--;
@ -36,13 +166,11 @@ bool SourceFile::ReadLine(char* line)
return true;
}
}
else
return false;
}
else
{
if (fgets(line, 1024, mFile))
break;
case SFM_BINARY_RLE:
if (ReadLineRLE(line))
return true;
break;
}
fclose(mFile);
@ -74,7 +202,7 @@ SourceFile::~SourceFile(void)
}
}
bool SourceFile::Open(const char* name, const char* path, bool binary)
bool SourceFile::Open(const char* name, const char* path, SourceFileMode mode)
{
char fname[220];
@ -102,8 +230,9 @@ bool SourceFile::Open(const char* name, const char* path, bool binary)
*p = '/';
p++;
}
mBinary = binary;
mMode = mode;
mLimit = 0x10000;
mFill = 0;
return true;
}
@ -174,7 +303,7 @@ bool Preprocessor::NextLine(void)
return false;
}
bool Preprocessor::EmbedData(const char* reason, const char* name, bool local, int skip, int limit)
bool Preprocessor::EmbedData(const char* reason, const char* name, bool local, int skip, int limit, SourceFileMode mode)
{
if (strlen(name) > 200)
{
@ -189,7 +318,7 @@ bool Preprocessor::EmbedData(const char* reason, const char* name, bool local, i
bool ok = false;
if (source->Open(name, "", true))
if (source->Open(name, "", mode))
ok = true;
if (!ok && local && mSource)
@ -201,14 +330,14 @@ bool Preprocessor::EmbedData(const char* reason, const char* name, bool local, i
i--;
lpath[i] = 0;
if (source->Open(name, lpath, true))
if (source->Open(name, lpath, mode))
ok = true;
}
SourcePath* p = mPaths;
while (!ok && p)
{
if (source->Open(name, p->mPathName, true))
if (source->Open(name, p->mPathName, mode))
ok = true;
else
p = p->mNext;

View File

@ -14,6 +14,12 @@ public:
Location mLocation;
};
enum SourceFileMode
{
SFM_TEXT,
SFM_BINARY,
SFM_BINARY_RLE
};
class SourceFile
{
public:
@ -22,15 +28,20 @@ public:
SourceFile * mUp, * mNext;
Location mLocation;
SourceStack * mStack;
bool mBinary;
SourceFileMode mMode;
int mLimit;
char mBuffer[256];
int mFill;
bool ReadLine(char* line);
bool ReadLineRLE(char* line);
SourceFile(void);
~SourceFile(void);
bool Open(const char* name, const char * path, bool binary = false);
bool Open(const char* name, const char * path, SourceFileMode mode = SFM_TEXT);
void Close(void);
void Limit(int skip, int limit);
@ -77,7 +88,7 @@ public:
bool PopSource(void);
bool DropSource(void);
bool EmbedData(const char* reason, const char* name, bool local, int skip, int limit);
bool EmbedData(const char* reason, const char* name, bool local, int skip, int limit, SourceFileMode mode);
Preprocessor(Errors * errors);
~Preprocessor(void);

View File

@ -637,6 +637,7 @@ void Scanner::NextToken(void)
else if (mToken == TK_PREP_EMBED)
{
int limit = 65536, skip = 0;
SourceFileMode mode = SFM_BINARY;
NextRawToken();
if (mToken == TK_INTEGER)
@ -651,16 +652,26 @@ void Scanner::NextToken(void)
}
}
if (mToken == TK_IDENT)
{
if (!strcmp(mTokenIdent->mString, "rle"))
mode = SFM_BINARY_RLE;
else
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Invalid embed compression mode", mTokenIdent);
NextRawToken();
}
if (mToken == TK_STRING)
{
if (!mPreprocessor->EmbedData("Embedding", mTokenString, true, skip, limit))
if (!mPreprocessor->EmbedData("Embedding", mTokenString, true, skip, limit, mode))
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString);
}
else if (mToken == TK_LESS_THAN)
{
mOffset--;
StringToken('>', 'a');
if (!mPreprocessor->EmbedData("Embedding", mTokenString, false, skip, limit))
if (!mPreprocessor->EmbedData("Embedding", mTokenString, false, skip, limit, mode))
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString);
}
}