Fix easyflash placement of auto copied main section

This commit is contained in:
drmortalwombat 2022-08-25 18:01:58 +02:00
parent 4b4c8866dd
commit 7dd8f4dae3
10 changed files with 326 additions and 29 deletions

View File

@ -558,6 +558,11 @@ This sample reserves a fixed area of several banks for a common code segment. A
An alternative to calling the function in the cartridge ROM itself is to copy it to a different location in RAM and execute it there. This sample creates functions in different ROM banks that are linked for a memory area in RAM at 0x7000. The code is copied from the ROM to RAM and then executed.
#### Easyflash low memory usage "easyflash.c"
This sample will use the memory area starting from 0x0400 for the main code section when copying the code, using the stack page 0x100 for the startup itself, thus wasting small amount of RAM space.
#### Terminate stay resident "tsr.c"
A common usage for the RAM area in 0xc000..0xcfff which is visible but not usable from BASIC is to install a terminate stay resident BASIC extension, which can then be called using sys 49152.

View File

@ -8,6 +8,7 @@
#define MMAP_NO_ROM 0x35
#define MMAP_RAM 0x30
#define MMAP_CHAR_ROM 0x31
#define MMAP_ALL_ROM 0x33
// Install an IRQ an NMI trampoline, that routes the kernal interrupts
// through an intermediate trampoline when the kernal ROM is not paged

View File

@ -14,8 +14,9 @@
#define regs __regs
void StackStart, StackEnd, BSSStart, BSSEnd;
void StackStart, StackEnd, BSSStart, BSSEnd, CodeStart, CodeEnd;
#pragma section(code, 0x0000, CodeStart, CodeEnd)
#pragma section(stack, 0x0000, StackStart, StackEnd)
#pragma section(bss, 0x0000, BSSStart, BSSEnd)
@ -26,6 +27,7 @@ int main(void);
__asm startup
{
st0:
#ifdef OSCAR_TARGET_CRT16
byt 0x09
byt 0x80
@ -39,23 +41,88 @@ __asm startup
// Copy cartridge rom to ram
ldx #$40
ldy #$00
lda #$80
ldx #0
lc0: lda $8000, x
sta st0, x
inx
bne lc0
// Set up address for decompress
lda #$00
sta ip
lda #$81
sta ip + 1
lda #$08
lda #<CodeStart
sta sp
lda #>CodeStart
sta sp + 1
sty ip
sty sp
l0: lda (ip), y
ldy #0
lda (ip),y
lx0:
sta accu
bmi wx1
clc
lda ip + 0
adc #1
sta addr + 0
lda ip + 1
adc #0
sta addr + 1
clc
lda addr + 0
adc accu
sta ip + 0
lda addr + 1
adc #0
sta ip + 1
lx2:
ldy #0
lx1: lda (addr), y
sta (sp), y
iny
bne l0
inc ip + 1
inc sp + 1
dex
bne l0
cpy accu
bne lx1
clc
lda sp
adc accu
sta sp
lda sp + 1
adc #0
sta sp + 1
ldy #0
lda (ip), y
bne lx0
jmp w0
wx1:
lda sp + 0
sec
ldy #1
sbc (ip), y
sta addr
lda sp + 1
sbc #0
sta addr + 1
clc
lda ip + 0
adc #2
sta ip + 0
lda ip + 1
adc #0
sta ip + 1
lda accu
and #$7f
sta accu
jmp lx2
w0:
lda #$3f
sta $00

View File

@ -5365,6 +5365,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = 255;
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = 0;
}
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255)
{
@ -11779,6 +11781,15 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets)
fprintf(file, "-");
}
fprintf(file, "\n\n");
fprintf(file, "Exit required temps : ");
for (i = 0; i < mExitRequiredTemps.Size(); i++)
{
if (mExitRequiredTemps[i])
fprintf(file, "#");
else
fprintf(file, "-");
}
fprintf(file, "\n\n");
}
for (i = 0; i < mInstructions.Size(); i++)
@ -12958,6 +12969,8 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("Peephole Temp Check");
RemoveUnusedInstructions();
ReduceTemporaries();
MergeBasicBlocks();
@ -13350,6 +13363,8 @@ void InterCodeProcedure::ReduceTemporaries(void)
for (i = 0; i < numTemps; i++)
collisionSet[i].Reset(numTemps);
Disassemble("ReduceTemps", true);
ResetVisited();
mEntryBlock->BuildCollisionTable(collisionSet);

View File

