Add __bankof operator

This commit is contained in:
drmortalwombat 2023-04-30 18:35:04 +02:00
parent ac7e1d5867
commit b1fc2e3736
16 changed files with 161 additions and 16 deletions

View File

@ -23,7 +23,7 @@ After extensive optimizations it turns out, that the interpreted code is not sig
## Limits and Errors
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 82 iterations per second with byte code (11831) and 365 iterations with native code (11372 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not.
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not.
### Language
@ -516,6 +516,8 @@ the start of the stack section. The size of the stack and the minimum size of t
The linker will throw an error if the heap or stack cannot be placed without collision.
The __bankof operator returns the bank id of a function or constant placed into a ROM bank.
#### Overlays

View File

@ -7,6 +7,20 @@ void vram_addr(unsigned long addr)
vera.addrh = (char)((addr >> 16) & 1) | 0x10;
}
void vram_addr0(unsigned long addr)
{
vera.ctrl &= ~VERA_CTRL_ADDRSEL;
vera.addr = (unsigned)addr;
vera.addrh = (char)((addr >> 16) & 1) | 0x00;
}
void vram_addr2(unsigned long addr)
{
vera.ctrl &= ~VERA_CTRL_ADDRSEL;
vera.addr = (unsigned)addr;
vera.addrh = (char)((addr >> 16) & 1) | 0x20;
}
void vram_put(char data)
{
vera.data0 = data;
@ -88,6 +102,17 @@ void vera_spr_set(char spr, unsigned addr32, VERASpriteMode mode8, VERASpriteSiz
vram_put((h << 6) | (w << 4) | pal);
}
void vera_spr_flip(char spr, bool fliph, bool flipv)
{
__assume(spr < 128);
vram_addr0(0x1fc00UL + spr * 8 + 6);
char b = vram_get() & 0xfc;
if (fliph) b |= 0x01;
if (flipv) b |= 0x02;
vram_put(b);
}
void vera_spr_move(char spr, int x, int y)
{
__assume(spr < 128);
@ -129,3 +154,13 @@ void vera_pal_putn(char index, const unsigned * color, unsigned size)
size--;
}
}
void vera_pal_getn(char index, unsigned * color, unsigned size)
{
vram_addr(0x1fa00ul + 2 * index);
while (size > 0)
{
*color++ = vram_getw();
size--;
}
}

View File

@ -114,6 +114,10 @@ enum VERASpritePriority
inline void vram_addr(unsigned long addr);
inline void vram_addr0(unsigned long addr);
inline void vram_addr2(unsigned long addr);
inline void vram_put(char data);
inline void vram_putw(unsigned data);
@ -134,6 +138,8 @@ void vram_fill(unsigned long addr, char data, unsigned size);
void vera_spr_set(char spr, unsigned addr32, VERASpriteMode mode8, VERASpriteSize w, VERASpriteSize h, VERASpritePriority z, char pal);
void vera_spr_flip(char spr, bool fliph, bool flipv);
void vera_spr_move(char spr, int x, int y);
void vera_spr_image(char spr, unsigned addr32);
@ -144,6 +150,8 @@ unsigned vera_pal_get(char index);
void vera_pal_putn(char index, const unsigned * color, unsigned size);
void vera_pal_getn(char index, unsigned * color, unsigned size);
#pragma compile("vera.c")
#endif

View File

@ -150,7 +150,8 @@ enum ExpressionType
EX_CASE,
EX_DEFAULT,
EX_CONDITIONAL,
EX_ASSUME
EX_ASSUME,
EX_BANKOF
};
class Expression

View File

@ -67,6 +67,7 @@ enum ErrorID
ERRR_SEMICOLON_EXPECTED,
ERRR_USE_OF_UNINITIALIZED_VARIABLE,
ERRR_STRIPE_REQUIRES_FIXED_SIZE_ARRAY,
ERRR_CANNOT_FIND_BANK_OF_EXPRESSION,
ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER,

View File

