From eebc39e53acda2916e1f8576a7347dd620935083 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 21 Sep 2021 20:44:19 +0200 Subject: [PATCH] Fix return type coercion, region based linker --- include/stdio.c | 164 +++++++++++--------- oscar64/CompilationUnits.h | 3 + oscar64/Compiler.cpp | 40 +++-- oscar64/Declaration.h | 6 +- oscar64/Emulator.cpp | 8 +- oscar64/InterCodeGenerator.cpp | 2 + oscar64/Linker.cpp | 115 ++++++++------ oscar64/Linker.h | 32 +++- oscar64/NativeCodeGenerator.cpp | 251 ++++++++++++++++++++----------- oscar64/NativeCodeGenerator.h | 4 + oscar64/Parser.cpp | 4 +- oscar64/Parser.h | 2 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 6 +- 14 files changed, 400 insertions(+), 245 deletions(-) diff --git a/include/stdio.c b/include/stdio.c index 8f34cee..d875831 100644 --- a/include/stdio.c +++ b/include/stdio.c @@ -101,14 +101,14 @@ void * putstrstr(void * handle, const char * str) struct sinfo { char fill; - int width, precision; + char width, precision; unsigned base; bool sign, left, prefix; }; -void nformi(const sinfo * si, char * str, int v, bool s) +int nformi(const sinfo * si, char * str, int v, bool s) { - char buffer[10]; + char * sp = str; unsigned int u = v; bool neg = false; @@ -119,7 +119,7 @@ void nformi(const sinfo * si, char * str, int v, bool s) u = -v; } - int i = 0; + char i = 10; while (u > 0) { int c = u % si->base; @@ -127,49 +127,53 @@ void nformi(const sinfo * si, char * str, int v, bool s) c += 'A' - 10; else c += '0'; - buffer[i++] = c; + sp[--i] = c; u /= si->base; } - int digits = si->precision >= 0 ? si->precision : 1; + int digits = si->precision != 255 ? 10 - si->precision : 9; - while (i < digits) - buffer[i++] = '0'; + while (i > digits) + sp[--i] = '0'; if (si->prefix && si->base == 16) { - buffer[i++] = 'X'; - buffer[i++] = '0'; + sp[--i] = 'X'; + sp[--i] = '0'; } if (neg) - buffer[i++] = '-'; + sp[--i] = '-'; else if (si->sign) - buffer[i++] = '+'; + sp[--i] = '+'; - while (i < si->width) - buffer[i++] = si->fill; + while (i > 10 - si->width) + sp[--i] = si->fill; - while (i > 0) - *str++ = buffer[--i]; - *str++ = 0; + char j = 0; + while (i < 10) + sp[j++] = sp[i++]; + + return j; } -void nformf(const sinfo * si, char * str, float f, char type) +int nformf(const sinfo * si, char * str, float f, char type) { - int d = 0; + char * sp = str; + + char d = 0; if (f < 0.0) { f = -f; - str[d++] = '-'; + sp[d++] = '-'; } else if (si->sign) - str[d++] = '+'; + sp[d++] = '+'; int exp = 0; - int fdigits = si->precision >= 0 ? si->precision : 6; + char fdigits = si->precision != 255 ? si->precision : 6; if (f != 0.0) { @@ -193,7 +197,7 @@ void nformf(const sinfo * si, char * str, float f, char type) } - int digits = fdigits + 1; + char digits = fdigits + 1; bool fexp = type == 'e'; if (type == 'g') @@ -211,10 +215,10 @@ void nformf(const sinfo * si, char * str, float f, char type) } digits = fdigits + exp + 1; - float s = 0.5; - for(int i=1; i= 10.0) { f /= 10.0; @@ -223,10 +227,10 @@ void nformf(const sinfo * si, char * str, float f, char type) } else { - float s = 0.5; - for(int i=0; i= 10.0) { f /= 10.0; @@ -234,53 +238,55 @@ void nformf(const sinfo * si, char * str, float f, char type) } } - int pdigits = digits - fdigits; + char pdigits = digits - fdigits; if (digits > 20) digits = 20; if (pdigits == 0) - str[d++] = '0'; + sp[d++] = '0'; - for(int i=0; iwidth) { - for(int i=0; i<=d; i++) - str[si->width - i] = str[d - i]; - for(int i=0; iwidth-d; i++) - str[i] = ' ' + for(char i=1; i<=d; i++) + sp[si->width - i] = sp[d - i]; + for(char i=0; iwidth-d; i++) + sp[i] = ' '; + d = si->width; } + + return d; } -void * sformat(void * data, putstrfn fn, const char * fmt, int * fps) +char * sformat(char * buff, const char * fmt, int * fps, bool print) { const char * p = fmt; - char c, buff[21]; + char c; int bi = 0; sinfo si; @@ -290,15 +296,20 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps) { if (bi) { - buff[bi] = 0; - data = fn(data, buff); - bi = 0; + if (print) + { + buff[bi] = 0; + puts(buff); + } + else + buff += bi; + bi = 0; } c = *p++; si.base = 10; si.width = 1; - si.precision = -1; + si.precision = 255; si.fill = ' '; si.sign = false; si.left = false; @@ -342,32 +353,35 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps) if (c == 'd') { - nformi(&si, buff, *fps++, true); - data = fn(data, buff); + bi = nformi(&si, buff, *fps++, true); } else if (c == 'u') { - nformi(&si, buff, *fps++, false); - data = fn(data, buff); + bi = nformi(&si, buff, *fps++, false); } else if (c == 'x') { si.base = 16; - nformi(&si, buff, *fps++, false); - data = fn(data, buff); + bi = nformi(&si, buff, *fps++, false); } #ifndef NOFLOAT else if (c == 'f' || c == 'g' || c == 'e') { - nformf(&si, buff, *(float *)fps, c); - data = fn(data, buff); + bi = nformf(&si, buff, *(float *)fps, c); fps ++; fps ++; } #endif else if (c == 's') { - data = fn(data, (char *)*fps++); + char * sp = (char *)*fps++; + if (print) + puts(sp); + else + { + while (char c = *sp++) + *buff++ = c; + } } else if (c == 'c') { @@ -381,32 +395,40 @@ void * sformat(void * data, putstrfn fn, const char * fmt, int * fps) else { buff[bi++] = c; - if (bi == 10) + if (bi >= 10) { - buff[bi] = 0; - data = fn(data, buff); - bi = 0; + if (print) + { + buff[bi] = 0; + puts(buff); + } + else + buff += bi; + bi = 0; } } } + buff[bi] = 0; if (bi) { - buff[bi] = 0; - data = fn(data, buff); - bi = 0; + if (print) + puts(buff); + else + buff += bi; } - return data; + return buff; } void printf(const char * fmt, ...) { - sformat(nullptr, putstrio, fmt, (int *)&fmt + 1); + char buff[40]; + sformat(buff, fmt, (int *)&fmt + 1, true); } int sprintf(char * str, const char * fmt, ...) { - char * d = (char *)(sformat(str, putstrstr, fmt, (int *)&fmt + 1)); + char * d = sformat(str, fmt, (int *)&fmt + 1, false); return d - str; } diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index 2cbc08b..3df1276 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -2,6 +2,7 @@ #include "Declaration.h" #include "Errors.h" +#include "Linker.h" class CompilationUnit { @@ -26,6 +27,8 @@ public: DeclarationScope* mRuntimeScope; + LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack; + bool AddUnit(Location & location, const char* name, const char * from); CompilationUnit* PendingUnit(void); protected: diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 159e964..71da0d1 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -19,6 +19,12 @@ Compiler::Compiler(void) mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker); mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker); mInterCodeModule = new InterCodeModule(); + + mCompilationUnits->mSectionCode = mLinker->AddSection(Ident::Unique("code"), 0); + mCompilationUnits->mSectionData = mLinker->AddSection(Ident::Unique("data"), 0); + mCompilationUnits->mSectionBSS = mLinker->AddSection(Ident::Unique("bss"), 0); + mCompilationUnits->mSectionHeap = mLinker->AddSection(Ident::Unique("heap"), 0); + mCompilationUnits->mSectionStack = mLinker->AddSection(Ident::Unique("stack"), 0); } Compiler::~Compiler(void) @@ -112,13 +118,25 @@ bool Compiler::GenerateCode(void) return false; } - const Ident* sectionStartup = Ident::Unique("startup"); - const Ident* sectionBytecode = Ident::Unique("bytecode"); - const Ident* sectionCode = Ident::Unique("code"); + const Ident* identStartup = Ident::Unique("startup"); + const Ident* identBytecode = Ident::Unique("bytecode"); + const Ident* identMain = Ident::Unique("main"); + const Ident* identCode = Ident::Unique("code"); - mLinker->AddSection(sectionStartup, 0x0801, 0x00ff); - mLinker->AddSection(sectionBytecode, 0x0900, 0x0100); - mLinker->AddSection(sectionCode, 0x0a00, 0x8000); + LinkerRegion * regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900); + LinkerRegion * regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00); + LinkerRegion * regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000); + + LinkerSection * sectionStartup = mLinker->AddSection(identStartup, 0); + LinkerSection * sectionBytecode = mLinker->AddSection(identBytecode, 0); + + regionStartup->mSections.Push(sectionStartup); + regionBytecode->mSections.Push(sectionBytecode); + regionMain->mSections.Push(mCompilationUnits->mSectionCode); + regionMain->mSections.Push(mCompilationUnits->mSectionData); + regionMain->mSections.Push(mCompilationUnits->mSectionBSS); + regionMain->mSections.Push(mCompilationUnits->mSectionHeap); + regionMain->mSections.Push(mCompilationUnits->mSectionStack); dcrtstart->mSection = sectionStartup; @@ -128,14 +146,6 @@ bool Compiler::GenerateCode(void) if (mErrors->mErrorCount != 0) return false; - const Ident* imain = Ident::Unique("main"); - Declaration* dmain = mCompilationUnits->mScope->Lookup(imain); - if (!dmain) - { - mErrors->Error(loc, EERR_OBJECT_NOT_FOUND, "main function not found"); - return false; - } - // Register native runtime functions RegisterRuntime(loc, Ident::Unique("mul16by8")); @@ -158,8 +168,6 @@ bool Compiler::GenerateCode(void) // - InterCodeProcedure* iproc = mInterCodeGenerator->TranslateProcedure(mInterCodeModule, dmain->mValue, dmain); - if (mErrors->mErrorCount != 0) return false; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 2365458..03a26a7 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -6,6 +6,7 @@ #include "Assembler.h" class LinkerObject; +class LinkerSection; enum DecType { @@ -156,8 +157,9 @@ public: __int64 mInteger; double mNumber; uint32 mFlags; - const Ident * mIdent, * mSection; - const uint8* mData; + const Ident * mIdent; + LinkerSection * mSection; + const uint8 * mData; LinkerObject * mLinkerObject; bool CanAssign(const Declaration* fromType) const; diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index 0c6def0..8865258 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -582,7 +582,7 @@ int Emulator::Emulate(int startIP) int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1]; int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1]; int sp = mMemory[BC_REG_STACK] + 256 * mMemory[BC_REG_STACK + 1]; - printf("%04x (A:%04x P:%04x S:%04x) %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr, accu, ptr, sp, + printf("%04x (A:%04x P:%04x S:%04x) %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x : %04x\n", addr, accu, ptr, sp, mMemory[BC_REG_TMP + 0] + 256 * mMemory[BC_REG_TMP + 1], mMemory[BC_REG_TMP + 2] + 256 * mMemory[BC_REG_TMP + 3], mMemory[BC_REG_TMP + 4] + 256 * mMemory[BC_REG_TMP + 5], @@ -601,7 +601,11 @@ int Emulator::Emulate(int startIP) mMemory[BC_REG_TMP + 24] + 256 * mMemory[BC_REG_TMP + 25], mMemory[BC_REG_TMP + 26] + 256 * mMemory[BC_REG_TMP + 27], mMemory[BC_REG_TMP + 28] + 256 * mMemory[BC_REG_TMP + 29], - mMemory[BC_REG_TMP + 30] + 256 * mMemory[BC_REG_TMP + 31] + mMemory[BC_REG_TMP + 30] + 256 * mMemory[BC_REG_TMP + 31], + + mMemory[0x9f9e] + 256 * mMemory[0x9f9f] + + ); } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2fd1612..2b5f543 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1591,6 +1591,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!procType->mBase->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); + vr = CoerceType(proc, block, vr, procType->mBase); + ins->mSType[0] = InterTypeOf(vr.mType); ins->mSTemp[0] = vr.mTemp; ins->mCode = IC_RETURN_VALUE; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 7d73dcd..8c3cfc7 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -3,6 +3,14 @@ #include +LinkerRegion::LinkerRegion(void) + : mSections(nullptr) +{} + +LinkerSection::LinkerSection(void) + : mObjects(nullptr) +{} + void LinkerObject::AddData(const uint8* data, int size) { mSize = size; @@ -19,7 +27,7 @@ uint8* LinkerObject::AddSpace(int size) } Linker::Linker(Errors* errors) - : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr) + : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr) { } @@ -29,19 +37,39 @@ Linker::~Linker(void) } -int Linker::AddSection(const Ident* section, int start, int size) + +LinkerRegion* Linker::AddRegion(const Ident* region, int start, int end) { - LinkerSection* lsec = new LinkerSection; - lsec->mID = mSections.Size(); - lsec->mIdent = section; - lsec->mStart = start; - lsec->mSize = size; - lsec->mUsed = 0; - mSections.Push(lsec); - return lsec->mID; + LinkerRegion* lrgn = new LinkerRegion(); + lrgn->mIdent = region; + lrgn->mStart = start; + lrgn->mEnd = end; + lrgn->mUsed = 0; + mRegions.Push(lrgn); + return lrgn; } -LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, const Ident* section, LinkerObjectType type) +LinkerSection* Linker::AddSection(const Ident* section, uint32 flags) +{ + LinkerSection* lsec = new LinkerSection; + lsec->mIdent = section; + mSections.Push(lsec); + return lsec; + +} + +LinkerSection* Linker::FindSection(const Ident* section) +{ + for (int i = 0; i < mSections.Size(); i++) + { + if (mSections[i]->mIdent == section) + return mSections[i]; + } + + return nullptr; +} + +LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type) { LinkerObject* obj = new LinkerObject; obj->mLocation = location; @@ -53,6 +81,8 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, c obj->mSection = section; obj->mProc = nullptr; obj->mReferenced = false; + obj->mPlaced = false; + section->mObjects.Push(obj); mObjects.Push(obj); return obj; } @@ -79,46 +109,42 @@ void Linker::ReferenceObject(LinkerObject* obj) void Linker::Link(void) { - for (int i = 0; i < mObjects.Size(); i++) - { - LinkerObject* obj = mObjects[i]; - if (obj->mReferenced) - { - LinkerSection* lsec; - int j = 0; - while (j < mSections.Size() && !(mSections[j]->mIdent == obj->mSection && mSections[j]->mUsed + obj->mSize <= mSections[j]->mSize)) - j++; - if (j < mSections.Size()) - { - LinkerSection* lsec = mSections[j]; - obj->mLinkerSection = lsec; - obj->mAddress = lsec->mUsed; - lsec->mUsed += obj->mSize; - } - else - mErrors->Error(obj->mLocation, EERR_OUT_OF_MEMORY, "Out of space in section", obj->mSection->mString); - } - } - if (mErrors->mErrorCount == 0) { + + // Move objects into regions + + for (int i = 0; i < mRegions.Size(); i++) + { + LinkerRegion* lrgn = mRegions[i]; + for (int j = 0; j < lrgn->mSections.Size(); j++) + { + LinkerSection* lsec = lrgn->mSections[j]; + for (int k = 0; k < lsec->mObjects.Size(); k++) + { + LinkerObject* lobj = lsec->mObjects[k]; + if (lobj->mReferenced && !lobj->mPlaced && lrgn->mStart + lrgn->mUsed + lobj->mSize <= lrgn->mEnd) + { + lobj->mPlaced = true; + lobj->mAddress = lrgn->mStart + lrgn->mUsed; + lrgn->mUsed += lobj->mSize; + } + } + } + } + mProgramStart = 0x0801; mProgramEnd = 0x0801; int address = 0; - for (int i = 0; i < mSections.Size(); i++) + for (int i = 0; i < mRegions.Size(); i++) { - LinkerSection* lsec = mSections[i]; - if (lsec->mStart == 0) - lsec->mStart = address; - address = lsec->mStart + lsec->mUsed; + LinkerRegion* lrgn = mRegions[i]; + address = lrgn->mStart + lrgn->mUsed; - if (lsec->mUsed > 0) - { - if (address > mProgramEnd) - mProgramEnd = address; - } + if (lrgn->mUsed && address > mProgramEnd) + mProgramEnd = address; } for (int i = 0; i < mObjects.Size(); i++) @@ -126,7 +152,6 @@ void Linker::Link(void) LinkerObject* obj = mObjects[i]; if (obj->mReferenced) { - obj->mAddress += obj->mLinkerSection->mStart; memcpy(mMemory + obj->mAddress, obj->mData, obj->mSize); } } @@ -194,9 +219,9 @@ bool Linker::WriteMapFile(const char* filename) if (obj->mReferenced) { if (obj->mIdent) - fprintf(file, "%04x - %04x : %s, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mString); + fprintf(file, "%04x - %04x : %s, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString); else - fprintf(file, "%04x - %04x : *, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, LinkerObjectTypeNames[obj->mType], obj->mSection->mString); + fprintf(file, "%04x - %04x : *, %s:%s\n", obj->mAddress, obj->mAddress + obj->mSize, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString); } } diff --git a/oscar64/Linker.h b/oscar64/Linker.h index c3c01f5..ba67ddf 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -22,6 +22,19 @@ enum LinkerObjectType }; class LinkerObject; +class LinkerSection; + +class LinkerRegion +{ +public: + const Ident* mIdent; + + int mStart, mEnd, mUsed; + + GrowingArray mSections; + + LinkerRegion(void); +}; class LinkerReference { @@ -35,23 +48,25 @@ class LinkerSection { public: const Ident* mIdent; - int mID; - int mStart, mSize, mUsed; + + GrowingArray mObjects; + + LinkerSection(void); }; class LinkerObject { public: Location mLocation; - const Ident* mIdent, * mSection; + const Ident* mIdent; LinkerObjectType mType; int mID; int mAddress; int mSize; - LinkerSection* mLinkerSection; + LinkerSection* mSection; uint8* mData; InterCodeProcedure* mProc; - bool mReferenced; + bool mReferenced, mPlaced; void AddData(const uint8* data, int size); uint8* AddSpace(int size); @@ -63,9 +78,11 @@ public: Linker(Errors * errors); ~Linker(void); - int AddSection(const Ident* section, int start, int size); + LinkerRegion * AddRegion(const Ident* region, int start, int end); + LinkerSection * AddSection(const Ident* section, uint32 flags); + LinkerSection* FindSection(const Ident* section); - LinkerObject * AddObject(const Location & location, const Ident* ident, const Ident* section, LinkerObjectType type); + LinkerObject * AddObject(const Location & location, const Ident* ident, LinkerSection * section, LinkerObjectType type); void AddReference(const LinkerReference& ref); @@ -74,6 +91,7 @@ public: bool WriteAsmFile(const char* filename); GrowingArray mReferences; + GrowingArray mRegions; GrowingArray mSections; GrowingArray mObjects; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 637a4d2..5274c37 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -435,6 +435,15 @@ bool NativeCodeInstruction::LoadsAccu(void) const return mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || mType == ASMIT_JSR; } +bool NativeCodeInstruction::ChangesAccuAndFlag(void) const +{ + return + mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || + mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR || + mType == ASMIT_SBC || mType == ASMIT_CLC; +} + + bool NativeCodeInstruction::ChangesAddress(void) const { if (mMode != ASMIM_IMPLIED) @@ -516,6 +525,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else @@ -613,6 +623,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_X].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else @@ -643,6 +654,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_Y].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else @@ -718,6 +730,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_A].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else if (data.mRegs[mAddress].mImmediate) @@ -733,6 +746,18 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) mAddress = data.mRegs[CPU_REG_A].mValue; changed = true; } + else if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress) + { + mType = ASMIT_TXA; + mMode = ASMIM_IMPLIED; + data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X]; + } + else if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress) + { + mType = ASMIT_TYA; + mMode = ASMIM_IMPLIED; + data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y]; + } else { data.mRegs[CPU_REG_A].Reset(); @@ -753,6 +778,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else if (data.mRegs[mAddress].mImmediate) @@ -782,6 +808,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress) { mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; changed = true; } else if (data.mRegs[mAddress].mImmediate) @@ -2753,15 +2780,15 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, NativeCodePr { if (sins0) { - insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg); - insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1); + LoadValueToReg(proc, sins0, treg, nullptr, nullptr); + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); - - LoadValueToReg(proc, sins0, treg, &insl, &insh); } else { @@ -3807,13 +3834,15 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void) for (i = mIns.Size() - 1; i >= 0; i--) { - if (!mIns[i].IsUsedResultInstructions(requiredRegs)) + if (mIns[i].mType != ASMIT_NOP && !mIns[i].IsUsedResultInstructions(requiredRegs)) { if (i > 0 && mIns[i - 1].mMode == ASMIM_RELATIVE && mIns[i - 1].mAddress > 0) { mIns[i - 1].mType = ASMIT_NOP; + mIns[i - 1].mMode = ASMIM_IMPLIED; } mIns[i].mType = ASMIT_NOP; + mIns[i].mMode = ASMIM_IMPLIED; changed = true; } } @@ -3905,6 +3934,101 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) return false; } +bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + NativeRegisterDataSet ndata(data); + + if (mNumEntries != 1) + ndata.Reset(); + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].ValueForwarding(ndata)) + changed = true; + } + + if (mFalseJump) + { + switch (mBranch) + { + case ASMIT_BCS: + if (ndata.mRegs[CPU_REG_C].mImmediate) + { + mBranch = ASMIT_JMP; + if (!ndata.mRegs[CPU_REG_C].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BCC: + if (ndata.mRegs[CPU_REG_C].mImmediate) + { + mBranch = ASMIT_JMP; + if (ndata.mRegs[CPU_REG_C].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BNE: + if (ndata.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (!ndata.mRegs[CPU_REG_Z].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BEQ: + if (ndata.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (ndata.mRegs[CPU_REG_Z].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BPL: + if (ndata.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if ((ndata.mRegs[CPU_REG_Z].mValue & 0x80)) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BMI: + if (ndata.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (!(ndata.mRegs[CPU_REG_Z].mValue & 0x80)) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + } + } + + if (this->mTrueJump && this->mTrueJump->ValueForwarding(ndata)) + changed = true; + if (this->mFalseJump && this->mFalseJump->ValueForwarding(ndata)) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::PeepHoleOptimizer(void) { if (!mVisited) @@ -3913,84 +4037,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mVisited = true; - NativeRegisterDataSet data; - - for (int i = 0; i < mIns.Size(); i++) - { - mIns[i].ValueForwarding(data); - } -#if 1 - if (mFalseJump) - { - switch (mBranch) - { -#if 1 - case ASMIT_BCS: - if (data.mRegs[CPU_REG_C].mImmediate) - { - mBranch = ASMIT_JMP; - if (!data.mRegs[CPU_REG_C].mValue) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; - case ASMIT_BCC: - if (data.mRegs[CPU_REG_C].mImmediate) - { - mBranch = ASMIT_JMP; - if (data.mRegs[CPU_REG_C].mValue) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; -#endif -#if 1 - case ASMIT_BNE: - if (data.mRegs[CPU_REG_Z].mImmediate) - { - mBranch = ASMIT_JMP; - if (!data.mRegs[CPU_REG_Z].mValue) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; - case ASMIT_BEQ: - if (data.mRegs[CPU_REG_Z].mImmediate) - { - mBranch = ASMIT_JMP; - if (data.mRegs[CPU_REG_Z].mValue) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; -#endif - case ASMIT_BPL: - if (data.mRegs[CPU_REG_Z].mImmediate) - { - mBranch = ASMIT_JMP; - if ((data.mRegs[CPU_REG_Z].mValue & 0x80)) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; - case ASMIT_BMI: - if (data.mRegs[CPU_REG_Z].mImmediate) - { - mBranch = ASMIT_JMP; - if (!(data.mRegs[CPU_REG_Z].mValue & 0x80)) - mTrueJump = mFalseJump; - mFalseJump = nullptr; - changed = true; - } - break; - } - } -#endif #if 1 // move load store pairs up to initial store @@ -4113,6 +4159,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mType = mIns[i + 2].mType; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP; + progress = true; + } + else if ( + mIns[i + 0].ChangesAccuAndFlag() && + mIns[i + 1].mType == ASMIT_STA && mIns[i + 2].mType == ASMIT_LDA && + mIns[i + 1].SameEffectiveAddress(mIns[i + 2])) + { + mIns[i + 2].mType = ASMIT_NOP; + progress = true; } } @@ -4127,7 +4182,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mType = ASMIT_INC; + progress = true; } + } @@ -4143,6 +4200,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 3].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_ZERO_PAGE; mIns[i + 2].mAddress = mIns[i + 0].mAddress; + progress = true; } } #endif @@ -4555,20 +4613,29 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) bool changed; do { - BuildDataFlowSets(); - ResetVisited(); - - changed = entryBlock->RemoveUnusedResultInstructions(); - - ResetVisited(); - if (entryBlock->PeepHoleOptimizer()) - changed = true; - ResetVisited(); for (int i = 0; i < mBlocks.Size(); i++) mBlocks[i]->mNumEntries = 0; entryBlock->CountEntries(); + do + { + BuildDataFlowSets(); + ResetVisited(); + changed = entryBlock->RemoveUnusedResultInstructions(); + + ResetVisited(); + NativeRegisterDataSet data; + if (entryBlock->ValueForwarding(data)) + changed = true; + + } while (changed); + + + ResetVisited(); + if (entryBlock->PeepHoleOptimizer()) + changed = true; + ResetVisited(); if (entryBlock->MergeBasicBlocks()) changed = true; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 8bdba4d..d3b258c 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -49,6 +49,7 @@ public: bool ValueForwarding(NativeRegisterDataSet& data); bool LoadsAccu(void) const; + bool ChangesAccuAndFlag(void) const; bool ChangesAddress(void) const; bool SameEffectiveAddress(const NativeCodeInstruction& ins) const; bool IsCommutative(void) const; @@ -123,6 +124,9 @@ public: bool MergeBasicBlocks(void); bool MoveLoadStoreUp(int at); + + bool ValueForwarding(const NativeRegisterDataSet& data); + }; class NativeCodeProcedure diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c28d19a..09659a2 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -9,8 +9,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mGlobals = new DeclarationScope(compilationUnits->mScope); mScope = mGlobals; - mCodeSection = Ident::Unique("code"); - mDataSection = Ident::Unique("code"); + mCodeSection = compilationUnits->mSectionCode; + mDataSection = compilationUnits->mSectionData; } Parser::~Parser(void) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 7f01128..e1c0629 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -14,7 +14,7 @@ public: int mLocalIndex; CompilationUnits * mCompilationUnits; - const Ident* mCodeSection, * mDataSection; + LinkerSection * mCodeSection, * mDataSection; void Parse(void); protected: diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index c3d4081..7a2e3f4 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,31,0 - PRODUCTVERSION 1,0,31,0 + FILEVERSION 1,0,32,0 + PRODUCTVERSION 1,0,32,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.0.31.0" + VALUE "FileVersion", "1.0.32.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.0.31.0" + VALUE "ProductVersion", "1.0.32.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 4915cf1..4794fec 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -564,15 +564,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{62476C9D-FE04-46D6-94CA-6521843D6575}" - "PackageCode" = "8:{67130DB4-0306-455D-881B-FCE28C4AB1C9}" + "ProductCode" = "8:{69C89FCE-CBE7-4824-B039-777CDE9B33FF}" + "PackageCode" = "8:{025298B2-CAEE-4BDE-AA51-591D0418C086}" "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.0.31" + "ProductVersion" = "8:1.0.32" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"