@ -568,6 +568,62 @@ bool Linker::WritePrgFile(const char* filename)
return false;
}
static int memlzcomp(uint8 * dp, const uint8 * sp, int size)
{
int pos = 0, csize = 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 && sp[pos - i + j] == sp[pos + j])
j++;
if (j > bj)
{
bi = i;
bj = j;
}
}
if (bj >= 4)
{
if (pi > 0)
{
dp[csize++] = pi;
for (int i = 0; i < pi; i++)
dp[csize++] = sp[pos - pi + i];
pi = 0;
}
dp[csize++] = 128 + bj;
dp[csize++] = bi;
pos += bj;
}
else
{
pos++;
pi++;
}
}
if (pi > 0)
{
dp[csize++] = pi;
for (int i = 0; i < pi; i++)
dp[csize++] = sp[pos - pi + i];
}
}
dp[csize++] = 0;
return csize;
}
bool Linker::WriteCrtFile(const char* filename)
{
FILE* file;
@ -608,18 +664,27 @@ bool Linker::WriteCrtFile(const char* filename)
chipHeader.mBankNumber = 0;
chipHeader.mImageSize = 0x0020;
uint8 bootmem[8192];
uint8 bootmem[0x4000];
memset(bootmem, 0, 0x2000);
memset(bootmem, 0, 0x4000);
chipHeader.mLoadAddress = 0x0080;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mMemory + 0x0800, 1, 0x2000, file);
LinkerRegion * mainRegion = FindRegion(Ident::Unique("main"));
LinkerRegion * startupRegion = FindRegion(Ident::Unique("startup"));
memcpy(bootmem, mMemory + 0x2800, 0x1f00);
memcpy(bootmem, mMemory + startupRegion->mStart, startupRegion->mNonzero - startupRegion->mStart);
int usedlz = memlzcomp(bootmem + 0x0100, mMemory + mainRegion->mStart, mainRegion->mNonzero - mainRegion->mStart);
bootmem[0x1ffc] = 0x00;
bootmem[0x1ffd] = 0xff;
Location loc;
if (usedlz > 0x03e00)
{
mErrors->Error(loc, ERRR_INSUFFICIENT_MEMORY, "Can not fit main region into first ROM bank");
fclose(file);
return false;
}
bootmem[0x3ffc] = 0x00;
bootmem[0x3ffd] = 0xff;
uint8 bootcode[] = {
0xa9, 0x87,
@ -629,7 +694,7 @@ bool Linker::WriteCrtFile(const char* filename)
0x6c, 0xfc, 0xff
};
int j = 0x1f00;
int j = 0x3f00;
for (int i = 0; i < sizeof(bootcode); i++)
{
bootmem[j++] = 0xa9;
@ -642,10 +707,14 @@ bool Linker::WriteCrtFile(const char* filename)
bootmem[j++] = 0x00;
bootmem[j++] = 0x04;
chipHeader.mLoadAddress = 0x00e0;
chipHeader.mLoadAddress = 0x0080;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(bootmem, 1, 0x2000, file);
chipHeader.mLoadAddress = 0x00e0;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(bootmem + 0x2000, 1, 0x2000, file);
for (int i = 1; i < 64; i++)
{
if (mCartridgeBankUsed[i])

View File

@ -1178,6 +1178,25 @@ bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
return false;
}
bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins)
{
if ((ChangesAddress() || ins.ChangesAddress()) && MayBeSameAddress(ins))
return false;
if (RequiresXReg() && ins.ChangesXReg() || ins.RequiresXReg() && ChangesXReg())
return false;
if (RequiresYReg() && ins.ChangesYReg() || ins.RequiresYReg() && ChangesYReg())
return false;
if (RequiresAccu() && ins.ChangesAccu() || ins.RequiresAccu() && ChangesAccu())
return false;
if (RequiresCarry() && ins.ChangesCarry() || ins.RequiresCarry() && ChangesCarry())
return false;
if ((ins.mLive & LIVE_CPU_REG_Z) && ChangesZFlag())
return false;
return true;
}
bool NativeCodeInstruction::MayBeSameAddress(const NativeCodeInstruction& ins, bool sameXY) const
{
if (ins.mMode == ASMIM_ZERO_PAGE)
@ -11692,7 +11711,7 @@ bool NativeCodeBasicBlock::RegisterValueForwarding(void)
{
if (mIns[i].mType == ASMIT_LDX)
{
if (xreg[mIns[i].mAddress])
if (xreg[mIns[i].mAddress] && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
changed = true;
@ -11719,7 +11738,7 @@ bool NativeCodeBasicBlock::RegisterValueForwarding(void)
}
else if (mIns[i].mType == ASMIT_LDY)
{
if (yreg[mIns[i].mAddress])
if (yreg[mIns[i].mAddress] && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
changed = true;
@ -11746,7 +11765,7 @@ bool NativeCodeBasicBlock::RegisterValueForwarding(void)
}
else if (mIns[i].mType == ASMIT_LDA)
{
if (areg[mIns[i].mAddress])
if (areg[mIns[i].mAddress] && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
changed = true;
@ -12333,6 +12352,36 @@ bool NativeCodeBasicBlock::AlternateXYUsage(void)
return changed;
}
bool NativeCodeBasicBlock::SimplifyLoopEnd(NativeCodeProcedure* proc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && !mFalseJump && mTrueJump->mLoopHead)
{
if (mTrueJump->mIns.Size() == 1 && mTrueJump->mFalseJump)
{
mIns.Push(mTrueJump->mIns[0]);
mBranch = mTrueJump->mBranch;
mFalseJump = mTrueJump->mFalseJump;
mTrueJump = mTrueJump->mTrueJump;
changed = true;
}
}
if (mTrueJump && mTrueJump->SimplifyLoopEnd(proc))
changed = true;
if (mFalseJump && mFalseJump->SimplifyLoopEnd(proc))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::SimplifyDiamond(NativeCodeProcedure* proc)
{
bool changed = false;
@ -25330,6 +25379,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
#endif
else if (
mIns[i + 0].ChangesAccuAndFlag() &&
mIns[i + 1].mType == ASMIT_STA &&
mIns[i + 2].MayBeMovedBefore(mIns[i + 1]) && mIns[i + 2].MayBeMovedBefore(mIns[i + 0]) &&
mIns[i + 3].mType == ASMIT_ORA && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0)
{
NativeCodeInstruction ins(mIns[i + 2]);
mIns.Remove(i + 2);
mIns.Insert(i, ins);
mIns[i + 0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
mIns[i + 1].mLive |= mIns[i + 3].mLive;
mIns[i + 2].mLive |= mIns[i + 3].mLive;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y &&
@ -28065,6 +28130,10 @@ void NativeCodeProcedure::Optimize(void)
ResetVisited();
if (mEntryBlock->SimplifyDiamond(this))
changed = true;
ResetVisited();
if (mEntryBlock->SimplifyLoopEnd(this))
changed = true;
}
#if 1
@ -28086,13 +28155,14 @@ void NativeCodeProcedure::Optimize(void)
#if 1
if (!changed && step < 8)
{
cnt = 0;
step++;
changed = true;
}
#endif
cnt++;
else
cnt++;
} while (changed);
@ -28100,7 +28170,10 @@ void NativeCodeProcedure::Optimize(void)
ResetVisited();
mEntryBlock->ReduceLocalYPressure();
#endif
#if 1
CompressTemporaries();
#endif
#if 1
ResetVisited();

View File

@ -138,6 +138,7 @@ public:
bool IsCommutative(void) const;
bool IsShift(void) const;
bool IsSimpleJSR(void) const;
bool MayBeMovedBefore(const NativeCodeInstruction& ins);
bool ReplaceYRegWithXReg(void);
bool ReplaceXRegWithYReg(void);
@ -383,6 +384,7 @@ public:
bool ExpandADCToBranch(NativeCodeProcedure* proc);
bool Split16BitLoopCount(NativeCodeProcedure* proc);
bool SimplifyDiamond(NativeCodeProcedure* proc);
bool SimplifyLoopEnd(NativeCodeProcedure* proc);
bool MoveAccuTrainUp(int at, int end);
bool MoveAccuTrainsUp(void);

View File

@ -136,6 +136,12 @@
}
"Entry"
{
"MsmKey" = "8:_23211A34D7544532ABFD8D17B647717F"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_24F2466589154E2DAA108C2EDB3BB432"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -1395,6 +1401,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_23211A34D7544532ABFD8D17B647717F"
{
"SourcePath" = "8:..\\samples\\memmap\\easyflashlow.c"
"TargetName" = "8:easyflashlow.c"
"Tag" = "8:"
"Folder" = "8:_A62A71A6A08941C5964B90112D87731F"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_24F2466589154E2DAA108C2EDB3BB432"
{
"SourcePath" = "8:..\\include\\oscar.c"

View File

@ -0,0 +1,38 @@
#include <c64/memmap.h>
#include <c64/charwin.h>
#include <c64/cia.h>
#include <c64/vic.h>
#include <string.h>
#pragma section( startup, 0 )
#pragma region( startup, 0x0100, 0x0200, , , { startup } )
#pragma region( main, 0x0400, 0x8000, , , { code, data, bss, heap, stack } )
CharWin cw;
int main(void)
{
// Copy Char ROM
mmap_set(MMAP_ALL_ROM);
memcpy((char *)0xd000, (char *)0xd000, 0x1000);
// Enable ROM
mmap_set(MMAP_ROM);
// Init CIAs (no kernal rom was executed so far)
cia_init();
// Init VIC
vic_setmode(VICM_TEXT, (char *)0xc000, (char *)0xd800);
// Prepare output window
cwin_init(&cw, (char *)0xc000, 0, 0, 40, 25);
cwin_clear(&cw);
cwin_put_string(&cw, p"Hello World", 7);
while (true) ;
}

View File

@ -8,4 +8,5 @@ call ..\..\bin\oscar64 charsetload.c -d64=charsetload.d64 -fz=../resources/chars
call ..\..\bin\oscar64 easyflash.c -n -tf=crt
call ..\..\bin\oscar64 easyflashreloc.c -n -tf=crt
call ..\..\bin\oscar64 easyflashshared.c -n -tf=crt
call ..\..\bin\oscar64 easyflashlow.c -n -tf=crt
call ..\..\bin\oscar64 tsr.c -n -dNOFLOAT -dNOLONG