Reduce register spilling on function entry/exit

This commit is contained in:
drmortalwombat 2021-10-23 22:22:49 +02:00
parent e057e24918
commit 42e4f483c1
8 changed files with 448 additions and 159 deletions

View File

@ -1,4 +1,5 @@
#include <stdio.h>
#include <assert.h>
int asum(int a, int b)
{
@ -30,11 +31,46 @@ int bsum(int a, int b)
}
}
int b, t[10];
int bsome(int x)
{
return x;
}
int qsum(int a, int (* c)(int))
{
char n = 0;
b = 0;
for(int i=0; i<a; i++)
{
int j = c((char)i);
__asm
{
clc
lda j
adc b
sta b
lda j + 1
adc b + 1
sta b + 1
}
t[n] += i;
n = (n + 1) & 7;
}
return b;
}
int main(void)
{
int x = asum(7007, 8008);
int y = bsum(4004, 9009);
return (x == 7007 + 8008 && y == 4004 + 9009) ? 0 : -1;
assert(x == 7007 + 8008 && y == 4004 + 9009);
assert(qsum(10, bsome) == 45);
assert(qsum(200, bsome) == 19900);
return 0;
}

View File

@ -180,6 +180,7 @@ bool Compiler::GenerateCode(void)
mGlobalAnalyzer->DumpCallGraph();
mInterCodeGenerator->mCompilerOptions = mCompilerOptions;
mNativeCodeGenerator->mCompilerOptions = mCompilerOptions;
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);

View File

@ -2334,6 +2334,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vins->mConst.mOperandSize = vdec->mSize;
vins->mConst.mIntConst = vdec->mOffset;
}
else if (vdec->mType == DT_VARIABLE)
{
vins->mConst.mMemory = IM_LOCAL;
vins->mConst.mVarIndex = vdec->mVarIndex;
vins->mConst.mOperandSize = vdec->mSize;
vins->mConst.mIntConst = vdec->mOffset;
}
block->Append(vins);

View File

