Prepare cartdridge linking

This commit is contained in:
drmortalwombat 2021-10-19 09:36:30 +02:00
parent 6481e119e4
commit 6444428489
9 changed files with 323 additions and 78 deletions

View File

@ -6,12 +6,58 @@ void StackStart, StackEnd, BSSStart, BSSEnd;
#pragma section(stack, 0x0000, StackStart, StackEnd)
#pragma section(bss, 0x0000, BSSStart, BSSEnd)
char spentry;
char spentry = 0;
int main(void);
__asm inp_exit
{
lda #$4c
sta $54
lda #0
sta $13
rts
}
__asm startup
{
#ifdef OSCAR_TARGET_CRT16
byt 0x09
byt 0x80
byt 0xbc
byt 0xfe
byt 0xc3
byt 0xc2
byt 0xcd
byt 0x38
byt 0x30
// Copy cartridge rom to ram
ldx #$40
ldy #$00
lda #$80
sta ip + 1
lda #$08
sta sp + 1
sty ip
sty sp
l0: lda (ip), y
sta (sp), y
iny
bne l0
inc ip + 1
inc sp + 1
dex
bne l0
lda $01
and #$fc
ora #$02
sta $01
jmp w0
w0:
#else
byt 0x0b
byt 0x08
byt 0x0a
@ -24,7 +70,7 @@ __asm startup
byt 0x00
byt 0x00
byt 0x00
#endif
// Clear BSS Segment
tsx
@ -60,6 +106,21 @@ l2: dey
bne l2
w2:
lda #<StackEnd - 2
sta sp
lda #>StackEnd - 2
sta sp + 1
#ifdef OSCAR_NATIVE_ALL
// All native code
jsr main
pexec:
exec:
jmp inp_exit
#else
// Init byte code
lda #<bcode
@ -67,10 +128,6 @@ w2:
lda #>bcode
sta ip + 1
lda #<StackEnd - 2
sta sp
lda #>StackEnd - 2
sta sp + 1
pexec:
ldy #0
exec:
@ -96,6 +153,7 @@ bcode:
byt >main
byt BC_CALL * 2
byt BC_EXIT * 2
#endif
}
#pragma startup(startup)
@ -561,15 +619,6 @@ __asm inp_nop
#pragma bytecode(BC_NOP, inp_nop)
__asm inp_exit
{
lda #$4c
sta $54
lda #0
sta $13
rts
}
#pragma bytecode(BC_EXIT, inp_exit)
__asm inp_jsr

View File

