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(stack, 0x0000, StackStart, StackEnd)
#pragma section(bss, 0x0000, BSSStart, BSSEnd) #pragma section(bss, 0x0000, BSSStart, BSSEnd)
char spentry; char spentry = 0;
int main(void); int main(void);
__asm inp_exit
{
lda #$4c
sta $54
lda #0
sta $13
rts
}
__asm startup __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 0x0b
byt 0x08 byt 0x08
byt 0x0a byt 0x0a
@ -24,7 +70,7 @@ __asm startup
byt 0x00 byt 0x00
byt 0x00 byt 0x00
byt 0x00 byt 0x00
#endif
// Clear BSS Segment // Clear BSS Segment
tsx tsx
@ -60,6 +106,21 @@ l2: dey
bne l2 bne l2
w2: 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 // Init byte code
lda #<bcode lda #<bcode
@ -67,10 +128,6 @@ w2:
lda #>bcode lda #>bcode
sta ip + 1 sta ip + 1
lda #<StackEnd - 2
sta sp
lda #>StackEnd - 2
sta sp + 1
pexec: pexec:
ldy #0 ldy #0
exec: exec:
@ -96,6 +153,7 @@ bcode:
byt >main byt >main
byt BC_CALL * 2 byt BC_CALL * 2
byt BC_EXIT * 2 byt BC_EXIT * 2
#endif
} }
#pragma startup(startup) #pragma startup(startup)
@ -561,15 +619,6 @@ __asm inp_nop
#pragma bytecode(BC_NOP, 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) #pragma bytecode(BC_EXIT, inp_exit)
__asm inp_jsr __asm inp_jsr

View File

@ -3670,6 +3670,15 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i + 1].mCode = BC_NOP; mIns[i + 1].mCode = BC_NOP;
progress = true; 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 #endif
#if 1 #if 1
@ -3765,6 +3774,23 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
mIns[i].mCode = BC_NOP; mIns[i].mCode = BC_NOP;
progress = true; 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 #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) 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

