diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d706537..40a7197 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -13419,13 +13419,18 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mExpensive = true; break; case IC_LEA: + { + int offset = 0; + if (ins->mSrc[0].mTemp < 0) + offset = ins->mSrc[0].mIntConst; + if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[1].mTemp >= 0) ins->mExpensive = true; else if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[0].mRange.mMaxValue >= 256) ins->mExpensive = true; - else if (nins && nins->mCode == IC_LEA && nins->mSrc[0].mTemp >= 0 && (nins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_UNBOUND || nins->mSrc[0].mRange.mMaxValue >= 255)) + else if (nins && nins->mCode == IC_LEA && nins->mSrc[0].mTemp >= 0 && (nins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_UNBOUND || nins->mSrc[0].mRange.mMaxValue + offset >= 255)) ins->mExpensive = true; - break; + } break; case IC_LOAD: case IC_STORE: ins->mExpensive = true; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index a70ed93..1ce3d0f 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12138,9 +12138,18 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const else { NativeCodeInstruction ainsl(ins, iop, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ireg]); - NativeCodeInstruction ainsh(ins, iop, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ireg] + 1); + if (ins->mSrc[0].IsUByte()) + { + NativeCodeInstruction ainsh(ins, iop, ASMIM_IMMEDIATE, 0); - LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], &ainsl, &ainsh); + LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], &ainsl, &ainsh); + } + else + { + NativeCodeInstruction ainsh(ins, iop, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ireg] + 1); + + LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], &ainsl, &ainsh); + } } } } @@ -20063,6 +20072,153 @@ bool NativeCodeBasicBlock::IsExitARegZP(int addr, int& index) const return false; } +bool NativeCodeBasicBlock::CanJoinEntryLoadStoreZP(int saddr, int daddr) +{ + int at = mIns.Size() - 1; + while (at >= 0) + { + NativeCodeInstruction & ins = mIns[at]; + if (ins.ReferencesZeroPage(daddr)) + return false; + if (ins.ChangesZeroPage(saddr)) + { + if (ins.mType == ASMIT_STA || ins.mType == ASMIT_STX || ins.mType == ASMIT_STY) + return true; + else + return false; + } + at--; + } + + return false; +} + +bool NativeCodeBasicBlock::DoJoinEntryLoadStoreZP(int saddr, int daddr) +{ + int at = mIns.Size() - 1; + while (at >= 0) + { + NativeCodeInstruction& ins = mIns[at]; + if (ins.ChangesZeroPage(saddr)) + { + if (ins.mType == ASMIT_STA) + { + ins.mLive |= LIVE_CPU_REG_A; + mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STA, ASMIM_ZERO_PAGE, daddr)); + return true; + } + else if (ins.mType == ASMIT_STX) + { + ins.mLive |= LIVE_CPU_REG_X; + mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STX, ASMIM_ZERO_PAGE, daddr)); + return true; + } + else if (ins.mType == ASMIT_STY) + { + ins.mLive |= LIVE_CPU_REG_Y; + mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STY, ASMIM_ZERO_PAGE, daddr)); + return true; + } + } + at--; + } + + return false; +} + +bool NativeCodeBasicBlock::JoinEntryLoadStoreZP(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + CheckLive(); + + for (int i = 0; i + 1 < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) || + mIns[i].mType == ASMIT_LDX && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STX && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z))) + { + int saddr = mIns[i].mAddress, daddr = mIns[i + 1].mAddress; + if (!ReferencesZeroPage(saddr, 0, i) && !ReferencesZeroPage(daddr, 0, i)) + { + int n = 0; + for (int j = 0; j < mEntryBlocks.Size(); j++) + { + if (mEntryBlocks[j]->CanJoinEntryLoadStoreZP(saddr, daddr)) + n++; + } + + if (n == mEntryBlocks.Size()) + { + for (int j = 0; j < mEntryBlocks.Size(); j++) + { + mEntryBlocks[j]->DoJoinEntryLoadStoreZP(saddr, daddr); + mEntryBlocks[j]->mExitRequiredRegs += daddr; + } + mEntryRequiredRegs += daddr; + changed = true; + mIns.Remove(i, 2); + i--; + } + else if (n >= 2) + { + NativeCodeBasicBlock* xblock = mProc->AllocateBlock(); + + int j = 0; + while (j < mEntryBlocks.Size()) + { + NativeCodeBasicBlock* eb = mEntryBlocks[j]; + + if (eb->CanJoinEntryLoadStoreZP(saddr, daddr)) + { + eb->DoJoinEntryLoadStoreZP(saddr, daddr); + eb->mExitRequiredRegs += daddr; + j++; + } + else + { + if (eb->mTrueJump == this) + eb->mTrueJump = xblock; + if (eb->mFalseJump == this) + eb->mFalseJump = xblock; + mEntryBlocks.Remove(i); + xblock->mEntryBlocks.Push(eb); + xblock->mNumEntries++; + } + } + + xblock->mEntryRequiredRegs = mEntryRequiredRegs; + xblock->mExitRequiredRegs = mEntryRequiredRegs; + xblock->mExitRequiredRegs += daddr; + + xblock->mIns.Push(mIns[i + 0]); + xblock->mIns.Push(mIns[i + 1]); + + xblock->Close(mIns[i].mIns, this, nullptr, ASMIT_JMP); + mEntryBlocks.Push(xblock); + mNumEntries++; + + mEntryRequiredRegs += daddr; + changed = true; + mIns.Remove(i, 2); + i--; + } + } + } + } + + if (mTrueJump && mTrueJump->JoinEntryLoadStoreZP()) + changed = true; + if (mFalseJump && mFalseJump->JoinEntryLoadStoreZP()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops) { @@ -25944,6 +26100,9 @@ bool NativeCodeBasicBlock::MoveLoadIndirectTempStoreUp(int at) mIns[j - 0].mAddress == mIns[at + 1].mAddress + 1 && mIns[j - 1].mAddress == mIns[j - 3].mAddress + 1) { + for (int k = j + 1; k < at; k++) + mIns[k].mLive |= mIns[at + 2].mLive & LIVE_CPU_REG_Y; + mIns[at + 0].mLive |= mIns[j].mLive; mIns[at + 1].mLive |= mIns[j].mLive; mIns[at + 2].mLive |= mIns[j].mLive; @@ -25985,6 +26144,9 @@ bool NativeCodeBasicBlock::MoveLoadIndirectTempStoreUp(int at) return false; } + for (int k = j + 1; k < at; k++) + mIns[k].mLive |= mIns[at + 2].mLive & LIVE_CPU_REG_Y; + mIns[at + 0].mLive |= mIns[j].mLive; mIns[at + 1].mLive |= mIns[j].mLive; mIns[at + 2].mLive |= mIns[j].mLive; @@ -42373,7 +42535,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "A::draw"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -43308,6 +43470,13 @@ void NativeCodeProcedure::Optimize(void) changed = true; } + + if (step > 6) + { + ResetVisited(); + if (mEntryBlock->JoinEntryLoadStoreZP()) + changed = true; + } #endif #if _DEBUG diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 6188094..f2274a7 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -515,6 +515,10 @@ public: bool HasTailSTX(int& addr, int& index) const; bool HasTailSTY(int& addr, int& index) const; + bool CanJoinEntryLoadStoreZP(int saddr, int daddr); + bool DoJoinEntryLoadStoreZP(int saddr, int daddr); + bool JoinEntryLoadStoreZP(void); + bool IsExitYRegZP(int addr, int& index) const; bool IsExitXRegZP(int addr, int& index) const; bool IsExitARegZP(int addr, int& index) const; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8d02b4f..020e582 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -855,7 +855,16 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl dec->mSize = 1; dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + bool classTemplate = false; + mScanner->NextToken(); + + if (mCompilerOptions & COPT_CPLUSPLUS) + { + if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_STRUCT)) + classTemplate = true; + } + if (mScanner->mToken == TK_IDENT) { dec->mIdent = mScanner->mTokenIdent; @@ -870,6 +879,21 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl mScanner->NextToken(); } + if (mCompilerOptions & COPT_CPLUSPLUS) + { + if (ConsumeTokenIf(TK_COLON)) + { + Declaration* pdec = ParseBaseTypeDeclaration(0, false); + if (pdec->mType == DT_TYPE_INTEGER) + { + dec->mSize = pdec->mSize; + dec->mFlags |= pdec->mFlags & DTF_SIGNED; + } + else + mErrors->Error(pdec->mLocation, EERR_INCOMPATIBLE_TYPES, "Integer base type expected"); + } + } + int nitem = 0; if (mScanner->mToken == TK_OPEN_BRACE) { @@ -887,7 +911,12 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl { cdec->mIdent = mScanner->mTokenIdent; cdec->mQualIdent = mScope->Mangle(cdec->mIdent); - Declaration* odec = mScope->Insert(cdec->mIdent, cdec); + Declaration* odec; + if (classTemplate) + odec = dec->mScope->Insert(cdec->mIdent, cdec); + else + odec = mScope->Insert(cdec->mIdent, cdec); + if (odec) { mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate declaration", mScanner->mTokenIdent->mString); @@ -3684,12 +3713,30 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { - mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace"); + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a namespace"); mErrors->Error(dec->mLocation, EINFO_ORIGINAL_DEFINITION, "Original definition"); } } - return dec; + return nullptr; + } + else if (ConsumeTokenIf(TK_ENUM)) + { + Declaration* dec = ParseQualIdent(); + if (dec) + { + if (dec->mType == DT_TYPE_ENUM) + { + mScope->UseScope(dec->mScope); + } + else + { + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not an enum"); + mErrors->Error(dec->mLocation, EINFO_ORIGINAL_DEFINITION, "Original definition"); + } + } + + return nullptr; } else { @@ -4818,7 +4865,7 @@ Declaration* Parser::ParseQualIdent(void) { if (mScanner->mToken == TK_IDENT) { - if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) + if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_ENUM) { Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING); @@ -5189,6 +5236,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp = ParseDeclarationExpression(nullptr); break; + case TK_USING: + ParseDeclaration(nullptr, true, true); + break; + case TK_CHARACTER: dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec->mInteger = mCharMap[(unsigned char)mScanner->mTokenInteger]; @@ -5445,7 +5496,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) { if (mScanner->mToken == TK_IDENT) { - if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) + if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_ENUM) { Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING);