Add BIT instruction for sign check, add inlay sections in linker
This commit is contained in:
parent
2b0f074c94
commit
6bbf325720
13
README.md
13
README.md
|
@ -684,6 +684,19 @@ The overlay file can then be loaded in memory during program execution:
|
|||
|
||||
krnio_setnam(P"OVL1");
|
||||
krnio_load(1, 8, 1);
|
||||
|
||||
#### Inlays
|
||||
|
||||
Inlays are sections that are compressed into constant arrays by the linker and can then be expanded by the program on demand. The array has to be declared with unknown size.
|
||||
|
||||
const char Inlay1[];
|
||||
#pragma section( icode1, 0 )
|
||||
#pragma region( isec1, 0xc000, 0xd000, , Inlay1, { icode1 } )
|
||||
|
||||
The size of the array is not known at compile time, so a sizeof() will return 0. The oscar_expand_lzo can be used to expand the code and does not need the size:
|
||||
|
||||
oscar_expand_lzo((char *)0xc000, Inlay1);
|
||||
|
||||
|
||||
#### NES ROM Banks
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ enum IEC_STATUS
|
|||
|
||||
IEC_ERROR = 0x80,
|
||||
IEC_TIMEOUT,
|
||||
IEC_DATA_CHECK
|
||||
IEC_DATA_CHECK,
|
||||
};
|
||||
|
||||
extern IEC_STATUS iec_status;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#include "Compression.h"
|
||||
|
||||
int CompressLZO(uint8* dst, const uint8* source, int size)
|
||||
{
|
||||
int csize = 0;
|
||||
|
||||
int pos = 0;
|
||||
while (pos < size)
|
||||
{
|
||||
int pi = 0;
|
||||
while (pi < 127 && pos < size)
|
||||
{
|
||||
int bi = pi, bj = 0;
|
||||
for (int i = 1; i < (pos < 255 ? pos : 255); i++)
|
||||
{
|
||||
int j = 0;
|
||||
while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j])
|
||||
j++;
|
||||
|
||||
if (j > bj)
|
||||
{
|
||||
bi = i;
|
||||
bj = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (bj >= 4)
|
||||
{
|
||||
if (pi > 0)
|
||||
{
|
||||
dst[csize++] = pi;
|
||||
for (int i = 0; i < pi; i++)
|
||||
dst[csize++] = source[pos - pi + i];
|
||||
pi = 0;
|
||||
}
|
||||
|
||||
dst[csize++] = 128 + bj;
|
||||
dst[csize++] = bi;
|
||||
pos += bj;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos++;
|
||||
pi++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pi > 0)
|
||||
{
|
||||
dst[csize++] = pi;
|
||||
for (int i = 0; i < pi; i++)
|
||||
dst[csize++] = source[pos - pi + i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[csize++] = 0;
|
||||
|
||||
return csize;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "CompilerTypes.h"
|
||||
|
||||
int CompressLZO(uint8* dst, const uint8* source, int size);
|
||||
|
|
@ -986,7 +986,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
|||
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
|
||||
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
|
||||
mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr),
|
||||
mShift(0), mBits(0), mOptFlags(0)
|
||||
mShift(0), mBits(0), mOptFlags(0), mInlayRegion(nullptr)
|
||||
{}
|
||||
|
||||
Declaration::~Declaration(void)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
class LinkerObject;
|
||||
class LinkerSection;
|
||||
class LinkerRegion;
|
||||
class Linker;
|
||||
class Parser;
|
||||
|
||||
|
@ -99,6 +100,7 @@ static const uint64 DTF_COMPLETED = (1ULL << 30);
|
|||
static const uint64 DTF_CONSTEXPR = (1ULL << 31);
|
||||
|
||||
static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32);
|
||||
static const uint64 DTF_BANK_INLAY = (1ULL << 33);
|
||||
|
||||
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 36);
|
||||
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37);
|
||||
|
@ -280,6 +282,7 @@ public:
|
|||
uint64 mFlags, mCompilerOptions, mOptFlags;
|
||||
const Ident * mIdent, * mQualIdent, * mMangleIdent;
|
||||
LinkerSection * mSection;
|
||||
LinkerRegion * mInlayRegion;
|
||||
const uint8 * mData;
|
||||
LinkerObject * mLinkerObject;
|
||||
int mUseCount;
|
||||
|
|
|
@ -696,6 +696,11 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
|
|||
dec->mLinkerObject->mType = LOT_SECTION_START;
|
||||
else if (dec->mFlags & DTF_SECTION_END)
|
||||
dec->mLinkerObject->mType = LOT_SECTION_END;
|
||||
else if (dec->mFlags & DTF_BANK_INLAY)
|
||||
{
|
||||
dec->mLinkerObject->mType = LOT_INLAY;
|
||||
dec->mInlayRegion->mInlayObject = dec->mLinkerObject;
|
||||
}
|
||||
|
||||
uint8* d = var->mLinkerObject->AddSpace(var->mSize);
|
||||
if (dec->mValue)
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "CompilerTypes.h"
|
||||
#include "Compression.h"
|
||||
|
||||
LinkerRegion::LinkerRegion(void)
|
||||
: mSections(nullptr), mFreeChunks(FreeChunk{ 0, 0 } ), mLastObject(nullptr)
|
||||
: mSections(nullptr), mFreeChunks(FreeChunk{ 0, 0 } ), mLastObject(nullptr), mInlayObject(nullptr), mCartridgeBanks(0)
|
||||
{}
|
||||
|
||||
LinkerSection::LinkerSection(void)
|
||||
|
@ -44,7 +45,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref)
|
|||
}
|
||||
|
||||
LinkerObject::LinkerObject(void)
|
||||
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr)
|
||||
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
|
||||
{}
|
||||
|
||||
LinkerObject::~LinkerObject(void)
|
||||
|
@ -339,13 +340,13 @@ void Linker::CombineSameConst(void)
|
|||
while (dobj->mMapID != mObjects[dobj->mMapID]->mMapID)
|
||||
dobj->mMapID = mObjects[dobj->mMapID]->mMapID;
|
||||
|
||||
if ((dobj->mFlags & LOBJF_REFERENCED) && (dobj->mFlags & LOBJF_CONST) && dobj->mMapID == dobj->mID)
|
||||
if ((dobj->mFlags & LOBJF_REFERENCED) && (dobj->mFlags & LOBJF_CONST) && dobj->mMapID == dobj->mID && dobj->mType != LOT_INLAY)
|
||||
{
|
||||
for (int j = i + 1; j < mObjects.Size(); j++)
|
||||
{
|
||||
LinkerObject* sobj(mObjects[j]);
|
||||
|
||||
if ((sobj->mFlags & LOBJF_REFERENCED) && (sobj->mFlags & LOBJF_CONST) && sobj->mMapID == sobj->mID)
|
||||
if ((sobj->mFlags & LOBJF_REFERENCED) && (sobj->mFlags & LOBJF_CONST) && sobj->mMapID == sobj->mID && sobj->mType != LOT_INLAY)
|
||||
{
|
||||
if (dobj->mSize == sobj->mSize && dobj->mSection == sobj->mSection && dobj->mReferences.Size() == sobj->mReferences.Size())
|
||||
{
|
||||
|
@ -531,7 +532,7 @@ void LinkerRegion::PlaceStackSection(LinkerSection* stackSection, LinkerSection*
|
|||
{
|
||||
int start = stackSection->mEnd;
|
||||
|
||||
for(int i=0; i<section->mSections.Size(); i++)
|
||||
for (int i = 0; i < section->mSections.Size(); i++)
|
||||
{
|
||||
PlaceStackSection(stackSection, section->mSections[i]);
|
||||
if (section->mSections[i]->mStart < start)
|
||||
|
@ -540,7 +541,7 @@ void LinkerRegion::PlaceStackSection(LinkerSection* stackSection, LinkerSection*
|
|||
|
||||
section->mStart = start;
|
||||
section->mEnd = start;
|
||||
|
||||
|
||||
for (int i = 0; i < section->mObjects.Size(); i++)
|
||||
{
|
||||
LinkerObject* lobj = section->mObjects[i];
|
||||
|
@ -561,147 +562,48 @@ void LinkerRegion::PlaceStackSection(LinkerSection* stackSection, LinkerSection*
|
|||
}
|
||||
}
|
||||
|
||||
void Linker::Link(void)
|
||||
void Linker::CopyObjects(bool inlays)
|
||||
{
|
||||
if (mErrors->mErrorCount == 0)
|
||||
for (int i = 0; i < mObjects.Size(); i++)
|
||||
{
|
||||
|
||||
for (int i = 0; i < mSections.Size(); i++)
|
||||
LinkerObject* obj = mObjects[i];
|
||||
if (obj->mType == LOT_SECTION_START)
|
||||
{
|
||||
LinkerSection* lsec = mSections[i];
|
||||
lsec->mStart = 0x10000;
|
||||
lsec->mEnd = 0x0000;
|
||||
obj->mAddress = obj->mSection->mStart;
|
||||
obj->mRefAddress = obj->mAddress + (obj->mRegion ? obj->mRegion->mReloc : 0);
|
||||
}
|
||||
|
||||
// Move objects into regions
|
||||
|
||||
for (int i = 0; i < mRegions.Size(); i++)
|
||||
else if (obj->mType == LOT_SECTION_END)
|
||||
{
|
||||
LinkerRegion* lrgn = mRegions[i];
|
||||
for (int j = 0; j < lrgn->mSections.Size(); j++)
|
||||
obj->mAddress = obj->mSection->mEnd;
|
||||
obj->mRefAddress = obj->mAddress + (obj->mRegion ? obj->mRegion->mReloc : 0);
|
||||
}
|
||||
else if (obj->mFlags & LOBJF_REFERENCED)
|
||||
{
|
||||
if (inlays)
|
||||
{
|
||||
LinkerSection* lsec = lrgn->mSections[j];
|
||||
for (int k = 0; k < lsec->mObjects.Size(); k++)
|
||||
if (obj->mRegion && obj->mRegion->mInlayObject)
|
||||
{
|
||||
LinkerObject* lobj = lsec->mObjects[k];
|
||||
if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj, mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS))
|
||||
LinkerObject* iobj = obj->mRegion->mInlayObject;
|
||||
if (!iobj->mMemory)
|
||||
{
|
||||
if (lobj->mIdent && lobj->mIdent->mString && (mCompilerOptions & COPT_VERBOSE2))
|
||||
printf("Placed object <%s> $%04x - $%04x\n", lobj->mIdent->mString, lobj->mAddress, lobj->mAddress + lobj->mSize);
|
||||
|
||||
if (lobj->mAddress < lsec->mStart)
|
||||
lsec->mStart = lobj->mAddress;
|
||||
if (lobj->mAddress + lobj->mSize > lsec->mEnd)
|
||||
lsec->mEnd = lobj->mAddress + lobj->mSize;
|
||||
|
||||
if (lsec->mType == LST_DATA && lsec->mEnd > lrgn->mNonzero)
|
||||
lrgn->mNonzero = lsec->mEnd;
|
||||
iobj->mMemory = new uint8[0x10000];
|
||||
memset(iobj->mMemory, 0, 0x10000);
|
||||
}
|
||||
|
||||
memcpy(iobj->mMemory + obj->mAddress, obj->mData, obj->mSize);
|
||||
if (obj->mAddress < iobj->mStartUsed)
|
||||
iobj->mStartUsed = obj->mAddress;
|
||||
if (obj->mAddress + obj->mSize > iobj->mEndUsed)
|
||||
iobj->mEndUsed = obj->mAddress + obj->mSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < lrgn->mSections.Size(); j++)
|
||||
{
|
||||
LinkerSection* lsec = lrgn->mSections[j];
|
||||
if (lsec->mType == LST_BSS && lsec->mStart < lrgn->mNonzero)
|
||||
lsec->mStart = lrgn->mNonzero;
|
||||
if (lsec->mEnd < lsec->mStart)
|
||||
lsec->mEnd = lsec->mStart;
|
||||
}
|
||||
}
|
||||
|
||||
mProgramStart = 0xffff;
|
||||
mProgramEnd = 0x0000;
|
||||
|
||||
for (int i = 0; i < mRegions.Size(); i++)
|
||||
{
|
||||
LinkerRegion* lrgn = mRegions[i];
|
||||
|
||||
if (lrgn->mNonzero && lrgn->mCartridgeBanks == 0)
|
||||
{
|
||||
if (lrgn->mStart < mProgramStart)
|
||||
mProgramStart = lrgn->mStart;
|
||||
if (lrgn->mNonzero > mProgramEnd)
|
||||
mProgramEnd = lrgn->mNonzero;
|
||||
}
|
||||
}
|
||||
|
||||
// Place stack segment
|
||||
|
||||
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];
|
||||
|
||||
if (lsec->mType == LST_STACK)
|
||||
{
|
||||
lsec->mStart = lsec->mEnd = lrgn->mEnd;
|
||||
lrgn->mEnd = lsec->mStart - lsec->mSize;
|
||||
|
||||
for(int i=0; i<lsec->mSections.Size(); i++)
|
||||
lrgn->PlaceStackSection(lsec, lsec->mSections[i]);
|
||||
|
||||
if (lsec->mStart < lrgn->mEnd)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Static stack usage exceeds stack segment");
|
||||
}
|
||||
|
||||
lsec->mEnd = lsec->mStart;
|
||||
lsec->mStart = lrgn->mEnd;
|
||||
|
||||
if (lsec->mStart < lrgn->mStart + lrgn->mUsed)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Cannot place stack section");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now expand the heap section to cover the remainder of the region
|
||||
|
||||
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];
|
||||
|
||||
if (lsec->mType == LST_HEAP)
|
||||
{
|
||||
lsec->mStart = (lrgn->mStart + lrgn->mUsed + 7) & ~7;
|
||||
lsec->mEnd = lrgn->mEnd & ~7;
|
||||
|
||||
if (lsec->mStart + lsec->mSize > lsec->mEnd)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Cannot place heap section");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mObjects.Size(); i++)
|
||||
{
|
||||
LinkerObject* obj = mObjects[i];
|
||||
if (obj->mType == LOT_SECTION_START)
|
||||
{
|
||||
obj->mAddress = obj->mSection->mStart;
|
||||
obj->mRefAddress = obj->mAddress + (obj->mRegion ? obj->mRegion->mReloc : 0);
|
||||
}
|
||||
else if (obj->mType == LOT_SECTION_END)
|
||||
{
|
||||
obj->mAddress = obj->mSection->mEnd;
|
||||
obj->mRefAddress = obj->mAddress + (obj->mRegion ? obj->mRegion->mReloc : 0);
|
||||
}
|
||||
else if (obj->mFlags & LOBJF_REFERENCED)
|
||||
else
|
||||
{
|
||||
if (!obj->mRegion)
|
||||
mErrors->Error(obj->mLocation, ERRR_INSUFFICIENT_MEMORY, "Could not place object", obj->mIdent);
|
||||
else if (obj->mRegion->mCartridgeBanks != 0)
|
||||
else if (obj->mRegion->mInlayObject)
|
||||
;
|
||||
else if (obj->mRegion && obj->mRegion->mCartridgeBanks != 0)
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
|
@ -722,20 +624,46 @@ void Linker::Link(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mReferences.Size(); i++)
|
||||
void Linker::PatchReferences(bool inlays)
|
||||
{
|
||||
for (int i = 0; i < mReferences.Size(); i++)
|
||||
{
|
||||
LinkerReference* ref = mReferences[i];
|
||||
LinkerObject* obj = ref->mObject;
|
||||
if (obj->mFlags & LOBJF_REFERENCED)
|
||||
{
|
||||
LinkerReference* ref = mReferences[i];
|
||||
LinkerObject* obj = ref->mObject;
|
||||
if (obj->mFlags & LOBJF_REFERENCED)
|
||||
if (obj->mRegion)
|
||||
{
|
||||
if (obj->mRegion)
|
||||
LinkerObject* robj = ref->mRefObject;
|
||||
|
||||
int raddr = robj->mRefAddress + ref->mRefOffset;
|
||||
uint8* dp;
|
||||
|
||||
if (inlays)
|
||||
{
|
||||
LinkerObject* robj = ref->mRefObject;
|
||||
if (obj->mRegion->mInlayObject)
|
||||
{
|
||||
LinkerObject* iobj = obj->mRegion->mInlayObject;
|
||||
|
||||
int raddr = robj->mRefAddress + ref->mRefOffset;
|
||||
uint8* dp;
|
||||
dp = iobj->mMemory + obj->mAddress + ref->mOffset;
|
||||
|
||||
if (ref->mFlags & LREF_LOWBYTE)
|
||||
{
|
||||
*dp++ = raddr & 0xff;
|
||||
}
|
||||
if (ref->mFlags & LREF_HIGHBYTE)
|
||||
{
|
||||
*dp++ = (raddr >> 8) & 0xff;
|
||||
}
|
||||
if (ref->mFlags & LREF_TEMPORARY)
|
||||
*dp += obj->mTemporaries[ref->mRefOffset];
|
||||
}
|
||||
}
|
||||
else if (!obj->mRegion->mInlayObject)
|
||||
{
|
||||
if (obj->mRegion->mCartridgeBanks)
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
|
@ -775,6 +703,166 @@ void Linker::Link(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Linker::PlaceObjects(void)
|
||||
{
|
||||
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->mType != LOT_INLAY && (lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj, mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS))
|
||||
{
|
||||
if (lobj->mIdent && lobj->mIdent->mString && (mCompilerOptions & COPT_VERBOSE2))
|
||||
printf("Placed object <%s> $%04x - $%04x\n", lobj->mIdent->mString, lobj->mAddress, lobj->mAddress + lobj->mSize);
|
||||
|
||||
if (lobj->mAddress < lsec->mStart)
|
||||
lsec->mStart = lobj->mAddress;
|
||||
if (lobj->mAddress + lobj->mSize > lsec->mEnd)
|
||||
lsec->mEnd = lobj->mAddress + lobj->mSize;
|
||||
|
||||
if (lsec->mType == LST_DATA && lsec->mEnd > lrgn->mNonzero)
|
||||
lrgn->mNonzero = lsec->mEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Linker::Link(void)
|
||||
{
|
||||
if (mErrors->mErrorCount == 0)
|
||||
{
|
||||
|
||||
for (int i = 0; i < mSections.Size(); i++)
|
||||
{
|
||||
LinkerSection* lsec = mSections[i];
|
||||
lsec->mStart = 0x10000;
|
||||
lsec->mEnd = 0x0000;
|
||||
}
|
||||
|
||||
// Move objects into regions
|
||||
PlaceObjects();
|
||||
|
||||
// Place stack segment
|
||||
|
||||
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];
|
||||
|
||||
if (lsec->mType == LST_STACK)
|
||||
{
|
||||
lsec->mStart = lsec->mEnd = lrgn->mEnd;
|
||||
lrgn->mEnd = lsec->mStart - lsec->mSize;
|
||||
|
||||
for (int i = 0; i < lsec->mSections.Size(); i++)
|
||||
lrgn->PlaceStackSection(lsec, lsec->mSections[i]);
|
||||
|
||||
if (lsec->mStart < lrgn->mEnd)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Static stack usage exceeds stack segment");
|
||||
}
|
||||
|
||||
lsec->mEnd = lsec->mStart;
|
||||
lsec->mStart = lrgn->mEnd;
|
||||
|
||||
if (lsec->mStart < lrgn->mStart + lrgn->mUsed)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Cannot place stack section");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CopyObjects(true);
|
||||
PatchReferences(true);
|
||||
|
||||
// Move inlays into regions
|
||||
|
||||
for (int i = 0; i < mRegions.Size(); i++)
|
||||
{
|
||||
LinkerRegion* lrgn = mRegions[i];
|
||||
if (lrgn->mInlayObject)
|
||||
{
|
||||
LinkerObject* iobj = lrgn->mInlayObject;
|
||||
|
||||
int size = CompressLZO(mWorkspace, iobj->mMemory + iobj->mStartUsed, iobj->mEndUsed - iobj->mStartUsed);
|
||||
iobj->AddData(mWorkspace, size);
|
||||
iobj->mType = LOT_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
PlaceObjects();
|
||||
|
||||
// Calculate BSS storage
|
||||
|
||||
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];
|
||||
if (lsec->mType == LST_BSS && lsec->mStart < lrgn->mNonzero)
|
||||
lsec->mStart = lrgn->mNonzero;
|
||||
if (lsec->mEnd < lsec->mStart)
|
||||
lsec->mEnd = lsec->mStart;
|
||||
}
|
||||
}
|
||||
|
||||
mProgramStart = 0xffff;
|
||||
mProgramEnd = 0x0000;
|
||||
|
||||
for (int i = 0; i < mRegions.Size(); i++)
|
||||
{
|
||||
LinkerRegion* lrgn = mRegions[i];
|
||||
|
||||
if (lrgn->mNonzero && lrgn->mCartridgeBanks == 0 && !lrgn->mInlayObject)
|
||||
{
|
||||
if (lrgn->mStart < mProgramStart)
|
||||
mProgramStart = lrgn->mStart;
|
||||
if (lrgn->mNonzero > mProgramEnd)
|
||||
mProgramEnd = lrgn->mNonzero;
|
||||
}
|
||||
}
|
||||
|
||||
// Now expand the heap section to cover the remainder of the region
|
||||
|
||||
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];
|
||||
|
||||
if (lsec->mType == LST_HEAP)
|
||||
{
|
||||
lsec->mStart = (lrgn->mStart + lrgn->mUsed + 7) & ~7;
|
||||
lsec->mEnd = lrgn->mEnd & ~7;
|
||||
|
||||
if (lsec->mStart + lsec->mSize > lsec->mEnd)
|
||||
{
|
||||
Location loc;
|
||||
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Cannot place heap section");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second patch of references
|
||||
|
||||
CopyObjects(false);
|
||||
PatchReferences(false);
|
||||
|
||||
for (int i = 0; i < mObjects.Size(); i++)
|
||||
{
|
||||
|
@ -1527,6 +1615,8 @@ bool Linker::WriteAsmFile(const char* filename)
|
|||
i++;
|
||||
mNativeDisassembler.Disassemble(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj->mFullIdent);
|
||||
}
|
||||
else if (obj->mRegion->mInlayObject)
|
||||
mNativeDisassembler.Disassemble(file, obj->mRegion->mInlayObject->mMemory, 0xa0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj->mFullIdent);
|
||||
else
|
||||
mNativeDisassembler.Disassemble(file, mMemory, -1, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj->mFullIdent);
|
||||
break;
|
||||
|
@ -1538,6 +1628,8 @@ bool Linker::WriteAsmFile(const char* filename)
|
|||
i++;
|
||||
mNativeDisassembler.DumpMemory(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
|
||||
}
|
||||
else if (obj->mRegion->mInlayObject)
|
||||
mNativeDisassembler.DumpMemory(file, obj->mRegion->mInlayObject->mMemory, 0xa0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
|
||||
else
|
||||
mNativeDisassembler.DumpMemory(file, mMemory, -1, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
|
||||
break;
|
||||
|
|
|
@ -22,6 +22,7 @@ enum LinkerObjectType
|
|||
LOT_BSS,
|
||||
LOT_HEAP,
|
||||
LOT_STACK,
|
||||
LOT_INLAY,
|
||||
LOT_SECTION_START,
|
||||
LOT_SECTION_END
|
||||
};
|
||||
|
@ -79,9 +80,10 @@ class LinkerRegion
|
|||
public:
|
||||
const Ident* mIdent;
|
||||
|
||||
uint32 mFlags;
|
||||
int mStart, mEnd, mUsed, mNonzero, mReloc;
|
||||
uint64 mCartridgeBanks;
|
||||
uint32 mFlags;
|
||||
int mStart, mEnd, mUsed, mNonzero, mReloc;
|
||||
uint64 mCartridgeBanks;
|
||||
LinkerObject * mInlayObject;
|
||||
|
||||
GrowingArray<LinkerSection*> mSections;
|
||||
|
||||
|
@ -183,10 +185,10 @@ public:
|
|||
LinkerObjectType mType;
|
||||
int mID, mMapID;
|
||||
int mAddress, mRefAddress;
|
||||
int mSize, mAlignment;
|
||||
int mSize, mAlignment, mStartUsed, mEndUsed;
|
||||
LinkerSection * mSection;
|
||||
LinkerRegion * mRegion;
|
||||
uint8 * mData;
|
||||
uint8 * mData, * mMemory;
|
||||
InterCodeProcedure * mProc;
|
||||
uint32 mFlags;
|
||||
uint8 mTemporaries[16], mTempSizes[16];
|
||||
|
@ -278,7 +280,7 @@ public:
|
|||
GrowingArray<LinkerObject*> mObjects;
|
||||
GrowingArray<LinkerOverlay*> mOverlays;
|
||||
|
||||
uint8 mMemory[0x10000];
|
||||
uint8 mMemory[0x10000], mWorkspace[0x10000];
|
||||
uint8 mCartridge[64][0x10000];
|
||||
|
||||
bool mCartridgeBankUsed[64];
|
||||
|
@ -291,6 +293,9 @@ public:
|
|||
|
||||
void CollectReferences(void);
|
||||
void CombineSameConst(void);
|
||||
void PatchReferences(bool inlays);
|
||||
void CopyObjects(bool inlays);
|
||||
void PlaceObjects(void);
|
||||
void Link(void);
|
||||
protected:
|
||||
NativeCodeDisassembler mNativeDisassembler;
|
||||
|
|
|
@ -1391,6 +1391,7 @@ bool NativeCodeInstruction::ChangesZFlag(void) const
|
|||
mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY ||
|
||||
mType == ASMIT_LDA || mType == ASMIT_LDX || mType == ASMIT_LDY ||
|
||||
mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR ||
|
||||
mType == ASMIT_BIT ||
|
||||
mType == ASMIT_JSR;
|
||||
}
|
||||
|
||||
|
@ -1457,7 +1458,7 @@ bool NativeCodeInstruction::UsesAddress(void) const
|
|||
mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR ||
|
||||
mType == ASMIT_LDA || mType == ASMIT_LDX || mType == ASMIT_LDY ||
|
||||
mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY ||
|
||||
mType == ASMIT_ADC || mType == ASMIT_SBC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR;
|
||||
mType == ASMIT_ADC || mType == ASMIT_SBC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR || mType == ASMIT_BIT;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -2353,6 +2354,10 @@ void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data)
|
|||
}
|
||||
break;
|
||||
|
||||
case ASMIT_BIT:
|
||||
data.mRegs[CPU_REG_Z].Reset();
|
||||
break;
|
||||
|
||||
case ASMIT_LDA:
|
||||
if (reg >= 0)
|
||||
{
|
||||
|
@ -3384,6 +3389,9 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
data.mRegs[CPU_REG_Z].Reset();
|
||||
}
|
||||
break;
|
||||
case ASMIT_BIT:
|
||||
data.mRegs[CPU_REG_Z].Reset();
|
||||
break;
|
||||
case ASMIT_INX:
|
||||
case ASMIT_DEX:
|
||||
data.ResetX();
|
||||
|
@ -3545,7 +3553,18 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
if (final && mType == ASMIT_STX && data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_X]))
|
||||
{
|
||||
mType = ASMIT_STA;
|
||||
changed = true;
|
||||
}
|
||||
else if (final && mType == ASMIT_STY && data.mRegs[CPU_REG_A].SameData(data.mRegs[CPU_REG_Y]))
|
||||
{
|
||||
mType = ASMIT_STA;
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
if (mMode == ASMIM_ZERO_PAGE)
|
||||
{
|
||||
switch (mType)
|
||||
|
@ -4453,6 +4472,10 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
|
|||
case ASMIT_TXA:
|
||||
case ASMIT_TAY:
|
||||
case ASMIT_TYA:
|
||||
case ASMIT_DEY:
|
||||
case ASMIT_INY:
|
||||
case ASMIT_DEX:
|
||||
case ASMIT_INX:
|
||||
providedTemps += CPU_REG_Z;
|
||||
break;
|
||||
}
|
||||
|
@ -38892,6 +38915,30 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
mIns[i + 1].mType = ASMIT_STA;
|
||||
progress = true;
|
||||
}
|
||||
else if (mIns[i + 0].mType == ASMIT_STX && mIns[i + 1].mType == ASMIT_INC && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_X) && !(mIns[i + 0].mFlags & NCIF_VOLATILE))
|
||||
{
|
||||
mIns[i + 0].mType = ASMIT_INX; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
|
||||
mIns[i + 1].mType = ASMIT_STX;
|
||||
progress = true;
|
||||
}
|
||||
else if (mIns[i + 0].mType == ASMIT_STX && mIns[i + 1].mType == ASMIT_DEC && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_X) && !(mIns[i + 0].mFlags & NCIF_VOLATILE))
|
||||
{
|
||||
mIns[i + 0].mType = ASMIT_DEX; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
|
||||
mIns[i + 1].mType = ASMIT_STX;
|
||||
progress = true;
|
||||
}
|
||||
else if (mIns[i + 0].mType == ASMIT_STY && mIns[i + 1].mType == ASMIT_INC && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_Y) && !(mIns[i + 0].mFlags & NCIF_VOLATILE))
|
||||
{
|
||||
mIns[i + 0].mType = ASMIT_INY; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
|
||||
mIns[i + 1].mType = ASMIT_STY;
|
||||
progress = true;
|
||||
}
|
||||
else if (mIns[i + 0].mType == ASMIT_STY && mIns[i + 1].mType == ASMIT_DEC && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_Y) && !(mIns[i + 0].mFlags & NCIF_VOLATILE))
|
||||
{
|
||||
mIns[i + 0].mType = ASMIT_DEY; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
|
||||
mIns[i + 1].mType = ASMIT_STY;
|
||||
progress = true;
|
||||
}
|
||||
#endif
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||
|
@ -43527,6 +43574,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
|
||||
changed = true;
|
||||
}
|
||||
#if 1
|
||||
else if (pass >= 7 && sz >= 1 &&
|
||||
mIns[sz - 1].mType == ASMIT_LDA && (mIns[sz - 1].mMode == ASMIM_ABSOLUTE || mIns[sz - 1].mMode == ASMIM_ZERO_PAGE) && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A) &&
|
||||
(mBranch == ASMIT_BPL || mBranch == ASMIT_BMI) && !mExitRequiredRegs[CPU_REG_Z])
|
||||
{
|
||||
mIns[sz - 1].mType = ASMIT_BIT;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
#endif
|
||||
else if (pass >= 7 && sz >= 1 &&
|
||||
mIns[sz - 1].mType == ASMIT_AND && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x40 && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)) &&
|
||||
(mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE) && !mExitRequiredRegs[CPU_REG_Z])
|
||||
|
@ -44471,7 +44528,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
{
|
||||
mInterProc = proc;
|
||||
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "PlayingState::InitMaps");
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "main");
|
||||
|
||||
int nblocks = proc->mBlocks.Size();
|
||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||
|
|
|
@ -11227,7 +11227,7 @@ void Parser::ParsePragma(void)
|
|||
ConsumeToken(TK_COMMA);
|
||||
|
||||
exp = ParseRExpression();
|
||||
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||
if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_ADDRESS))
|
||||
start = int(exp->mDecValue->mInteger);
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for start expected");
|
||||
|
@ -11235,7 +11235,7 @@ void Parser::ParsePragma(void)
|
|||
ConsumeToken(TK_COMMA);
|
||||
|
||||
exp = ParseRExpression();
|
||||
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||
if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_ADDRESS))
|
||||
end = int(exp->mDecValue->mInteger);
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for end expected");
|
||||
|
@ -11253,6 +11253,8 @@ void Parser::ParsePragma(void)
|
|||
|
||||
ConsumeToken(TK_COMMA);
|
||||
|
||||
Declaration* inlay = nullptr;
|
||||
|
||||
if (mScanner->mToken != TK_COMMA)
|
||||
{
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
|
@ -11273,11 +11275,23 @@ void Parser::ParsePragma(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
exp = ParseRExpression();
|
||||
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||
bank = 1ULL << exp->mDecValue->mInteger;
|
||||
exp = ParseExpression(true);
|
||||
if (exp->mType == EX_VARIABLE && exp->mDecType->mType == DT_TYPE_ARRAY && exp->mDecType->mSize == 0 &&
|
||||
exp->mDecType->mBase->mType == DT_TYPE_INTEGER && exp->mDecType->mBase->mSize == 1)
|
||||
{
|
||||
exp->mDecValue->mFlags |= DTF_DEFINED | DTF_BANK_INLAY;
|
||||
exp->mDecValue->mSection = mCodeSection;
|
||||
exp->mDecType->mFlags |= DTF_DEFINED;
|
||||
inlay = exp->mDecValue;
|
||||
}
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for bank expected");
|
||||
{
|
||||
exp = exp->ConstantFold(mErrors, mDataSection, mCompilationUnits->mLinker);
|
||||
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||
bank = 1ULL << exp->mDecValue->mInteger;
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for bank expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11291,6 +11305,10 @@ void Parser::ParsePragma(void)
|
|||
else if (rgn->mStart != start || rgn->mEnd != end || rgn->mFlags != flags || rgn->mCartridgeBanks != bank)
|
||||
mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Conflicting linker region definition");
|
||||
|
||||
if (inlay)
|
||||
{
|
||||
inlay->mInlayRegion = rgn;
|
||||
}
|
||||
|
||||
ConsumeToken(TK_COMMA);
|
||||
ConsumeToken(TK_OPEN_BRACE);
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
<ClCompile Include="ByteCodeGenerator.cpp" />
|
||||
<ClCompile Include="CompilationUnits.cpp" />
|
||||
<ClCompile Include="Compiler.cpp" />
|
||||
<ClCompile Include="Compression.cpp" />
|
||||
<ClCompile Include="Constexpr.cpp" />
|
||||
<ClCompile Include="Declaration.cpp" />
|
||||
<ClCompile Include="Disassembler.cpp" />
|
||||
|
@ -186,6 +187,7 @@
|
|||
<ClInclude Include="CompilationUnits.h" />
|
||||
<ClInclude Include="Compiler.h" />
|
||||
<ClInclude Include="CompilerTypes.h" />
|
||||
<ClInclude Include="Compression.h" />
|
||||
<ClInclude Include="Constexpr.h" />
|
||||
<ClInclude Include="Declaration.h" />
|
||||
<ClInclude Include="Disassembler.h" />
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
<ClCompile Include="GlobalOptimizer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Compression.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Array.h">
|
||||
|
@ -164,6 +167,9 @@
|
|||
<ClInclude Include="GlobalOptimizer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Compression.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="oscar64.rc">
|
||||
|
|
Loading…
Reference in New Issue