Add auto generation of multiplier tables if variable factor is known to be small

This commit is contained in:
drmortalwombat 2022-02-02 22:05:55 +01:00
parent c6133ce7c0
commit 34220b96e3
10 changed files with 169 additions and 45 deletions

View File

@ -14,21 +14,21 @@ Compiler::Compiler(void)
mErrors = new Errors();
mLinker = new Linker(mErrors);
mCompilationUnits = new CompilationUnits(mErrors);
mPreprocessor = new Preprocessor(mErrors);
mByteCodeGenerator = new ByteCodeGenerator(mErrors, mLinker);
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker);
mInterCodeModule = new InterCodeModule();
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
mCompilationUnits->mLinker = mLinker;
mCompilationUnits->mSectionCode = mLinker->AddSection(Ident::Unique("code"), LST_DATA);
mCompilationUnits->mSectionData = mLinker->AddSection(Ident::Unique("data"), LST_DATA);
mCompilationUnits->mSectionBSS = mLinker->AddSection(Ident::Unique("bss"), LST_BSS);
mCompilationUnits->mSectionHeap = mLinker->AddSection(Ident::Unique("heap"), LST_HEAP);
mCompilationUnits->mSectionStack = mLinker->AddSection(Ident::Unique("stack"), LST_STACK);
mCompilationUnits->mSectionStack->mSize = 4096;
mPreprocessor = new Preprocessor(mErrors);
mByteCodeGenerator = new ByteCodeGenerator(mErrors, mLinker);
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode);
mInterCodeModule = new InterCodeModule();
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
}
Compiler::~Compiler(void)
@ -343,6 +343,8 @@ bool Compiler::GenerateCode(void)
}
}
mNativeCodeGenerator->CompleteRuntime();
mLinker->CollectReferences();
mLinker->ReferenceObject(dcrtstart->mLinkerObject);

View File