@ -1,4 +1,5 @@
#include "NativeCodeGenerator.h"
#include "CompilerTypes.h"
static const int CPU_REG_A = 256;
static const int CPU_REG_X = 257;
@ -6791,7 +6792,9 @@ bool NativeCodeBasicBlock::MergeBasicBlocks(void)
{
mVisited = true;
while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this)
if (!mLocked)
{
while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this && !mTrueJump->mLocked)
{
for (int i = 0; i < mTrueJump->mIns.Size(); i++)
mIns.Push(mTrueJump->mIns[i]);
@ -6800,6 +6803,7 @@ bool NativeCodeBasicBlock::MergeBasicBlocks(void)
mTrueJump = mTrueJump->mTrueJump;
changed = true;
}
}
if (mTrueJump)
mTrueJump->MergeBasicBlocks();
@ -6909,6 +6913,80 @@ bool NativeCodeBasicBlock::ApplyEntryDataSet(void)
return changed;
}
void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mIns.Size(); i++)
{
switch (mIns[i].mMode)
{
case ASMIM_ZERO_PAGE:
used += mIns[i].mAddress;
break;
case ASMIM_INDIRECT_Y:
used += mIns[i].mAddress + 0;
used += mIns[i].mAddress + 1;
break;
case ASMIM_ABSOLUTE:
if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject)
{
LinkerObject* lo = mIns[i].mLinkerObject;
for (int i = 0; i < lo->mNumTemporaries; i++)
{
for (int j = 0; j < lo->mTempSizes[i]; j++)
used += lo->mTemporaries[i] + j;
}
}
break;
}
}
if (mTrueJump)
mTrueJump->CollectZeroPageUsage(used);
if (mFalseJump)
mFalseJump->CollectZeroPageUsage(used);
}
}
void NativeCodeBasicBlock::RemapZeroPage(const uint8* remap)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mIns.Size(); i++)
{
switch (mIns[i].mMode)
{
case ASMIM_ZERO_PAGE:
case ASMIM_INDIRECT_Y:
mIns[i].mAddress = remap[mIns[i].mAddress];
break;
case ASMIM_ABSOLUTE:
if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject)
{
LinkerObject* lo = mIns[i].mLinkerObject;
for (int j = 0; j < lo->mNumTemporaries; j++)
{
lo->mTemporaries[j] = remap[lo->mTemporaries[j]];
}
}
break;
}
}
if (mTrueJump)
mTrueJump->RemapZeroPage(remap);
if (mFalseJump)
mFalseJump->RemapZeroPage(remap);
}
}
bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const
{
if (mIns.Size() > 0)
@ -8765,6 +8843,7 @@ NativeCodeBasicBlock::NativeCodeBasicBlock(void)
mKnownShortBranch = false;
mBypassed = false;
mAssembled = false;
mLocked = false;
}
NativeCodeBasicBlock::~NativeCodeBasicBlock(void)
@ -8783,8 +8862,62 @@ NativeCodeProcedure::~NativeCodeProcedure(void)
}
void NativeCodeProcedure::CompressTemporaries(void)
{
if (mInterProc->mTempSize > 16)
{
ResetVisited();
NumberSet used(256);
mEntryBlock->CollectZeroPageUsage(used);
uint8 remap[256];
for (int i = 0; i < 256; i++)
remap[i] = i;
int tpos = BC_REG_TMP_SAVED;
for (int i = 0; i < mInterProc->mTempOffset.Size(); i++)
{
bool tused = false;
int reg = BC_REG_TMP + mInterProc->mTempOffset[i];
if (reg >= BC_REG_TMP_SAVED)
{
int size = mInterProc->mTempSizes[i];
for (int j = 0; j < size; j++)
if (used[reg + j])
tused = true;
if (tused)
{
for (int j = 0; j < size; j++)
remap[reg + j] = tpos + j;
mInterProc->mTempOffset[i] = tpos - BC_REG_TMP;
tpos += size;
}
else
{
mInterProc->mTempOffset[i] = 0;
mInterProc->mTempSizes[i] = 0;
}
}
}
ResetVisited();
mEntryBlock->RemapZeroPage(remap);
mInterProc->mTempSize = tpos - BC_REG_TMP;
}
}
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{
mInterProc = proc;
int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks];
for (int i = 0; i < nblocks; i++)
@ -8800,122 +8933,145 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
commonFrameSize += 2;
mFrameOffset = 0;
mNoFrame = (stackExpand + proc->mCommonFrameSize) < 64 && !proc->mHasDynamicStack && !(proc->mHasInlineAssembler && !proc->mLeafProcedure);
mNoFrame = (stackExpand + proc->mCommonFrameSize) < 64 && !proc->mHasDynamicStack;// && !(proc->mHasInlineAssembler && !proc->mLeafProcedure);
if (mNoFrame)
proc->mLinkerObject->mFlags |= LOBJF_NO_FRAME;
entryBlock = new NativeCodeBasicBlock();
mBlocks.Push(entryBlock);
entryBlock->mNoFrame = mNoFrame;
entryBlock->mIndex = 0;
if (mNoFrame)
{
if (stackExpand > 0)
mFrameOffset = tempSave;
}
else
{
stackExpand += 2;
}
// generator->mByteCodeUsed[BC_NATIVE] = true;
if (!proc->mLeafProcedure)
{
if (mNoFrame)
mFrameOffset = commonFrameSize + tempSave;
}
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));
mEntryBlock = AllocateBlock();
mEntryBlock->mLocked = true;
mBlocks.Push(mEntryBlock);
mExitBlock = AllocateBlock();
mExitBlock->mLocked = true;
mBlocks.Push(mExitBlock);
mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]);
mEntryBlock->mBranch = ASMIT_JMP;
// Place a temporary RTS
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
Optimize();
assert(mEntryBlock->mIns.Size() == 0);
// Remove temporary RTS
mExitBlock->mIns.Pop();
CompressTemporaries();
tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
if (!(mGenerator->mCompilerOptions & COPT_NATIVE))
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));
if (mNoFrame)
{
if (stackExpand > 0)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
if (tempSave)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
if (tempSave > 1)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
}
}
mFrameOffset = tempSave;
}
}
else
{
stackExpand += 2;
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
if (tempSave)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
if (tempSave > 1)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
}
}
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, tempSave + 2));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, tempSave + 2));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
}
if (!proc->mLeafProcedure)
{
if (commonFrameSize > 0)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
if (mNoFrame)
mFrameOffset = commonFrameSize + tempSave;
}
entryBlock->mFrameOffset = mFrameOffset;
tblocks[0] = entryBlock;
exitBlock = AllocateBlock();
mBlocks.Push(exitBlock);
if (!proc->mLeafProcedure && commonFrameSize > 0)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
if (mNoFrame)
@ -8924,63 +9080,85 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{
if (tempSave)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
if (tempSave > 1)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
}
}
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
}
else
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
if (tempSave)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
if (tempSave > 1)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
}
}
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
mEntryBlock->Assemble();
int total, base;
NativeCodeBasicBlock* lentryBlock = mEntryBlock->BypassEmptyBlocks();
total = 0;
lentryBlock->CalculateOffset(total);
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
lentryBlock->CopyCode(this, proc->mLinkerObject->AddSpace(total));
for (int i = 0; i < mRelocations.Size(); i++)
{
LinkerReference& rl(mRelocations[i]);
rl.mObject = proc->mLinkerObject;
if (!rl.mRefObject)
rl.mRefObject = proc->mLinkerObject;
proc->mLinkerObject->AddReference(rl);
}
}
void NativeCodeProcedure::Optimize(void)
{
#if 1
int step = 0;
@ -8997,52 +9175,52 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mBlocks[i]->mLoopHead = false;
mBlocks[i]->mFromJump = nullptr;
}
entryBlock->CountEntries(nullptr);
mEntryBlock->CountEntries(nullptr);
#if 1
do
{
BuildDataFlowSets();
ResetVisited();
changed = entryBlock->RemoveUnusedResultInstructions();
changed = mEntryBlock->RemoveUnusedResultInstructions();
ResetVisited();
NativeRegisterDataSet data;
if (entryBlock->ValueForwarding(data))
if (mEntryBlock->ValueForwarding(data))
changed = true;
} while (changed);
#endif
ResetVisited();
if (entryBlock->PeepHoleOptimizer())
if (mEntryBlock->PeepHoleOptimizer())
changed = true;
ResetVisited();
if (entryBlock->OptimizeSimpleLoop(this))
if (mEntryBlock->OptimizeSimpleLoop(this))
changed = true;
ResetVisited();
if (entryBlock->MergeBasicBlocks())
if (mEntryBlock->MergeBasicBlocks())
changed = true;
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mEntryBlocks.SetSize(0);
entryBlock->CollectEntryBlocks(nullptr);
mEntryBlock->CollectEntryBlocks(nullptr);
if (step > 2)
{
ResetVisited();
if (entryBlock->JoinTailCodeSequences())
if (mEntryBlock->JoinTailCodeSequences())
changed = true;
}
#if 1
ResetVisited();
NativeRegisterDataSet data;
entryBlock->BuildEntryDataSet(data);
mEntryBlock->BuildEntryDataSet(data);
ResetVisited();
if (entryBlock->ApplyEntryDataSet())
if (mEntryBlock->ApplyEntryDataSet())
changed = true;
#endif
if (!changed && step < 4)
@ -9053,27 +9231,6 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
} while (changed);
#endif
entryBlock->Assemble();
int total, base;
NativeCodeBasicBlock* lentryBlock = entryBlock->BypassEmptyBlocks();
total = 0;
lentryBlock->CalculateOffset(total);
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
lentryBlock->CopyCode(this, proc->mLinkerObject->AddSpace(total));
for (int i = 0; i < mRelocations.Size(); i++)
{
LinkerReference& rl(mRelocations[i]);
rl.mObject = proc->mLinkerObject;
if (!rl.mRefObject)
rl.mRefObject = proc->mLinkerObject;
proc->mLinkerObject->AddReference(rl);
}
}
void NativeCodeProcedure::BuildDataFlowSets(void)
@ -9397,12 +9554,12 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
}
}
block->Close(exitBlock, nullptr, ASMIT_JMP);
block->Close(mExitBlock, nullptr, ASMIT_JMP);
return;
}
case IC_RETURN:
block->Close(exitBlock, nullptr, ASMIT_JMP);
block->Close(mExitBlock, nullptr, ASMIT_JMP);
return;
case IC_TYPECAST:
@ -9443,7 +9600,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker)
: mErrors(errors), mLinker(linker), mRuntime({ 0 })
: mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT), mRuntime({ 0 })
{
}

