diff --git a/README.md b/README.md index 8602d38..6b9573c 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ The compiler is command line driven, and creates an executable .prg file. * -d64 : create a d64 disk image * -f : add a binary file to the disk image * -fz : add a compressed binary file to the disk image +* -xz : extended zero page usage, more zero page space, but no return to basic A list of source files can be provided. diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 41af7bc..712e35d 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -49,6 +49,22 @@ void Compiler::AddDefine(const Ident* ident, const char* value) bool Compiler::ParseSource(void) { + if (mCompilerOptions & COPT_EXTENDED_ZERO_PAGE) + { + BC_REG_FPARAMS = 0x0d; + BC_REG_FPARAMS_END = 0x25; + + BC_REG_IP = 0x25; + BC_REG_ACCU = 0x27; + BC_REG_ADDR = 0x2b; + BC_REG_STACK = 0x2f; + BC_REG_LOCALS = 0x31; +#if 1 + BC_REG_TMP = 0x33; + BC_REG_TMP_SAVED = 0x53; +#endif + } + mPreprocessor->mCompilerOptions = mCompilerOptions; mLinker->mCompilerOptions = mCompilerOptions; @@ -220,6 +236,8 @@ bool Compiler::GenerateCode(void) regionMain->mSections.Push(mCompilationUnits->mSectionStack); } + mInterCodeModule->InitParamStack(mCompilationUnits->mSectionStack); + dcrtstart->mSection = sectionStartup; mGlobalAnalyzer->mCompilerOptions = mCompilerOptions; diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 94748a0..a293995 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -12,6 +12,8 @@ static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00000100; +static const uint64 COPT_EXTENDED_ZERO_PAGE = 0x00010000; + static const uint64 COPT_TARGET_PRG = 0x100000000ULL; static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL; static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL; diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 1896316..a8296b6 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -797,7 +797,7 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS); return buffer; } - else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 3) + else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 1) { sprintf_s(buffer, 10, "FP + %d", tmp - BC_REG_LOCALS); return buffer; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 6890c5a..5be7052 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -156,25 +156,52 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec) nbase = 1000; } - int nparams = 0; + int nparams = 0, npalign = 0; + int numfpzero = BC_REG_FPARAMS_END - BC_REG_FPARAMS; + int fplimit = numfpzero; + + if (!(procDec->mFlags & DTF_FUNC_INTRCALLED)) + fplimit += 256; if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT) + { + if (nbase < numfpzero && nbase + 2 > numfpzero) + nbase = numfpzero; nparams += 2; + } Declaration* dec = procDec->mBase->mParams; while (dec) { + // Check for paramter crossing boundary + if (nbase + nparams < numfpzero && nbase + nparams + dec->mBase->mSize > numfpzero) + { + npalign = numfpzero - (nbase + nparams); + nparams += npalign; + } nparams += dec->mBase->mSize; dec = dec->mNext; } - if (nbase + nparams <= BC_REG_FPARAMS_END - BC_REG_FPARAMS) + if (nbase + nparams <= fplimit) { procDec->mFastCallBase = nbase; procDec->mFastCallSize = nparams; procDec->mBase->mFastCallBase = nbase; procDec->mBase->mFastCallSize = nparams; + // Align fast call parameters to avoid crossing the zero page boundary + if (npalign) + { + Declaration* dec = procDec->mBase->mParams; + while (dec) + { + if (nbase + dec->mVarIndex + dec->mBase->mSize > numfpzero) + dec->mVarIndex += npalign; + dec = dec->mNext; + } + } + procDec->mBase->mFlags |= DTF_FASTCALL; #if 0 printf("FASTCALL %s\n", f->mIdent->mString); @@ -410,16 +437,39 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) return exp->mDecValue->mBase; case EX_CALL: ldec = Analyze(exp->mLeft, procDec); - RegisterCall(procDec, ldec); - if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT))) + if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue) { - procDec->mFlags &= ~DTF_FUNC_INTRSAVE; - if (procDec->mFlags & DTF_INTERRUPT) - mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent); + + } + else + { + RegisterCall(procDec, ldec); + if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT))) + { + procDec->mFlags &= ~DTF_FUNC_INTRSAVE; + if (procDec->mFlags & DTF_INTERRUPT) + mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent); + } } if (exp->mRight) + { + // Check for struct to struct forwarding + Expression* rex = exp->mRight; + while (rex) + { + Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + + if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT) + ldec->mBase->mFlags |= DTF_STACKCALL; + + if (rex->mType == EX_LIST) + rex = rex->mRight; + else + rex = nullptr; + } RegisterProc(Analyze(exp->mRight, procDec)); + } break; case EX_LIST: RegisterProc(Analyze(exp->mLeft, procDec)); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index e56cac4..598be1d 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -85,7 +85,7 @@ void IntegerValueRange::LimitMaxBound(int64 value) void IntegerValueRange::LimitMinWeak(int64 value) { - if (mMinState == S_UNBOUND || mMinValue < value) + if (mMinState == S_UNBOUND || mMinState != S_UNKNOWN && mMinValue < value) { mMinState = S_BOUND; mMinValue = value; @@ -95,7 +95,7 @@ void IntegerValueRange::LimitMinWeak(int64 value) void IntegerValueRange::LimitMaxWeak(int64 value) { - if (mMaxState == S_UNBOUND || mMaxValue > value) + if (mMaxState == S_UNBOUND || mMinState != S_UNKNOWN && mMaxValue > value) { mMaxState = S_BOUND; mMaxValue = value; @@ -6130,6 +6130,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray default: vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; } + #if 1 if (ins->mDst.mType == IT_INT8) { @@ -6600,6 +6601,11 @@ void InterCodeBasicBlock::RestartLocalIntegerRangeSets(int num, const GrowingVar mMemoryValueSize.SetSize(num, false); mEntryMemoryValueSize.SetSize(num, false); + mEntryParamValueRange.SetSize(paramVars.Size(), false); + mTrueParamValueRange.SetSize(paramVars.Size(), false); + mFalseParamValueRange.SetSize(paramVars.Size(), false); + mLocalParamValueRange.SetSize(paramVars.Size(), false); + for (int i = 0; i < mEntryValueRange.Size(); i++) { IntegerValueRange& vr(mEntryValueRange[i]); @@ -10080,7 +10086,7 @@ void ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars) iop.mMemory = IM_GLOBAL; iop.mLinkerObject = localVars[iop.mVarIndex]->mLinkerObject; iop.mVarIndex = localVars[iop.mVarIndex]->mIndex; - } + } } void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVariableArray& localVars) @@ -10095,7 +10101,7 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection); if (mInstructions[i]->mCode == IC_LOAD) - ApplyStaticStack(mInstructions[i]->mSrc[0], localVars); + ApplyStaticStack(mInstructions[i]->mSrc[0],localVars); else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA) ApplyStaticStack(mInstructions[i]->mSrc[1], localVars); else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER) @@ -10112,6 +10118,47 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa } } +void PromoteStaticStackParam(InterOperand& iop, LinkerObject* paramlobj) +{ + if (iop.mMemory == IM_FFRAME || iop.mMemory == IM_FPARAM) + { + if (iop.mVarIndex >= BC_REG_FPARAMS_END - BC_REG_FPARAMS) + { + int offset = iop.mVarIndex - (BC_REG_FPARAMS_END - BC_REG_FPARAMS); + iop.mMemory = IM_GLOBAL; + iop.mIntConst += offset; + iop.mLinkerObject = paramlobj; + paramlobj->EnsureSpace(iop.mIntConst, iop.mOperandSize); + } + } +} + +void InterCodeBasicBlock::PromoteStaticStackParams(LinkerObject* paramlobj) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + if (mInstructions[i]->mCode == IC_LOAD) + PromoteStaticStackParam(mInstructions[i]->mSrc[0], paramlobj); + else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA) + PromoteStaticStackParam(mInstructions[i]->mSrc[1], paramlobj); + else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER) + PromoteStaticStackParam(mInstructions[i]->mConst, paramlobj); + else if (mInstructions[i]->mCode == IC_COPY) + { + PromoteStaticStackParam(mInstructions[i]->mSrc[0], paramlobj); + PromoteStaticStackParam(mInstructions[i]->mSrc[1], paramlobj); + } + } + + if (mTrueJump) mTrueJump->PromoteStaticStackParams(paramlobj); + if (mFalseJump) mFalseJump->PromoteStaticStackParams(paramlobj); + } +} + bool InterCodeBasicBlock::DropUnreachable(void) { if (!mVisited) @@ -14333,6 +14380,7 @@ void InterCodeProcedure::Close(void) { mLinkerObject->mFlags |= LOBJF_STATIC_STACK; mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent->Mangle("@stack"), LST_STATIC_STACK); + mLinkerObject->mStackSection->mSections.Push(mModule->mParamLinkerSection); for (int i = 0; i < mLocalVars.Size(); i++) { @@ -14458,14 +14506,17 @@ void InterCodeProcedure::Close(void) MapCallerSavedTemps(); + ResetVisited(); + mEntryBlock->PromoteStaticStackParams(mModule->mParamLinkerObject); + if (mValueReturn) { ResetVisited(); mEntryBlock->CheckValueReturn(this); } - if (mSaveTempsLinkerObject && mTempSize > 16) - mSaveTempsLinkerObject->AddSpace(mTempSize - 16); + if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP) + mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP)); } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) @@ -14867,10 +14918,10 @@ void InterCodeProcedure::MapCallerSavedTemps(void) ResetVisited(); mEntryBlock->BuildCallerSaveTempSet(callerSaved); - int callerSavedTemps = 0, calleeSavedTemps = 16, freeCallerSavedTemps = 0, freeTemps = 0; + int callerSavedTemps = 0, calleeSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP, freeCallerSavedTemps = 0, freeTemps = 0; if (mCallsFunctionPointer) - freeCallerSavedTemps = 16; + freeCallerSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP; else { for (int i = 0; i < mCalledFunctions.Size(); i++) @@ -14939,8 +14990,8 @@ void InterCodeProcedure::MapCallerSavedTemps(void) printf("T%02d : %d, %d\n", i, mTempOffset[i], mTempSizes[i]); #endif - if (mSaveTempsLinkerObject && mTempSize > 16) - mSaveTempsLinkerObject->AddSpace(mTempSize - 16); + if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP) + mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP)); // printf("Map %s, %d, %d, %d, %d\n", mIdent->mString, freeTemps, callerSavedTemps, calleeSavedTemps, freeCallerSavedTemps); } @@ -15004,7 +15055,7 @@ void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) } InterCodeModule::InterCodeModule(Errors* errors, Linker * linker) - : mErrors(errors), mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0) + : mErrors(errors), mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0), mParamLinkerObject(nullptr), mParamLinkerSection(nullptr) { } @@ -15013,6 +15064,15 @@ InterCodeModule::~InterCodeModule(void) } + +void InterCodeModule::InitParamStack(LinkerSection* stackSection) +{ + mParamLinkerSection = mLinker->AddSection(Ident::Unique("sstack"), LST_STATIC_STACK); + stackSection->mSections.Push(mParamLinkerSection); + + mParamLinkerObject = mLinker->AddObject(Location(), Ident::Unique("sstack"), mParamLinkerSection, LOT_STACK); +} + bool InterCodeModule::Disassemble(const char* filename) { FILE* file; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index c56da96..57f159c 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -518,6 +518,7 @@ public: bool CheckStaticStack(void); void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars); + void PromoteStaticStackParams(LinkerObject* paramlobj); bool SameExitCode(const InterCodeBasicBlock* block) const; @@ -622,11 +623,15 @@ public: InterCodeModule(Errors* errors, Linker * linker); ~InterCodeModule(void); + void InitParamStack(LinkerSection * stackSection); + bool Disassemble(const char* name); GrowingInterCodeProcedurePtrArray mProcedures; GrowingVariableArray mGlobalVars; + LinkerObject * mParamLinkerObject; + LinkerSection * mParamLinkerSection; Linker * mLinker; Errors* mErrors; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 8cfcd6d..49b9a22 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -704,6 +704,186 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } } +InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) +{ + Declaration* dec; + ExValue vl, vr; + + Declaration* fdec = exp->mLeft->mDecValue; + Expression* fexp = fdec->mValue; + Declaration* ftype = fdec->mBase; + + InlineMapper nmapper; + nmapper.mReturn = new InterCodeBasicBlock(); + nmapper.mVarIndex = proc->mNumLocals; + nmapper.mConstExpr = inlineConstexpr; + proc->mNumLocals += fdec->mNumVars; + if (inlineMapper) + nmapper.mDepth = inlineMapper->mDepth + 1; + proc->Append(nmapper.mReturn); + + Declaration* pdec = ftype->mParams; + Expression* pex = exp->mRight; + while (pex) + { + int nindex = proc->mNumLocals++; + Declaration* vdec = new Declaration(pex->mLocation, DT_VARIABLE); + + InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mMemory = IM_LOCAL; + ains->mConst.mVarIndex = nindex; + + if (pdec) + { + nmapper.mParams[pdec->mVarIndex] = nindex; + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase; + if (pdec->mBase->mType == DT_TYPE_ARRAY) + ains->mConst.mOperandSize = 2; + else + ains->mConst.mOperandSize = pdec->mSize; + vdec->mSize = ains->mConst.mOperandSize; + vdec->mIdent = pdec->mIdent; + } + else + { + mErrors->Error(pex->mLocation, EERR_WRONG_PARAMETER, "Too many arguments for function call"); + } + + block->Append(ains); + + Expression* texp; + + if (pex->mType == EX_LIST) + { + texp = pex->mLeft; + pex = pex->mRight; + } + else + { + texp = pex; + pex = nullptr; + } + + ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); + + vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp); + + if (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION) + { + if (pdec && !pdec->mBase->CanAssign(vr.mType)) + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + + vr = Dereference(proc, texp, block, vr, 1); + + if (vr.mReference != 1) + mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an adressable expression"); + + if (vp.mTemp != vr.mTemp) + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = vr.mType->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = ains->mDst.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + cins->mSrc[1].mOperandSize = vr.mType->mSize; + + cins->mConst.mOperandSize = vr.mType->mSize; + block->Append(cins); + } + } + else + { + if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) + vr = Dereference(proc, texp, block, vr, 1); + else + vr = Dereference(proc, texp, block, vr); + + if (pdec) + { + if (!pdec->mBase->CanAssign(vr.mType)) + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + vr = CoerceType(proc, texp, block, vr, pdec->mBase); + } + else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2) + { + vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration); + } + + InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE); + wins->mSrc[1].mMemory = IM_INDIRECT; + wins->mSrc[0].mType = InterTypeOf(vr.mType);; + wins->mSrc[0].mTemp = vr.mTemp; + wins->mSrc[1].mType = IT_POINTER; + wins->mSrc[1].mTemp = ains->mDst.mTemp; + if (pdec) + { + if (pdec->mBase->mType == DT_TYPE_ARRAY) + wins->mSrc[1].mOperandSize = 2; + else + wins->mSrc[1].mOperandSize = pdec->mSize; + } + else if (vr.mType->mSize > 2 && vr.mType->mType != DT_TYPE_ARRAY) + wins->mSrc[1].mOperandSize = vr.mType->mSize; + else + wins->mSrc[1].mOperandSize = 2; + block->Append(wins); + } + + if (pdec) + pdec = pdec->mNext; + } + + if (pdec) + mErrors->Error(exp->mLocation, EERR_WRONG_PARAMETER, "Not enough arguments for function call"); + + Declaration* rdec = nullptr; + if (ftype->mBase->mType != DT_TYPE_VOID) + { + int nindex = proc->mNumLocals++; + nmapper.mResult = nindex; + + rdec = new Declaration(ftype->mLocation, DT_VARIABLE); + rdec->mVarIndex = nindex; + rdec->mBase = ftype->mBase; + rdec->mSize = rdec->mBase->mSize; + } + + vl = TranslateExpression(ftype, proc, block, fexp, nullptr, nullptr, &nmapper); + + InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + block->Append(jins); + + block->Close(nmapper.mReturn, nullptr); + block = nmapper.mReturn; + + if (rdec) + { + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + ins->mDst.mType = IT_POINTER; + ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mOperandSize = rdec->mSize; + ins->mConst.mIntConst = rdec->mOffset; + ins->mConst.mVarIndex = rdec->mVarIndex; + ins->mConst.mMemory = IM_LOCAL; + + block->Append(ins); + + return ExValue(rdec->mBase, ins->mDst.mTemp, 1); + } + else + return ExValue(TheVoidTypeDeclaration); +} + InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) { Declaration* dec; @@ -2048,179 +2228,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (doInline) { - Declaration* fdec = exp->mLeft->mDecValue; - Expression* fexp = fdec->mValue; - Declaration* ftype = fdec->mBase; - - InlineMapper nmapper; - nmapper.mReturn = new InterCodeBasicBlock(); - nmapper.mVarIndex = proc->mNumLocals; - nmapper.mConstExpr = inlineConstexpr; - proc->mNumLocals += fdec->mNumVars; - if (inlineMapper) - nmapper.mDepth = inlineMapper->mDepth + 1; - proc->Append(nmapper.mReturn); - - Declaration* pdec = ftype->mParams; - Expression* pex = exp->mRight; - while (pex) - { - int nindex = proc->mNumLocals++; - Declaration* vdec = new Declaration(pex->mLocation, DT_VARIABLE); - - InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT); - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); - ains->mConst.mMemory = IM_LOCAL; - ains->mConst.mVarIndex = nindex; - - if (pdec) - { - nmapper.mParams[pdec->mVarIndex] = nindex; - - vdec->mVarIndex = nindex; - vdec->mBase = pdec->mBase; - if (pdec->mBase->mType == DT_TYPE_ARRAY) - ains->mConst.mOperandSize = 2; - else - ains->mConst.mOperandSize = pdec->mSize; - vdec->mSize = ains->mConst.mOperandSize; - vdec->mIdent = pdec->mIdent; - } - else - { - mErrors->Error(pex->mLocation, EERR_WRONG_PARAMETER, "Too many arguments for function call"); - } - - block->Append(ains); - - Expression* texp; - - if (pex->mType == EX_LIST) - { - texp = pex->mLeft; - pex = pex->mRight; - } - else - { - texp = pex; - pex = nullptr; - } - - ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - - vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp); - - if (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION) - { - if (pdec && !pdec->mBase->CanAssign(vr.mType)) - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - - vr = Dereference(proc, texp, block, vr, 1); - - if (vr.mReference != 1) - mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an adressable expression"); - - if (vp.mTemp != vr.mTemp) - { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = vr.mType->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; - - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = ains->mDst.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; - cins->mSrc[1].mOperandSize = vr.mType->mSize; - - cins->mConst.mOperandSize = vr.mType->mSize; - block->Append(cins); - } - } - else - { - if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) - vr = Dereference(proc, texp, block, vr, 1); - else - vr = Dereference(proc, texp, block, vr); - - if (pdec) - { - if (!pdec->mBase->CanAssign(vr.mType)) - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, texp, block, vr, pdec->mBase); - } - else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2) - { - vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration); - } - - InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE); - wins->mSrc[1].mMemory = IM_INDIRECT; - wins->mSrc[0].mType = InterTypeOf(vr.mType);; - wins->mSrc[0].mTemp = vr.mTemp; - wins->mSrc[1].mType = IT_POINTER; - wins->mSrc[1].mTemp = ains->mDst.mTemp; - if (pdec) - { - if (pdec->mBase->mType == DT_TYPE_ARRAY) - wins->mSrc[1].mOperandSize = 2; - else - wins->mSrc[1].mOperandSize = pdec->mSize; - } - else if (vr.mType->mSize > 2 && vr.mType->mType != DT_TYPE_ARRAY) - wins->mSrc[1].mOperandSize = vr.mType->mSize; - else - wins->mSrc[1].mOperandSize = 2; - block->Append(wins); - } - - if (pdec) - pdec = pdec->mNext; - } - - if (pdec) - mErrors->Error(exp->mLocation, EERR_WRONG_PARAMETER, "Not enough arguments for function call"); - - Declaration* rdec = nullptr; - if (ftype->mBase->mType != DT_TYPE_VOID) - { - int nindex = proc->mNumLocals++; - nmapper.mResult = nindex; - - rdec = new Declaration(ftype->mLocation, DT_VARIABLE); - rdec->mVarIndex = nindex; - rdec->mBase = ftype->mBase; - rdec->mSize = rdec->mBase->mSize; - } - - vl = TranslateExpression(ftype, proc, block, fexp, nullptr, nullptr, &nmapper); - - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); - block->Append(jins); - - block->Close(nmapper.mReturn, nullptr); - block = nmapper.mReturn; - - if (rdec) - { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); - ins->mDst.mType = IT_POINTER; - ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); - ins->mConst.mOperandSize = rdec->mSize; - ins->mConst.mIntConst = rdec->mOffset; - ins->mConst.mVarIndex = rdec->mVarIndex; - ins->mConst.mMemory = IM_LOCAL; - - block->Append(ins); - - return ExValue(rdec->mBase, ins->mDst.mTemp, 1); - } - else - return ExValue(TheVoidTypeDeclaration); + return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr); } else { diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 29ed04d..614d9d5 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -58,6 +58,7 @@ protected: ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, InlineMapper* inlineMapper); + ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); }; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index d1ef60e..9738a23 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -71,6 +71,12 @@ void LinkerObject::AddData(const uint8* data, int size) memcpy(mData, data, size); } +void LinkerObject::EnsureSpace(int offset, int size) +{ + if (offset + size > mSize) + AddSpace(offset + size); +} + uint8* LinkerObject::AddSpace(int size) { if (mSize != size) diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 53b9425..f831772 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -174,6 +174,7 @@ public: void AddData(const uint8* data, int size); uint8* AddSpace(int size); + void EnsureSpace(int offset, int size); GrowingArray mReferences; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 7e5d662..2449f46 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -13750,6 +13750,83 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) for (int i = 0; i < mIns.Size(); i++) { +#if 1 + if (i + 6 < mIns.Size()) + { + if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED && + mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x00 && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff && + mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0xff && + mIns[i + 5].mType == ASMIT_ASL && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 0].mAddress && + mIns[i + 6].mType == ASMIT_ROL && mIns[i + 6].mMode == ASMIM_IMPLIED) + { + changed = true; + + NativeCodeBasicBlock* eblock = proc->AllocateBlock(); + NativeCodeBasicBlock* neblock = proc->AllocateBlock(); + NativeCodeBasicBlock* rblock = proc->AllocateBlock(); + + rblock->mTrueJump = mTrueJump; + rblock->mFalseJump = mFalseJump; + rblock->mBranch = mBranch; + + for (int j = i + 7; j < mIns.Size(); j++) + rblock->mIns.Push(mIns[j]); + mIns.SetSize(i + 1); + mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns[i + 0].mType = ASMIT_ASL; + + mTrueJump = neblock; + mFalseJump = eblock; + mBranch = ASMIT_BCS; + + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff)); + + eblock->Close(rblock, nullptr, ASMIT_JMP); + neblock->Close(rblock, nullptr, ASMIT_JMP); + break; + } + + if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED && + mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x00 && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff && + mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0xff && + mIns[i + 5].mType == ASMIT_ASL && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 0].mAddress && + mIns[i + 6].mType == ASMIT_ROL && mIns[i + 6].mMode == ASMIM_IMPLIED) + { + changed = true; + + NativeCodeBasicBlock* eblock = proc->AllocateBlock(); + NativeCodeBasicBlock* neblock = proc->AllocateBlock(); + NativeCodeBasicBlock* rblock = proc->AllocateBlock(); + + rblock->mTrueJump = mTrueJump; + rblock->mFalseJump = mFalseJump; + rblock->mBranch = mBranch; + + for (int j = i + 7; j < mIns.Size(); j++) + rblock->mIns.Push(mIns[j]); + mIns.SetSize(i + 1); + mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_ASL)); + + mTrueJump = neblock; + mFalseJump = eblock; + mBranch = ASMIT_BCS; + + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff)); + + eblock->Close(rblock, nullptr, ASMIT_JMP); + neblock->Close(rblock, nullptr, ASMIT_JMP); + break; + } + } +#endif + #if 1 if (i + 6 < mIns.Size()) { @@ -16415,6 +16492,27 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool } } #endif +#if 1 + if (mIns.Size() >= 1 && mIns[0].mType == ASMIT_TAY && !(mIns[0].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mEntryRegA) + { + int i = 0; + while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mIns.Size() > 0 && mEntryBlocks[i]->mIns.Last().mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mEntryBlocks[i]->mIns.Last().mMode) && !mEntryBlocks[i]->mFalseJump) + i++; + if (i == mEntryBlocks.Size()) + { + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + NativeCodeBasicBlock* b = mEntryBlocks[i]; + int sz = b->mIns.Size(); + b->mIns[sz - 1].mType = ASMIT_LDY; + b->mIns[sz - 1].mLive |= LIVE_CPU_REG_Y; + changed = true; + } + + mIns[0].mType = ASMIT_NOP; mIns[0].mMode = ASMIM_IMPLIED; + } + } +#endif #if 1 if (mIns.Size() >= 1 && mIns[0].mMode == ASMIM_ABSOLUTE_X && !(mIns[0].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z))) { @@ -21860,13 +21958,24 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo #endif // Check load and commutative with current accu value #if 1 - if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress) + if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && + mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress) { mIns[i].mType = mIns[i + 1].mType; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; changed = true; } #endif +#if 1 + if (i + 2 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].IsCommutative() && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 2].mAddress) + { + mIns[i + 2].CopyMode(mIns[i + 0]); + mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + changed = true; + } +#endif + if (mIns[i].ValueForwarding(mNDataSet, carryop, !global, final)) changed = true; if (carryop != ASMIT_NOP) @@ -31860,7 +31969,7 @@ void NativeCodeProcedure::CompressTemporaries(void) else mInterProc->mTempSize = tpos - BC_REG_TMP; - if (mNoFrame && !used[BC_REG_STACK] && mInterProc->mTempSize <= 16) + if (mNoFrame && !used[BC_REG_STACK] && mInterProc->mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP) mStackExpand = 0; } } @@ -31924,7 +32033,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mIndex = proc->mID; - int tempSave = proc->mTempSize > 16 && !proc->mSaveTempsLinkerObject && !mInterProc->mInterrupt ? proc->mTempSize - 16 : 0; + int tempSave = proc->mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP && !proc->mSaveTempsLinkerObject && !mInterProc->mInterrupt ? proc->mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP) : 0; int commonFrameSize = proc->mCommonFrameSize; mStackExpand = tempSave + proc->mLocalSize; @@ -32007,7 +32116,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) int frameSpace = tempSave; - tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0; + tempSave = proc->mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP ? proc->mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP) : 0; if (!(mGenerator->mCompilerOptions & COPT_NATIVE)) mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea)); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 88e4589..597c6c1 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.13.178"); + strcpy(strProductVersion, "1.14.179"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); @@ -206,6 +206,10 @@ int main2(int argc, const char** argv) if (arg[2] == '2') compiler->mCompilerOptions |= COPT_VERBOSE2; } + else if (arg[1] == 'x' && arg[2] == 'z') + { + compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE; + } else compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg); } diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 5992d45..d5b0d83 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,13,178,0 - PRODUCTVERSION 1,13,178,0 + FILEVERSION 1,14,179,0 + PRODUCTVERSION 1,14,179,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.13.178.0" + VALUE "FileVersion", "1.14.179.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.13.178.0" + VALUE "ProductVersion", "1.14.179.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index aed1fb5..9ce372e 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -4450,15 +4450,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{9F4E2BAD-97D8-4D1A-981F-D6B719A704C0}" - "PackageCode" = "8:{9749B605-800D-406D-A8C7-759AA28CA93D}" + "ProductCode" = "8:{28347196-C1B9-4B31-9AAB-50EC7E4BFC8E}" + "PackageCode" = "8:{F19F2B8B-8649-4939-B1FA-8EF0A6862DD7}" "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.13.178" + "ProductVersion" = "8:1.14.179" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" diff --git a/samples/games/missile.c b/samples/games/missile.c index b28b617..07d2c81 100644 --- a/samples/games/missile.c +++ b/samples/games/missile.c @@ -548,6 +548,7 @@ void screen_clear(void) __interrupt void joy_interrupt() { +// vic.color_border++; // Poll joystick joy_poll(0); @@ -580,6 +581,7 @@ __interrupt void joy_interrupt() } else if (CrossDelay > 0) CrossDelay--; +// vic.color_border--; } enum GameState @@ -843,7 +845,7 @@ int main(void) rirq_write(&bottom, 0, &vic.memptr, 0x27); rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3); rirq_call(&bottom, 2, joy_interrupt); - rirq_set(1, 250, &bottom); + rirq_set(1, 252, &bottom); // sort the raster IRQs rirq_sort();