@ -3670,6 +3670,15 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 1].mCode = BC_NOP;
progress = true;
}
else if (
mIns[i + 0].mCode == BC_STORE_REG_16 &&
mIns[i + 1].LoadsRegister(BC_REG_ACCU) &&
mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
{
mIns[i + 0].mCode = BC_NOP;
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
progress = true;
}
}
#endif
#if 1
@ -3765,6 +3774,23 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i].mCode = BC_NOP;
progress = true;
}
else if ((mIns[i].mCode == BC_CONST_16 || mIns[i].mCode == BC_CONST_P8 || mIns[i].mCode == BC_CONST_N8) &&
(mIns[i + 1].mCode == BC_CONST_16 || mIns[i + 1].mCode == BC_CONST_P8 || mIns[i + 1].mCode == BC_CONST_N8 || mIns[i + 1].mCode == BC_CONST_32) && mIns[i].mRegister == mIns[i + 1].mRegister)
{
mIns[i].mCode = BC_NOP;
progress = true;
}
else if (mIns[i].mCode == BC_CONST_32 && mIns[i + 1].mCode == BC_CONST_32 && mIns[i].mRegister == mIns[i + 1].mRegister)
{
mIns[i].mCode = BC_NOP;
progress = true;
}
else if (mIns[i].mCode == BC_CONST_8 && mIns[i + 1].mCode == BC_CONST_8 && mIns[i].mRegister == mIns[i + 1].mRegister)
{
mIns[i].mCode = BC_NOP;
progress = true;
}
#if 0
else if ((mIns[i].mCode == BC_LOAD_LOCAL_16 || mIns[i].mCode == BC_LOAD_ABS_16) && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
{

View File

@ -123,25 +123,45 @@ bool Compiler::GenerateCode(void)
const Ident* identCode = Ident::Unique("code");
LinkerRegion* regionStartup = mLinker->FindRegion(identStartup);
if (!regionStartup)
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900);
LinkerRegion* regionBytecode = mLinker->FindRegion(identBytecode);
if (!regionBytecode)
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
if (!regionStartup)
{
if (mCompilerOptions & COPT_TARGET_PRG)
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900);
else
regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900);
}
LinkerRegion* regionBytecode = nullptr;
if (!(mCompilerOptions & COPT_NATIVE))
{
regionBytecode = mLinker->FindRegion(identBytecode);
if (!regionBytecode)
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
}
LinkerRegion* regionMain = mLinker->FindRegion(identMain);
LinkerSection * sectionStartup = mLinker->AddSection(identStartup, LST_DATA);
LinkerSection * sectionBytecode = mLinker->AddSection(identBytecode, LST_DATA);
LinkerSection* sectionBytecode = nullptr;
if (regionBytecode)
{
sectionBytecode = mLinker->AddSection(identBytecode, LST_DATA);
}
regionStartup->mSections.Push(sectionStartup);
regionBytecode->mSections.Push(sectionBytecode);
if (regionBytecode)
regionBytecode->mSections.Push(sectionBytecode);
if (!mLinker->IsSectionPlaced(mCompilationUnits->mSectionCode))
{
if (!regionMain)
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
{
if (regionBytecode)
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
else
regionMain = mLinker->AddRegion(identMain, 0x0900, 0xa000);
}
regionMain->mSections.Push(mCompilationUnits->mSectionCode);
regionMain->mSections.Push(mCompilationUnits->mSectionData);
@ -239,49 +259,53 @@ bool Compiler::GenerateCode(void)
}
}
// Compile used byte code functions
LinkerObject* byteCodeObject = mLinker->AddObject(loc, Ident::Unique("bytecode"), sectionBytecode, LOT_RUNTIME);
for (int i = 0; i < 128; i++)
LinkerObject* byteCodeObject = nullptr;
if (!(mCompilerOptions & COPT_NATIVE))
{
if (mByteCodeGenerator->mByteCodeUsed[i])
// Compile used byte code functions
byteCodeObject = mLinker->AddObject(loc, Ident::Unique("bytecode"), sectionBytecode, LOT_RUNTIME);
for (int i = 0; i < 128; i++)
{
Declaration* bcdec = mCompilationUnits->mByteCodes[i];
if (bcdec)
if (mByteCodeGenerator->mByteCodeUsed[i])
{
LinkerObject* linkerObject = nullptr;
int offset = 0;
if (bcdec->mType == DT_CONST_ASSEMBLER)
Declaration* bcdec = mCompilationUnits->mByteCodes[i];
if (bcdec)
{
if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
linkerObject = bcdec->mLinkerObject;
LinkerObject* linkerObject = nullptr;
int offset = 0;
if (bcdec->mType == DT_CONST_ASSEMBLER)
{
if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
linkerObject = bcdec->mLinkerObject;
}
else if (bcdec->mType == DT_LABEL)
{
if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
linkerObject = bcdec->mBase->mLinkerObject;
offset = bcdec->mInteger;
}
assert(linkerObject);
LinkerReference lref;
lref.mObject = byteCodeObject;
lref.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
lref.mOffset = 2 * i;
lref.mRefObject = linkerObject;
lref.mRefOffset = offset;
byteCodeObject->AddReference(lref);
}
else if (bcdec->mType == DT_LABEL)
else
{
if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
linkerObject = bcdec->mBase->mLinkerObject;
offset = bcdec->mInteger;
char n[10];
sprintf_s(n, "%d", i);
mErrors->Error(loc, EERR_RUNTIME_CODE, "Missing byte code implementation", n);
}
assert(linkerObject);
LinkerReference lref;
lref.mObject = byteCodeObject;
lref.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
lref.mOffset = 2 * i;
lref.mRefObject = linkerObject;
lref.mRefOffset = offset;
byteCodeObject->AddReference(lref);
}
else
{
char n[10];
sprintf_s(n, "%d", i);
mErrors->Error(loc, EERR_RUNTIME_CODE, "Missing byte code implementation", n);
}
}
}
@ -289,7 +313,9 @@ bool Compiler::GenerateCode(void)
mLinker->CollectReferences();
mLinker->ReferenceObject(dcrtstart->mLinkerObject);
mLinker->ReferenceObject(byteCodeObject);
if (!(mCompilerOptions & COPT_NATIVE))
mLinker->ReferenceObject(byteCodeObject);
mLinker->Link();
@ -298,7 +324,7 @@ bool Compiler::GenerateCode(void)
bool Compiler::WriteOutputFile(const char* targetPath)
{
char prgPath[200], mapPath[200], asmPath[200], lblPath[200];
char prgPath[200], mapPath[200], asmPath[200], lblPath[200], crtPath[200];
strcpy_s(prgPath, targetPath);
int i = strlen(prgPath);
@ -309,14 +335,25 @@ bool Compiler::WriteOutputFile(const char* targetPath)
strcpy_s(mapPath, prgPath);
strcpy_s(asmPath, prgPath);
strcpy_s(lblPath, prgPath);
strcpy_s(crtPath, prgPath);
strcat_s(prgPath, "prg");
strcat_s(mapPath, "map");
strcat_s(asmPath, "asm");
strcat_s(lblPath, "lbl");
strcat_s(crtPath, "crt");
if (mCompilerOptions & COPT_TARGET_PRG)
{
printf("Writing <%s>\n", prgPath);
mLinker->WritePrgFile(prgPath);
}
else if (mCompilerOptions & COPT_TARGET_CRT16)
{
printf("Writing <%s>\n", crtPath);
mLinker->WriteCrtFile(crtPath);
}
printf("Writing <%s>\n", prgPath);
mLinker->WritePrgFile(prgPath);
printf("Writing <%s>\n", mapPath);
mLinker->WriteMapFile(mapPath);
@ -336,10 +373,21 @@ int Compiler::ExecuteCode(void)
printf("Running emulation...\n");
Emulator* emu = new Emulator(mLinker);
memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart);
emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff;
emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8;
int ecode = emu->Emulate(2061);
int ecode = 20;
if (mCompilerOptions & COPT_TARGET_PRG)
{
memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart);
emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff;
emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8;
ecode = emu->Emulate(2061);
}
else if (mCompilerOptions & COPT_TARGET_CRT16)
{
memcpy(emu->mMemory + 0x8000, mLinker->mMemory + 0x0800, 0x4000);
ecode = emu->Emulate(0x8009);
}
printf("Emulation result %d\n", ecode);
if (ecode != 0)