View File

@ -105,7 +105,7 @@ public:
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
int mOffset, mSize, mNumEntries, mNumEntered, mFrameOffset;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked;
NativeRegisterDataSet mDataSet, mNDataSet;
@ -183,6 +183,9 @@ public:
void BuildEntryDataSet(const NativeRegisterDataSet& set);
bool ApplyEntryDataSet(void);
void CollectZeroPageUsage(NumberSet& used);
void RemapZeroPage(const uint8* remap);
};
class NativeCodeProcedure
@ -191,11 +194,13 @@ class NativeCodeProcedure
NativeCodeProcedure(NativeCodeGenerator* generator);
~NativeCodeProcedure(void);
NativeCodeBasicBlock* entryBlock, * exitBlock;
NativeCodeBasicBlock* mEntryBlock, * mExitBlock;
NativeCodeBasicBlock** tblocks;
NativeCodeGenerator* mGenerator;
InterCodeProcedure* mInterProc;
int mProgStart, mProgSize, mIndex, mFrameOffset;
bool mNoFrame;
int mTempBlocks;
@ -204,12 +209,15 @@ class NativeCodeProcedure
GrowingArray < NativeCodeBasicBlock*> mBlocks;
void Compile(InterCodeProcedure* proc);
void Optimize(void);
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
NativeCodeBasicBlock* AllocateBlock(void);
NativeCodeBasicBlock* TransientBlock(void);
void CompileInterBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* iblock, NativeCodeBasicBlock*block);
void CompressTemporaries(void);
void BuildDataFlowSets(void);
void ResetVisited(void);
@ -223,6 +231,8 @@ public:
void RegisterRuntime(const Ident * ident, LinkerObject * object, int offset);
uint64 mCompilerOptions;
struct Runtime
{
const Ident * mIdent;

View File

@ -75,7 +75,7 @@ int main(int argc, const char** argv)
DWORD length = ::GetModuleFileNameA(NULL, basePath, sizeof(basePath));
#else
printf("Starting oscar64 1.1.42\n");
printf("Starting oscar64 1.1.43\n");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,42,0
PRODUCTVERSION 1,1,42,0
FILEVERSION 1,1,43,0
PRODUCTVERSION 1,1,43,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.1.42.0"
VALUE "FileVersion", "1.1.43.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.1.42.0"
VALUE "ProductVersion", "1.1.43.0"
END
END
BLOCK "VarFileInfo"

View File

@ -28,6 +28,12 @@
}
"Entry"
{
"MsmKey" = "8:_1F88FA4F35F043B3ABFCB552FCEA5CDD"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_216D2A5FECF74C96A4964A74DFEB8552"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -106,6 +112,12 @@
}
"Entry"
{
"MsmKey" = "8:_A566398810C1458E8E063A81FA88D46F"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_B4265CBF352343D2867DBCCE67D9F493"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -118,6 +130,12 @@
}
"Entry"
{
"MsmKey" = "8:_C72E9CB8EC154F9BA499FAC968B83A93"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_D0E45B48D76B4407B0BDE4378C1DB2C7"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -303,6 +321,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1F88FA4F35F043B3ABFCB552FCEA5CDD"
{
"SourcePath" = "8:..\\include\\c64\\rasterirq.c"
"TargetName" = "8:rasterirq.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}:_216D2A5FECF74C96A4964A74DFEB8552"
{
"SourcePath" = "8:..\\include\\stdbool.h"
@ -563,6 +601,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A566398810C1458E8E063A81FA88D46F"
{
"SourcePath" = "8:..\\include\\stddef.h"
"TargetName" = "8:stddef.h"
"Tag" = "8:"
"Folder" = "8:_7C0D28C244F14A21B5F72213BBE59B6F"
"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}:_B4265CBF352343D2867DBCCE67D9F493"
{
"SourcePath" = "8:..\\include\\c64\\joystick.c"
@ -603,6 +661,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C72E9CB8EC154F9BA499FAC968B83A93"
{
"SourcePath" = "8:..\\include\\c64\\rasterirq.h"
"TargetName" = "8:rasterirq.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}:_D0E45B48D76B4407B0BDE4378C1DB2C7"
{
"SourcePath" = "8:..\\include\\stdlib.h"
@ -872,15 +950,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{BE34D2A8-161C-4DA2-972D-BBF520134E2C}"
"PackageCode" = "8:{B497440C-3E40-4996-868C-98739B7F7C7B}"
"ProductCode" = "8:{9CDBFF70-1B69-46D4-AF9A-421A9A0A39A3}"
"PackageCode" = "8:{5E5D8444-E4D7-49D3-B597-D5F498EC44BE}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.1.42"
"ProductVersion" = "8:1.1.43"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"