@ -2081,6 +2081,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
dec->mFlags = DTF_DEFINED;
return ExValue(dec, vl.mTemp, vl.mReference - 1);
}
case TK_BANKOF:
{
LinkerRegion* rgn;
if (exp->mLeft->mDecValue->mSection && (rgn = mLinker->FindRegionOfSection(exp->mLeft->mDecValue->mSection)))
{
uint64 i = 0;
while (i < 64 && rgn->mCartridgeBanks != (1ULL << i))
i++;
if (i < 64)
{
ins->mCode = IC_CONSTANT;
ins->mNumOperands = 0;
ins->mConst.mType = IT_INT8;
ins->mConst.mIntConst = i;
ins->mDst.mType = IT_INT8;
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
block->Append(ins);
return ExValue(TheUnsignedCharTypeDeclaration, ins->mDst.mTemp, vl.mReference - 1);
}
}
mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn");
} break;
}
ins->mSrc[0].mType = InterTypeOf(vl.mType);

View File

@ -172,6 +172,23 @@ LinkerSection* Linker::AddSection(const Ident* section, LinkerSectionType type)
}
LinkerRegion* Linker::FindRegionOfSection(LinkerSection* section)
{
LinkerRegion* srgn = nullptr;
for (int i = 0; i < mRegions.Size(); i++)
{
LinkerRegion* rgn = mRegions[i];
if (rgn->mSections.Contains(section))
{
if (srgn)
return nullptr;
srgn = rgn;
}
}
return srgn;
}
LinkerSection* Linker::FindSection(const Ident* section)
{
for (int i = 0; i < mSections.Size(); i++)

View File

@ -231,6 +231,8 @@ public:
LinkerSection * AddSection(const Ident* section, LinkerSectionType type);
LinkerSection* FindSection(const Ident* section);
LinkerRegion* FindRegionOfSection(LinkerSection* section);
LinkerObject* FindObjectByAddr(int addr);
bool IsSectionPlaced(LinkerSection* section);

View File

@ -27443,6 +27443,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[0]);
mIns.Remove(0);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
CheckLive();
return true;
@ -27747,6 +27751,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[si]);
mIns.Remove(si);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
CheckLive();
return true;
@ -27791,6 +27799,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[si]);
mIns.Remove(si);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
CheckLive();
return true;
@ -27844,6 +27856,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[si]);
mIns.Remove(si);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
CheckLive();
return true;
@ -27893,6 +27909,9 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[0]);
mIns.Remove(0);
mEntryRequiredRegs += CPU_REG_Y;
mExitRequiredRegs += CPU_REG_Y;
CheckLive();
return true;
@ -27920,6 +27939,9 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[0]);
mIns.Remove(0);
mEntryRequiredRegs += CPU_REG_X;
mExitRequiredRegs += CPU_REG_X;
CheckLive();
return true;
@ -27996,6 +28018,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[ai]);
mIns.Remove(ai);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
changed = true;
}
@ -28010,6 +28036,10 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
prevBlock->mIns.Push(mIns[ai]);
mIns.Remove(ai);
mEntryRequiredRegs += CPU_REG_A;
mExitRequiredRegs += CPU_REG_A;
prevBlock->mExitRequiredRegs += CPU_REG_A;
changed = true;
}
}
@ -28156,6 +28186,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
}
}
#if 1
if (mEntryRequiredRegs.Size() && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X]))
{
for (int i = 0; i + 1 < mIns.Size(); i++)
@ -28174,6 +28205,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
return OptimizeSimpleLoopInvariant(proc, full);
if (!mEntryRequiredRegs[CPU_REG_A])
{
assert(mIns[0].mType != ASMIT_STA);
prevBlock->mIns.Push(NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_LDA, ASMIM_ZERO_PAGE, mIns[i + 0].mAddress));
prevBlock->mIns.Push(NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 1].mAddress));
}
@ -28200,6 +28232,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
if (!mEntryRequiredRegs[CPU_REG_A])
{
assert(mIns[0].mType != ASMIT_STA);
prevBlock->mIns.Push(NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_LDA, ASMIM_ZERO_PAGE, mIns[i + 0].mAddress));
prevBlock->mIns.Push(NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 1].mAddress));
}
@ -28237,6 +28270,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
if (!mEntryRequiredRegs[CPU_REG_A])
{
assert(mIns[0].mType != ASMIT_STA);
prevBlock->mIns.Insert(k, NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_LDA, ASMIM_IMMEDIATE, mIns[i + 0].mAddress));
prevBlock->mIns.Insert(k + 1, NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 1].mAddress));
}
@ -28250,6 +28284,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
}
}
}
#endif
#if 1
for (int i = 0; i < mIns.Size(); i++)
@ -39543,6 +39578,7 @@ void NativeCodeProcedure::Optimize(void)
else
cnt++;
} while (changed);
#if 1