View File

@ -8,6 +8,11 @@ static const uint64 COPT_OPTIMIZE_INLINE = 0x00000002;
static const uint64 COPT_OPTIMIZE_AUTO_INLINE = 0x00000010;
static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 0x00000020;
static const uint64 COPT_TARGET_PRG = 0x100000000ULL;
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;
static const uint64 COPT_TARGET_COPY = 0x800000000ULL;
static const uint64 COPT_NATIVE = 0x01000000;
static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE;

View File

@ -197,7 +197,7 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
else if (adec->mType == DT_CONST_FUNCTION)
{
AnalyzeProcedure(adec->mValue, adec);
RegisterCall(adec, procDec);
RegisterCall(procDec, adec);
}
}

View File

@ -333,6 +333,98 @@ bool Linker::WritePrgFile(const char* filename)
return false;
}
bool Linker::WriteCrtFile(const char* filename)
{
FILE* file;
fopen_s(&file, filename, "wb");
if (file)
{
struct CRIHeader
{
char mSignature[16];
uint32 mHeaderLength;
uint16 mVersion, mHardware;
uint8 mExrom, mGameLine;
uint8 mPad[6];
char mName[32];
} criHeader = { 0 };
memcpy(criHeader.mSignature, "C64 CARTRIDGE ", 16);
criHeader.mHeaderLength = 0x40000000;
criHeader.mVersion = 0x0001;
criHeader.mHardware = 0x2000;
criHeader.mExrom = 1;
criHeader.mGameLine = 1;
memset(criHeader.mName, 0, 32);
strcpy_s(criHeader.mName, "OSCAR");
fwrite(&criHeader, sizeof(CRIHeader), 1, file);
struct CHIPHeader
{
char mSignature[4];
uint32 mPacketLength;
uint16 mChipType, mBankNumber, mLoadAddress, mImageSize;
} chipHeader = { 0 };
memcpy(chipHeader.mSignature, "CHIP", 4);
chipHeader.mPacketLength = 0x10200000;
chipHeader.mChipType = 0;
chipHeader.mBankNumber = 0;
chipHeader.mImageSize = 0x0020;
char * bootmem = new char[8192];
chipHeader.mLoadAddress = 0x0080;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(bootmem, 1, 0x2000, file);
bootmem[0x1ffc] = 0x00;
bootmem[0x1ffd] = 0xe0;
char bootcode[] = {
0xa9, 0x87,
0x8d, 0x02, 0xde,
0xa9, 0x01,
0x8d, 0x00, 0xde,
0x6c, 0xfc, 0xff
};
int j = 0;
for (int i = 0; i < sizeof(bootcode); i++)
{
bootmem[j++] = 0xa9;
bootmem[j++] = bootcode[i];
bootmem[j++] = 0x8d;
bootmem[j++] = i;
bootmem[j++] = 0x04;
}
bootmem[j++] = 0x4c;
bootmem[j++] = 0x00;
bootmem[j++] = 0x04;
chipHeader.mLoadAddress = 0x00e0;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(bootmem, 1, 0x2000, file);
chipHeader.mBankNumber = 0x100;
chipHeader.mLoadAddress = 0x0080;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mMemory + 0x0800, 1, 0x2000, file);
chipHeader.mLoadAddress = 0x00a0;
fwrite(&chipHeader, sizeof(chipHeader), 1, file);
fwrite(mMemory + 0x2800, 1, 0x2000, file);
fclose(file);
return true;
}
else
return false;
}
bool Linker::WriteMapFile(const char* filename)
{
FILE* file;

View File

@ -130,6 +130,7 @@ public:
bool WriteMapFile(const char* filename);
bool WriteAsmFile(const char* filename);
bool WriteLblFile(const char* filename);
bool WriteCrtFile(const char* filename);
GrowingArray<LinkerReference*> mReferences;
GrowingArray<LinkerRegion*> mRegions;

View File

@ -978,7 +978,7 @@ void Scanner::NextRawToken(void)
case '#':
{
if (!mAssemblerMode || mOffset == 1)
if (!(mAssemblerMode || mPrepCondFalse) || mOffset == 1)
{
int n = 0;
char tkprep[128];

View File

@ -116,6 +116,9 @@ int main(int argc, const char** argv)
targetPath[0] = 0;
char targetFormat[20];
strcpy_s(targetFormat, "prg");
for (int i = 1; i < argc; i++)
{
const char* arg = argv[i];
@ -133,9 +136,14 @@ int main(int argc, const char** argv)
{
strcpy_s(crtPath, arg + 4);
}
else if (arg[1] == 't' && arg[2] == 'f' && arg[3] == '=')
{
strcpy_s(targetFormat, arg + 4);
}
else if (arg[1] == 'n')
{
compiler->mCompilerOptions |= COPT_NATIVE;
compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1");
}
else if (arg[1] == 'O')
{
@ -180,16 +188,32 @@ int main(int argc, const char** argv)
}
}
// Add runtime module
compiler->mCompilationUnits->AddUnit(loc, crtPath, nullptr);
if (compiler->ParseSource() && compiler->GenerateCode())
if (!strcmp(targetFormat, "prg"))
{
compiler->WriteOutputFile(targetPath);
compiler->mCompilerOptions |= COPT_TARGET_PRG;
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_PRG"), "1");
}
else if (!strcmp(targetFormat, "crt"))
{
compiler->mCompilerOptions |= COPT_TARGET_CRT16;
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_CRT16"), "1");
}
else
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid target format option", targetFormat);
if (emulate)
compiler->ExecuteCode();
if (compiler->mErrors->mErrorCount == 0)
{
// Add runtime module
compiler->mCompilationUnits->AddUnit(loc, crtPath, nullptr);
if (compiler->ParseSource() && compiler->GenerateCode())
{
compiler->WriteOutputFile(targetPath);
if (emulate)
compiler->ExecuteCode();
}
}
if (compiler->mErrors->mErrorCount != 0)