Fix return type coercion, region based linker

This commit is contained in:
drmortalwombat 2021-09-21 20:44:19 +02:00
parent 3f5f3ee7ea
commit eebc39e53a
14 changed files with 400 additions and 245 deletions

View File

@ -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<digits; i++)
s /= 10.0;
f += s;
float r = 0.5;
for(char i=1; i<digits; i++)
r /= 10.0;
f += r;
if (f >= 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<fdigits; i++)
s /= 10.0;
f += s;
float r = 0.5;
for(char i=0; i<fdigits; i++)
r /= 10.0;
f += r;
if (f >= 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; i<digits; i++)
for(char i=0; i<digits; i++)
{
if (i == pdigits)
str[d++] = '.';
sp[d++] = '.';
int c = (int)f;
f -= (float)c;
f *= 10.0;
str[d++] = c + '0';
sp[d++] = c + '0';
}
if (fexp)
{
str[d++] = 'E';
sp[d++] = 'E';
if (exp < 0)
{
str[d++] = '-';
sp[d++] = '-';
exp = -exp;
}
else
str[d++] = '+';
sp[d++] = '+';
str[d++] = exp / 10 + '0';
str[d++] = exp % 10 + '0';
sp[d++] = exp / 10 + '0';
sp[d++] = exp % 10 + '0';
}
str[d++] = 0;
if (d < si->width)
{
for(int i=0; i<=d; i++)
str[si->width - i] = str[d - i];
for(int i=0; i<si->width-d; i++)
str[i] = ' '
for(char i=1; i<=d; i++)
sp[si->width - i] = sp[d - i];
for(char i=0; i<si->width-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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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]
);
}

View File

@ -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;

View File

@ -3,6 +3,14 @@
#include <stdio.h>
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);
}
}

View File

@ -22,6 +22,19 @@ enum LinkerObjectType
};
class LinkerObject;
class LinkerSection;
class LinkerRegion
{
public:
const Ident* mIdent;
int mStart, mEnd, mUsed;
GrowingArray<LinkerSection*> mSections;
LinkerRegion(void);
};
class LinkerReference
{
@ -35,23 +48,25 @@ class LinkerSection
{
public:
const Ident* mIdent;
int mID;
int mStart, mSize, mUsed;
GrowingArray <LinkerObject*> 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<LinkerReference*> mReferences;
GrowingArray<LinkerRegion*> mRegions;
GrowingArray<LinkerSection*> mSections;
GrowingArray<LinkerObject*> mObjects;

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -14,7 +14,7 @@ public:
int mLocalIndex;
CompilationUnits * mCompilationUnits;
const Ident* mCodeSection, * mDataSection;
LinkerSection * mCodeSection, * mDataSection;
void Parse(void);
protected:

View File

@ -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"

View File

@ -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:"