View File

@ -1768,7 +1768,9 @@ Expression* Parser::ParsePostfixExpression(void)
Expression* Parser::ParsePrefixExpression(void)
{
if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT || mScanner->mToken == TK_MUL || mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC || mScanner->mToken == TK_BINARY_AND)
if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT ||
mScanner->mToken == TK_MUL || mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC || mScanner->mToken == TK_BINARY_AND ||
mScanner->mToken == TK_BANKOF)
{
Expression* nexp;
if (mScanner->mToken == TK_LOGICAL_NOT)
@ -1814,6 +1816,10 @@ Expression* Parser::ParsePrefixExpression(void)
pdec->mFlags |= DTF_DEFINED;
nexp->mDecType = pdec;
}
else if (nexp->mToken == TK_BANKOF)
{
nexp->mDecType == TheUnsignedCharTypeDeclaration;
}
else
nexp->mDecType = nexp->mLeft->mDecType;
}

View File

@ -44,6 +44,7 @@ const char* TokenNames[] =
"'union'",
"'enum'",
"'sizeof'",
"'__bankof'",
"'static'",
"'auto'",
"'extern'",
@ -1342,6 +1343,8 @@ void Scanner::NextRawToken(void)
mToken = TK_ENUM;
else if (!strcmp(tkident, "sizeof"))
mToken = TK_SIZEOF;
else if (!strcmp(tkident, "__bankof"))
mToken = TK_BANKOF;
else if (!strcmp(tkident, "typedef"))
mToken = TK_TYPEDEF;
else if (!strcmp(tkident, "static"))

View File

@ -42,6 +42,7 @@ enum Token
TK_UNION,
TK_ENUM,
TK_SIZEOF,
TK_BANKOF,
TK_STATIC,
TK_AUTO,
TK_EXTERN,

View File

@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.19.198");
strcpy(strProductVersion, "1.19.199");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,19,198,0
PRODUCTVERSION 1,19,198,0
FILEVERSION 1,19,199,0
PRODUCTVERSION 1,19,199,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.19.198.0"
VALUE "FileVersion", "1.19.199.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.19.198.0"
VALUE "ProductVersion", "1.19.199.0"
END
END
BLOCK "VarFileInfo"

View File

@ -5155,15 +5155,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{1E7DBEE1-2479-49F8-9F5B-1DA786C469FD}"
"PackageCode" = "8:{F178C72F-3E89-41CE-8310-E30ADA97F214}"
"ProductCode" = "8:{A34D0747-EA76-43D6-AB25-7A788C4ECAE2}"
"PackageCode" = "8:{A35E0D83-FD72-41CF-85BC-8E74BB5E9888}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.19.198"
"ProductVersion" = "8:1.19.199"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"

View File

@ -106,6 +106,16 @@ void print6(void)
#pragma data ( data )
// Function for indirect cross bank call
void fcall(char bank, void (* func)())
{
eflash.bank = bank;
func();
}
// Macro for indirect cross bank call
#define FCALL(f) fcall(__bankof(f), f)
int main(void)
{
// Enable ROM
@ -136,14 +146,15 @@ int main(void)
eflash.bank = 3;
print3();
eflash.bank = 4;
// Get bank of function using __bankof operator
eflash.bank = __bankof print4;
print4();
eflash.bank = 5;
print5();
// Indirect call
fcall(__bankof print5, print5);
eflash.bank = 6;
print6();
// Macro call
FCALL(print6);
// Loop forever
while (true)