Add BIT instruction for sign check, add inlay sections in linker

This commit is contained in:
drmortalwombat 2023-12-12 11:08:59 +01:00
parent 2b0f074c94
commit 6bbf325720
13 changed files with 424 additions and 158 deletions

View File

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

View File

@ -8,7 +8,7 @@ enum IEC_STATUS
IEC_ERROR = 0x80,
IEC_TIMEOUT,
IEC_DATA_CHECK
IEC_DATA_CHECK,
};
extern IEC_STATUS iec_status;

59
oscar64/Compression.cpp Normal file
View File

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

6
oscar64/Compression.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "CompilerTypes.h"
int CompressLZO(uint8* dst, const uint8* source, int size);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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