@ -603,7 +603,7 @@ NativeCodeDisassembler::~NativeCodeDisassembler(void)
}
void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker)
void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker, LinkerObject * lobj)
{
fprintf(file, "--------------------------------------------------------------------\n");
if (proc && proc->mIdent)
@ -613,6 +613,12 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int sta
char tbuffer[10], abuffer[100];
if (lobj->mSection->mType == LST_BSS)
{
fprintf(file, "%04x : __ __ __ BSS\t%d\n", start, size);
}
else
{
int ip = start;
while (ip < start + size)
{
@ -640,6 +646,7 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int sta
ip += n;
}
}
}
void NativeCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident * ident, Linker* linker)
{

View File

@ -7,6 +7,7 @@
class ByteCodeGenerator;
class InterCodeProcedure;
class Linker;
class LinkerObject;
class ByteCodeDisassembler
{
@ -27,7 +28,7 @@ public:
~NativeCodeDisassembler(void);
void Disassemble(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker);
void DumpMemory(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker);
void DumpMemory(FILE* file, const uint8* memory, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker, LinkerObject * lobj);
protected:
const char* TempName(uint8 tmp, char* buffer, InterCodeProcedure* proc);
const char* AddrName(int addr, char* buffer, Linker* linker);

View File

@ -646,9 +646,9 @@ bool Linker::WriteAsmFile(const char* filename)
break;
case LOT_DATA:
if (obj->mRegion->mCartridge < 0)
mNativeDisassembler.DumpMemory(file, mMemory, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
mNativeDisassembler.DumpMemory(file, mMemory, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
else
mNativeDisassembler.DumpMemory(file, mCartridge[obj->mRegion->mCartridge] - 0x8000, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
mNativeDisassembler.DumpMemory(file, mCartridge[obj->mRegion->mCartridge] - 0x8000, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
}
}
}

View File

@ -4873,6 +4873,36 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
lshift++;
}
if (mul > 1 && (lshift > 3 || lmul != 1) && ins->mSrc[index].IsUByte() && ins->mSrc[index].mRange.mMaxValue < 16)
{
int dreg = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
if (sins)
{
LoadValueToReg(proc, sins, dreg, nullptr, nullptr);
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, dreg));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[index].mTemp]));
}
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(mul, ins->mSrc[index].mRange.mMaxValue + 1, false)));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg));
if (ins->mDst.IsUByte())
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, 0, nproc->mGenerator->AllocateShortMulTable(mul, ins->mSrc[index].mRange.mMaxValue + 1, true)));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg));
}
return dreg;
}
if (lmul == 1 && !sins && ins->mSrc[index].mTemp == ins->mDst.mTemp)
{
// shift in place
@ -14075,6 +14105,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
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 + 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 + 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;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
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 + 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 + 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;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress && !(mIns[i + 1].mLive & LIVE_MEM) &&
@ -16484,8 +16534,8 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
}
NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker)
: mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT), mRuntime({ 0 })
NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker, LinkerSection* runtimeSection)
: mErrors(errors), mLinker(linker), mRuntimeSection(runtimeSection), mCompilerOptions(COPT_DEFAULT), mRuntime({ 0 }), mMulTables({nullptr})
{
}
@ -16494,6 +16544,56 @@ NativeCodeGenerator::~NativeCodeGenerator(void)
}
void NativeCodeGenerator::CompleteRuntime(void)
{
for (int i = 0; i < mMulTables.Size(); i++)
{
const MulTable& m(mMulTables[i]);
m.mLinkerLSB->AddSpace(m.mSize);
m.mLinkerMSB->AddSpace(m.mSize);
for (int j = 0; j < m.mSize; j++)
{
m.mLinkerLSB->mData[j] = (uint8)(m.mFactor * j);
m.mLinkerMSB->mData[j] = (uint8)(m.mFactor * j >> 8);
}
}
}
LinkerObject* NativeCodeGenerator::AllocateShortMulTable(int factor, int size, bool msb)
{
int i = 0;
while (i < mMulTables.Size() && mMulTables[i].mFactor != factor)
i++;
if (i == mMulTables.Size())
{
Location loc;
MulTable mt;
char name[20];
sprintf_s(name, "__multab%dL", factor);
mt.mLinkerLSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
sprintf_s(name, "__multab%dH", factor);
mt.mLinkerMSB = mLinker->AddObject(loc, Ident::Unique(name), mRuntimeSection, LOT_DATA);
mt.mFactor = factor;
mt.mSize = size;
mMulTables.Push(mt);
return msb ? mt.mLinkerMSB : mt.mLinkerLSB;
}
else
{
if (size > mMulTables[i].mSize)
mMulTables[i].mSize = size;
return msb ? mMulTables[i].mLinkerMSB : mMulTables[i].mLinkerLSB;
}
}
NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* ident)
{
int i = 0;

View File

@ -297,10 +297,11 @@ class NativeCodeProcedure
class NativeCodeGenerator
{
public:
NativeCodeGenerator(Errors * errors, Linker* linker);
NativeCodeGenerator(Errors * errors, Linker* linker, LinkerSection * runtimeSection);
~NativeCodeGenerator(void);
void RegisterRuntime(const Ident * ident, LinkerObject * object, int offset);
void CompleteRuntime(void);
uint64 mCompilerOptions;
@ -311,9 +312,20 @@ public:
int mOffset;
};
struct MulTable
{
LinkerObject* mLinkerLSB, * mLinkerMSB;
int mFactor, mSize;
};
LinkerObject* AllocateShortMulTable(int factor, int size, bool msb);
Runtime& ResolveRuntime(const Ident* ident);
Errors* mErrors;
Linker* mLinker;
LinkerSection* mRuntimeSection;
GrowingArray<Runtime> mRuntime;
GrowingArray<MulTable> mMulTables;
};

View File

@ -84,7 +84,9 @@ Declaration* Parser::ParseStructDeclaration(uint32 flags, DecType dt)
if (offset > dec->mSize)
dec->mSize = offset;
dec->mScope->Insert(mdec->mIdent, mdec);
if (dec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent->mString);
if (mlast)
mlast->mNext = mdec;
else

View File

@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.4.78");
strcpy(strProductVersion, "1.4.79");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);

View File

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

View File

@ -3570,15 +3570,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{A63EF9D9-9EA0-4598-BE7F-C7F90A3FFEAA}"
"PackageCode" = "8:{B344F37B-0769-452A-BFC4-40EB21102D3C}"
"ProductCode" = "8:{71389DF5-8242-4F93-B029-00DDD7917F3C}"
"PackageCode" = "8:{62C0C282-BD8F-4744-A840-97FC2BF956FF}"
"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.4.78"
"ProductVersion" = "8:1.4.79"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"