From 05ef25a61eaf4418da5a4dbcb4c5661c2b9d7b3a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 11 May 2025 12:41:40 +0200 Subject: [PATCH] Add optimization -Ox to simplify pointer arithmetic by non page crossing --- autotest/autotest.bat | 15 ++++++ oscar64/CompilerTypes.h | 1 + oscar64/Declaration.cpp | 16 ++++++ oscar64/Declaration.h | 2 + oscar64/InterCode.cpp | 86 ++++++++++++++++++++++++++--- oscar64/InterCode.h | 4 +- oscar64/InterCodeGenerator.cpp | 10 ++++ oscar64/Linker.cpp | 4 +- oscar64/Linker.h | 1 + oscar64/NativeCodeGenerator.cpp | 95 ++++++++++++++++++++++++++++++--- oscar64/Parser.cpp | 21 ++++++++ oscar64/oscar64.cpp | 2 + 12 files changed, 237 insertions(+), 20 deletions(-) diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 2097a32..230f0f5 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -277,6 +277,15 @@ exit /b %errorlevel% ..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1 @if %errorlevel% neq 0 goto :error +..\bin\oscar64 -e -O2 -xz -Oz -n %~1 +@if %errorlevel% neq 0 goto :error + +..\bin\oscar64 -e -O2 -Oo -n %~1 +@if %errorlevel% neq 0 goto :error + +..\bin\oscar64 -e -O2 -Ox -n %~1 +@if %errorlevel% neq 0 goto :error + ..\bin\oscar64 -e -O0 -bc %~1 @if %errorlevel% neq 0 goto :error @@ -337,6 +346,9 @@ exit /b %errorlevel% ..\bin\oscar64 -e -O2 -Oo -n %~1 @if %errorlevel% neq 0 goto :error +..\bin\oscar64 -e -O2 -Ox -n %~1 +@if %errorlevel% neq 0 goto :error + @exit /b 0 :testb @@ -379,4 +391,7 @@ exit /b %errorlevel% ..\bin\oscar64 -e -O2 -Oo -n %~1 @if %errorlevel% neq 0 goto :error +..\bin\oscar64 -e -O2 -Ox -n %~1 +@if %errorlevel% neq 0 goto :error + @exit /b 0 diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 75dc289..134e6be 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -15,6 +15,7 @@ static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10; static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11; static const uint64 COPT_OPTIMIZE_OUTLINE = 1ULL << 12; +static const uint64 COPT_OPTIMIZE_PAGE_CROSSING = 1ULL << 13; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_NATIVE = 1ULL << 17; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 9a56d54..c77e5e5 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -3042,6 +3042,22 @@ bool Declaration::IsIndexed(void) const return mType == DT_TYPE_ARRAY || mType == DT_TYPE_POINTER; } +bool Declaration::ContainsArray(void) const +{ + if (mType == DT_TYPE_ARRAY) + return true; + else if (mType == DT_TYPE_STRUCT) + { + Declaration* p = mParams; + while (p) + { + if (p->mType == DT_ELEMENT && p->mBase->ContainsArray()) + return true; + p = p->mNext; + } + } + return false; +} bool Declaration::IsSimpleType(void) const { diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 9432ee9..954d593 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -127,6 +127,7 @@ static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49); static const uint64 DTF_DEPRECATED = (1ULL << 50); static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51); static const uint64 DTF_PLACED = (1ULL << 52); +static const uint64 DTF_NO_PAGE_CROSS = (1ULL << 53); @@ -333,6 +334,7 @@ public: bool IsSimpleType(void) const; bool IsReference(void) const; bool IsIndexed(void) const; + bool ContainsArray(void) const; void SetDefined(void); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d9fa09a..9b8b116 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -17506,7 +17506,7 @@ void InterCodeBasicBlock::RemoveUnusedMallocs(void) } } -void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue) +void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue, bool loops) { if (!mVisited) { @@ -17536,6 +17536,57 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt } } } + else if (loops && mNumEntries == 2) + { + InterCodeBasicBlock* tail, * post; + + if (mEntryBlocks[0] == mLoopPrefix) + tail = mEntryBlocks[1]; + else + tail = mEntryBlocks[0]; + + if (tail->mTrueJump == this) + post = tail->mFalseJump; + else + post = tail->mTrueJump; + + if (post && post->mNumEntries == 1) + { + GrowingArray body(nullptr); + + if (tail->CollectSingleHeadLoopBody(this, tail, body)) + { + for (int i = 0; i < ltvalue.Size(); i++) + { + if (ltvalue[i]) + { + bool fail = false; + + for (int k = 0; k < body.Size() && !fail; k++) + { + InterCodeBasicBlock* b = body[k]; + for (int j = 0; j < b->mInstructions.Size() && !fail; j++) + { + InterInstruction* ins = b->mInstructions[j]; + if (ins->mDst.mTemp == i) + { + if (ins->mCode == IC_LEA && ins->mSrc[1].mTemp == i) + ; + else + fail = true; + } + } + } + + if (fail) + { + ltvalue[i] = nullptr; + } + } + } + } + } + } else ltvalue.Clear(); } @@ -17567,18 +17618,22 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt for (int j = 0; j < ins->mNumOperands; j++) { - if (ins->mSrc[j].mTemp > 0 && ltvalue[ins->mSrc[j].mTemp] && ins->mSrc[j].mType == IT_POINTER) + if (ins->mSrc[j].mTemp >= 0 && ltvalue[ins->mSrc[j].mTemp] && ins->mSrc[j].mType == IT_POINTER) { ins->mSrc[j].mRestricted = ltvalue[ins->mSrc[j].mTemp]->mDst.mRestricted; ins->mSrc[j].mMemoryBase = ltvalue[ins->mSrc[j].mTemp]->mDst.mMemoryBase; ins->mSrc[j].mVarIndex = ltvalue[ins->mSrc[j].mTemp]->mDst.mVarIndex; ins->mSrc[j].mLinkerObject = ltvalue[ins->mSrc[j].mTemp]->mDst.mLinkerObject; + if (ins->mSrc[j].mMemory == IM_NONE && ins->mSrc[j].mMemoryBase != IM_NONE) + ins->mSrc[j].mMemory = IM_INDIRECT; + assert(ins->mSrc[j].mMemoryBase != IM_LOCAL || ins->mSrc[j].mVarIndex >= 0); } } if (ins->mCode == IC_LEA) { + ins->mDst.mMemory = ins->mSrc[1].mMemory; ins->mDst.mRestricted = ins->mSrc[1].mRestricted; if (ins->mSrc[1].mMemory != IM_INDIRECT) ins->mSrc[1].mMemoryBase = ins->mSrc[1].mMemory; @@ -17588,6 +17643,7 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt } else if (ins->mCode == IC_LOAD_TEMPORARY) { + ins->mDst.mMemory = ins->mSrc[0].mMemory; ins->mDst.mRestricted = ins->mSrc[0].mRestricted; ins->mDst.mMemoryBase = ins->mSrc[0].mMemoryBase; ins->mDst.mVarIndex = ins->mSrc[0].mVarIndex; @@ -17595,6 +17651,7 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt } else if (ins->mCode == IC_CONSTANT) { + ins->mDst.mMemory = ins->mConst.mMemory; ins->mDst.mRestricted = ins->mConst.mRestricted; ins->mDst.mMemoryBase = ins->mConst.mMemory; ins->mDst.mVarIndex = ins->mConst.mVarIndex; @@ -17611,8 +17668,8 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt } - if (mTrueJump) mTrueJump->PropagateMemoryAliasingInfo(ltvalue); - if (mFalseJump) mFalseJump->PropagateMemoryAliasingInfo(ltvalue); + if (mTrueJump) mTrueJump->PropagateMemoryAliasingInfo(ltvalue, loops); + if (mFalseJump) mFalseJump->PropagateMemoryAliasingInfo(ltvalue, loops); } } @@ -22801,12 +22858,21 @@ void InterCodeProcedure::EliminateDoubleLoopCounter(void) } -void InterCodeProcedure::PropagateMemoryAliasingInfo(void) +void InterCodeProcedure::PropagateMemoryAliasingInfo(bool loops) { GrowingInstructionPtrArray tvalue(nullptr); + if (loops) + { + BuildTraces(0); + BuildLoopPrefix(); + ResetEntryBlocks(); + ResetVisited(); + mEntryBlock->CollectEntryBlocks(nullptr); + } + ResetVisited(); - mEntryBlock->PropagateMemoryAliasingInfo(tvalue); + mEntryBlock->PropagateMemoryAliasingInfo(tvalue, loops); Disassemble("PropagateMemoryAliasingInfo"); } @@ -23401,7 +23467,7 @@ void InterCodeProcedure::LoadStoreForwarding(InterMemory paramMemory) bool changed; do { - PropagateMemoryAliasingInfo(); + PropagateMemoryAliasingInfo(false); GrowingInstructionPtrArray gipa(nullptr); ResetVisited(); @@ -23506,7 +23572,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "mbox::show"); + CheckFunc = !strcmp(mIdent->mString, "mbox::configure_animations"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -23984,6 +24050,8 @@ void InterCodeProcedure::Close(void) SingleTailLoopOptimization(paramMemory); BuildDataFlowSets(); + PropagateMemoryAliasingInfo(true); + #if 1 ExpandSelect(); @@ -24179,6 +24247,8 @@ void InterCodeProcedure::Close(void) #endif + PropagateMemoryAliasingInfo(true); + ResetVisited(); mEntryBlock->SimplifyIntegerRangeRelops(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 36e13a7..c75619f 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -638,7 +638,7 @@ public: void SingleLoopCountZeroCheck(void); bool PostDecLoopOptimization(void); - void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue); + void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue, bool loops); void RemoveUnusedMallocs(void); bool PullStoreUpToConstAddress(void); @@ -804,7 +804,7 @@ protected: void CheckUsedDefinedTemps(void); void WarnUsedUndefinedVariables(void); void WarnInvalidValueRanges(void); - void PropagateMemoryAliasingInfo(void); + void PropagateMemoryAliasingInfo(bool loops); void MoveConditionsOutOfLoop(void); void ShortcutConstBranches(void); void ShortcutDuplicateBranches(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 42e84e5..34bd22f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -782,6 +782,16 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* var->mLinkerObject->mFlags |= LOBJF_CONST; if (dec->mFlags & DTF_ZEROPAGE) var->mLinkerObject->mFlags |= LOBJF_ZEROPAGE; + if (dec->mFlags & DTF_NO_PAGE_CROSS) + var->mLinkerObject->mFlags |= LOBJF_NEVER_CROSS | LOBJF_NO_CROSS; + if (mCompilerOptions & COPT_OPTIMIZE_PAGE_CROSSING) + { + if (dec->mSize <= 256 && dec->mSize > 1) + { + if (dec->mBase->ContainsArray()) + var->mLinkerObject->mFlags |= LOBJF_NEVER_CROSS | LOBJF_NO_CROSS; + } + } var->mIndex = mod->mGlobalVars.Size(); var->mDeclaration = dec; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index d0c4159..3276b3e 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -650,7 +650,7 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge, boo int start = (mFreeChunks[i].mStart + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1); int end = start + lobj->mSize; - if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00) && !(lobj->mSection->mFlags & LSECF_PACKED)) + if (((lobj->mFlags & LOBJF_NEVER_CROSS) || !(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mSection->mFlags & LSECF_PACKED)) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00)) ; else if (end <= mFreeChunks[i].mEnd) { @@ -702,7 +702,7 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge, boo int start = (mStart + mUsed + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1); int end = start + lobj->mSize; - if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && !retry && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mFlags & LOBJF_FORCE_ALIGN) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00) && !(lobj->mSection->mFlags & LSECF_PACKED)) + if (((lobj->mFlags & LOBJF_NEVER_CROSS) || !(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && !retry && (lobj->mFlags & LOBJF_NO_CROSS) && !(lobj->mSection->mFlags & LSECF_PACKED)) && !(lobj->mFlags & LOBJF_FORCE_ALIGN) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00)) { start = (start + 0x00ff) & 0xff00; end = start + lobj->mSize; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 56bcd2b..0301a1c 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -156,6 +156,7 @@ static const uint32 LOBJF_NO_CROSS = 0x00000080; static const uint32 LOBJF_ZEROPAGE = 0x00000100; static const uint32 LOBJF_FORCE_ALIGN = 0x00000200; static const uint32 LOBJF_ZEROPAGESET = 0x00000400; +static const uint32 LOBJF_NEVER_CROSS = 0x00000800; static const uint32 LOBJF_ARG_REG_A = 0x00001000; static const uint32 LOBJF_ARG_REG_X = 0x00002000; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 0d209ca..1e52bd6 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3617,6 +3617,62 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_A].mValue >= mAddress; } + else if (mMode == ASMIM_IMMEDIATE_ADDRESS && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE_ADDRESS) + { + if (mLinkerObject == data.mRegs[CPU_REG_A].mLinkerObject) + { + if (mLinkerObject) + { + if (mLinkerObject->mFlags & LOBJF_NEVER_CROSS) + { + if (mFlags & NCIF_LOWER) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = (data.mRegs[CPU_REG_A].mValue - mAddress) & 0xff; + } + else + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = 0; + } + } + else + { + if (mFlags & NCIF_LOWER) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = (data.mRegs[CPU_REG_A].mValue & 0xff) == (mAddress & 0xff) ? 0 : 1; + } + else if (data.mRegs[CPU_REG_A].mValue == mAddress) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = 0; + } + else + data.mRegs[CPU_REG_Z].Reset(); + } + } + else + { + if (mFlags & NCIF_LOWER) + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = (data.mRegs[CPU_REG_A].mValue - mAddress) & 0xff; + } + else + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = ((data.mRegs[CPU_REG_A].mValue - mAddress) >> 8) & 0xff; + } + } + } + else + { + data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE; + data.mRegs[CPU_REG_Z].mValue = 1; + } + data.mRegs[CPU_REG_C].Reset(); + } else if (mMode == ASMIM_IMMEDIATE && mAddress == 0) { data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; @@ -14223,6 +14279,10 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const } else { + bool crossing = true; + if (ins->mSrc[1].mMemoryBase == IM_GLOBAL && ins->mSrc[1].mLinkerObject && (ins->mSrc[1].mLinkerObject->mFlags & LOBJF_NEVER_CROSS)) + crossing = false; + if (ins->mSrc[0].mTemp >= 0 || ins->mSrc[0].mIntConst != 0) mIns.Push(NativeCodeInstruction(ins, isub ? ASMIT_SEC : ASMIT_CLC, ASMIM_IMPLIED)); @@ -14240,15 +14300,18 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - if (ins->mSrc[0].mTemp < 0) + if (crossing) { - if (ins->mSrc[0].mIntConst) - mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff)); + if (ins->mSrc[0].mTemp < 0) + { + if (ins->mSrc[0].mIntConst) + mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff)); + } + else if (ins->mSrc[0].IsUByte()) + mIns.Push(NativeCodeInstruction(ins, iop, ASMIM_IMMEDIATE, 0)); + else + mIns.Push(NativeCodeInstruction(ins, iop, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ireg] + 1)); } - else if (ins->mSrc[0].IsUByte()) - mIns.Push(NativeCodeInstruction(ins, iop, ASMIM_IMMEDIATE, 0)); - else - mIns.Push(NativeCodeInstruction(ins, iop, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ireg] + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); } @@ -50945,6 +51008,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterateN(int i, int pass) } } + if (i + 6 < mIns.Size() && pass > 3 && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[i + 1].mLinkerObject && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_IMMEDIATE_ADDRESS && mIns[i + 1].mLinkerObject == mIns[i + 3].mLinkerObject && + mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 && + mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1) + { + if (mIns[i + 1].mLinkerObject->mFlags & LOBJF_NEVER_CROSS) + { + mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED; + return true; + } + + } + if (i + 7 < mIns.Size() && pass > 3 && mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && @@ -54650,7 +54729,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mInterProc->mLinkerObject->mNativeProc = this; - CheckFunc = !strcmp(mIdent->mString, "mbox::show"); + CheckFunc = !strcmp(mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3b2dbfe..8de9c9e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -13728,6 +13728,27 @@ void Parser::ParsePragma(void) ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "nocross")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + + if (mScanner->mToken == TK_IDENT) + { + Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_VARIABLE && (dec->mFlags & DTF_GLOBAL)) + dec->mFlags |= DTF_NO_PAGE_CROSS; + else if (dec && dec->mType == DT_CONST_FUNCTION) + dec->mFlags |= DTF_NO_PAGE_CROSS; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Variable not found"); + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Variable name expected"); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else if (!strcmp(mScanner->mTokenIdent->mString, "align")) { mScanner->NextToken(); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 625f201..52d7863 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -265,6 +265,8 @@ int main2(int argc, const char** argv) compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS; else if (arg[2] == 'o' && !arg[3]) compiler->mCompilerOptions |= COPT_OPTIMIZE_OUTLINE; + else if (arg[2] == 'x' && !arg[3]) + compiler->mCompilerOptions |= COPT_OPTIMIZE_PAGE_CROSSING; else compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg); }