From 34220b96e3fb4f119e2dcadcea62bd86c70b1388 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 2 Feb 2022 22:05:55 +0100 Subject: [PATCH] Add auto generation of multiplier tables if variable factor is known to be small --- oscar64/Compiler.cpp | 16 ++--- oscar64/Disassembler.cpp | 53 +++++++++------- oscar64/Disassembler.h | 3 +- oscar64/Linker.cpp | 4 +- oscar64/NativeCodeGenerator.cpp | 104 ++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 14 ++++- oscar64/Parser.cpp | 4 +- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 +-- oscar64setup/oscar64setup.vdproj | 6 +- 10 files changed, 169 insertions(+), 45 deletions(-) diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 8a7e75a..5391a31 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -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); diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 05c8895..71b431b 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -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,31 +613,38 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int sta char tbuffer[10], abuffer[100]; - int ip = start; - while (ip < start + size) + if (lobj->mSection->mType == LST_BSS) { - int n = 16; - if (ip + n > start + size) - n = start + size - ip; - - fprintf(file, "%04x : __ __ __ BYT", ip); - - for (int i = 0; i < n; i++) - fprintf(file, " %02x", memory[ip + i]); - for(int i=n; i<16; i++) - fprintf(file, " "); - fprintf(file, " : "); - for (int i = 0; i < n; i++) + fprintf(file, "%04x : __ __ __ BSS\t%d\n", start, size); + } + else + { + int ip = start; + while (ip < start + size) { - int k = memory[ip + i]; - if (k >= 32 && k < 128) - fprintf(file, "%c", k); - else - fprintf(file, "."); - } - fprintf(file, "\n"); + int n = 16; + if (ip + n > start + size) + n = start + size - ip; - ip += n; + fprintf(file, "%04x : __ __ __ BYT", ip); + + for (int i = 0; i < n; i++) + fprintf(file, " %02x", memory[ip + i]); + for (int i = n; i < 16; i++) + fprintf(file, " "); + fprintf(file, " : "); + for (int i = 0; i < n; i++) + { + int k = memory[ip + i]; + if (k >= 32 && k < 128) + fprintf(file, "%c", k); + else + fprintf(file, "."); + } + fprintf(file, "\n"); + + ip += n; + } } } diff --git a/oscar64/Disassembler.h b/oscar64/Disassembler.h index 99d3526..460a5c4 100644 --- a/oscar64/Disassembler.h +++ b/oscar64/Disassembler.h @@ -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); diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 39657bc..2209ea2 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -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); } } } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 78322bb..3730386 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 28d3142..f0e050b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -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 mRuntime; + GrowingArray mMulTables; }; \ No newline at end of file diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 11666ad..324c41e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -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 diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 501bc97..161eb9d 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -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); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 0eb3c43..e32e466 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -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" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 195c784..0c3c570 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -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:"