@ -124,24 +124,44 @@ bool Compiler::GenerateCode(void)
LinkerRegion* regionStartup = mLinker->FindRegion(identStartup); LinkerRegion* regionStartup = mLinker->FindRegion(identStartup);
if (!regionStartup) if (!regionStartup)
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900); {
if (mCompilerOptions & COPT_TARGET_PRG)
regionStartup = mLinker->AddRegion(identStartup, 0x0801, 0x0900);
else
regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900);
}
LinkerRegion* regionBytecode = mLinker->FindRegion(identBytecode); LinkerRegion* regionBytecode = nullptr;
if (!regionBytecode) if (!(mCompilerOptions & COPT_NATIVE))
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00); {
regionBytecode = mLinker->FindRegion(identBytecode);
if (!regionBytecode)
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
}
LinkerRegion* regionMain = mLinker->FindRegion(identMain); LinkerRegion* regionMain = mLinker->FindRegion(identMain);
LinkerSection * sectionStartup = mLinker->AddSection(identStartup, LST_DATA); 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); regionStartup->mSections.Push(sectionStartup);
regionBytecode->mSections.Push(sectionBytecode);
if (regionBytecode)
regionBytecode->mSections.Push(sectionBytecode);
if (!mLinker->IsSectionPlaced(mCompilationUnits->mSectionCode)) if (!mLinker->IsSectionPlaced(mCompilationUnits->mSectionCode))
{ {
if (!regionMain) 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->mSectionCode);
regionMain->mSections.Push(mCompilationUnits->mSectionData); regionMain->mSections.Push(mCompilationUnits->mSectionData);
@ -239,49 +259,53 @@ bool Compiler::GenerateCode(void)
} }
} }
// Compile used byte code functions LinkerObject* byteCodeObject = nullptr;
if (!(mCompilerOptions & COPT_NATIVE))
LinkerObject* byteCodeObject = mLinker->AddObject(loc, Ident::Unique("bytecode"), sectionBytecode, LOT_RUNTIME);
for (int i = 0; i < 128; i++)
{ {
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 (mByteCodeGenerator->mByteCodeUsed[i])
if (bcdec)
{ {
LinkerObject* linkerObject = nullptr; Declaration* bcdec = mCompilationUnits->mByteCodes[i];
if (bcdec)
int offset = 0;
if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) LinkerObject* linkerObject = nullptr;
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
linkerObject = bcdec->mLinkerObject; 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) char n[10];
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr); sprintf_s(n, "%d", i);
linkerObject = bcdec->mBase->mLinkerObject; mErrors->Error(loc, EERR_RUNTIME_CODE, "Missing byte code implementation", n);
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
{
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->CollectReferences();
mLinker->ReferenceObject(dcrtstart->mLinkerObject); mLinker->ReferenceObject(dcrtstart->mLinkerObject);
mLinker->ReferenceObject(byteCodeObject);
if (!(mCompilerOptions & COPT_NATIVE))
mLinker->ReferenceObject(byteCodeObject);
mLinker->Link(); mLinker->Link();
@ -298,7 +324,7 @@ bool Compiler::GenerateCode(void)
bool Compiler::WriteOutputFile(const char* targetPath) 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); strcpy_s(prgPath, targetPath);
int i = strlen(prgPath); int i = strlen(prgPath);
@ -309,14 +335,25 @@ bool Compiler::WriteOutputFile(const char* targetPath)
strcpy_s(mapPath, prgPath); strcpy_s(mapPath, prgPath);
strcpy_s(asmPath, prgPath); strcpy_s(asmPath, prgPath);
strcpy_s(lblPath, prgPath); strcpy_s(lblPath, prgPath);
strcpy_s(crtPath, prgPath);
strcat_s(prgPath, "prg"); strcat_s(prgPath, "prg");
strcat_s(mapPath, "map"); strcat_s(mapPath, "map");
strcat_s(asmPath, "asm"); strcat_s(asmPath, "asm");
strcat_s(lblPath, "lbl"); 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); printf("Writing <%s>\n", mapPath);
mLinker->WriteMapFile(mapPath); mLinker->WriteMapFile(mapPath);
@ -336,10 +373,21 @@ int Compiler::ExecuteCode(void)
printf("Running emulation...\n"); printf("Running emulation...\n");
Emulator* emu = new Emulator(mLinker); Emulator* emu = new Emulator(mLinker);
memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart);
emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff; int ecode = 20;
emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8; if (mCompilerOptions & COPT_TARGET_PRG)
int ecode = emu->Emulate(2061); {
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); printf("Emulation result %d\n", ecode);
if (ecode != 0) 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 = 0x00000010;
static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 0x00000020; 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_NATIVE = 0x01000000;
static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE; 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) else if (adec->mType == DT_CONST_FUNCTION)
{ {
AnalyzeProcedure(adec->mValue, adec); AnalyzeProcedure(adec->mValue, adec);
RegisterCall(adec, procDec); RegisterCall(procDec, adec);
} }
} }

View File

@ -333,6 +333,98 @@ bool Linker::WritePrgFile(const char* filename)
return false; 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) bool Linker::WriteMapFile(const char* filename)
{ {
FILE* file; FILE* file;

View File

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

View File

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

View File

@ -116,6 +116,9 @@ int main(int argc, const char** argv)
targetPath[0] = 0; targetPath[0] = 0;
char targetFormat[20];
strcpy_s(targetFormat, "prg");
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
const char* arg = argv[i]; const char* arg = argv[i];
@ -133,9 +136,14 @@ int main(int argc, const char** argv)
{ {
strcpy_s(crtPath, arg + 4); 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') else if (arg[1] == 'n')
{ {
compiler->mCompilerOptions |= COPT_NATIVE; compiler->mCompilerOptions |= COPT_NATIVE;
compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1");
} }
else if (arg[1] == 'O') else if (arg[1] == 'O')
{ {
@ -180,16 +188,32 @@ int main(int argc, const char** argv)
} }
} }
// Add runtime module if (!strcmp(targetFormat, "prg"))
compiler->mCompilationUnits->AddUnit(loc, crtPath, nullptr);
if (compiler->ParseSource() && compiler->GenerateCode())
{ {
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) if (compiler->mErrors->mErrorCount == 0)
compiler->ExecuteCode(); {
// 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) if (compiler->mErrors->mErrorCount != 0)