From bcc59a9afb72e845e8d2aa58d081c8917d666c92 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 2 Jul 2022 14:53:00 +0200 Subject: [PATCH] Add intermediat code select operator --- README.md | 15 ++ oscar64/Errors.h | 1 + oscar64/InterCode.cpp | 288 +++++++++++++++++++++++++++---- oscar64/InterCode.h | 4 + oscar64/InterCodeGenerator.cpp | 270 +++++++++++++++++++---------- oscar64/NativeCodeGenerator.cpp | 69 +++++++- oscar64/Parser.cpp | 8 +- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 6 +- samples/scrolling/bigfont.c | 2 +- 11 files changed, 538 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index 78b127e..999d1b7 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,21 @@ The character map for string and char constants can be changed with a pragma to The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion. +### Loop unrolling + +Loop unrolling on 6502 is hard to decide for the compiler. Memory is usually scarce, so it only does it in realy obvious cases (and in less obbious cases for O3). On the other hand unrolling is required to get good performance in e.g. scrolling code. Therefore the compiler offers an unrolling pragma, that can be used to specifiy the amount of unrolling either as a number or "full" for complete. + +The following code scrolls the screen to the left, and completely unrolls the inner vertical loop. + + + for(char x=0; x<39; x++) + { + #pragma unroll(full) + for(char y=0; y<25; y++) + screen[y][x] = screen[y][x + 1]; + } + + ### Marking functions as native Routines can be marked to be compiled to 6502 machine code with the native pragma: diff --git a/oscar64/Errors.h b/oscar64/Errors.h index f8fb96f..60d8517 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -23,6 +23,7 @@ enum ErrorID EWARN_NOT_INTERRUPT_SAFE, EWARN_BOOL_SHORTCUT, EWARN_OPTIMIZER_LOCKED, + EWARN_LOOP_UNROLL_IGNORED, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 670eb6a..a3750cb 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -2787,6 +2787,7 @@ bool InterInstruction::RemoveUnusedResultInstructions(InterInstruction* pre, Num { // previous instruction produced result, but it is not needed here pre->mDst.mTemp = mDst.mTemp; + pre->mSingleAssignment = mSingleAssignment; mCode = IC_NONE; mDst.mTemp = -1; @@ -3513,6 +3514,9 @@ void InterInstruction::Disassemble(FILE* file) case IC_TYPECAST: fprintf(file, "CAST"); break; + case IC_SELECT: + fprintf(file, "SELECT"); + break; case IC_CONSTANT: fprintf(file, "CONST"); break; @@ -4100,6 +4104,16 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI } break; + case IC_SELECT: + for(int i=0; i<3; i++) + { + if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT) + { + ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst; + ins->mSrc[i].mTemp = -1; + } + } + break; case IC_RETURN_VALUE: if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT) { @@ -5238,6 +5252,10 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray case IC_LOAD_TEMPORARY: vr = ins->mSrc[0].mRange; break; + case IC_SELECT: + vr = ins->mSrc[1].mRange; + vr.Merge(ins->mSrc[0].mRange, false, false); + break; case IC_UNARY_OPERATOR: { switch (ins->mOperator) @@ -6911,7 +6929,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra mInstructions[j] = ins; } } - +#if 1 for (int i = 0; i < mInstructions.Size(); i++) { InterInstruction* ins = mInstructions[i]; @@ -6943,7 +6961,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra } } - if (bins != lins && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst < 252) + if (bins != lins && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst < 252 && ins->mSrc[pi].mIntConst + lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst >= 0) { ins->mSrc[pi].mTemp = bins->mDst.mTemp; ins->mSrc[pi].mIntConst += lins->mSrc[1].mIntConst - bins->mSrc[1].mIntConst; @@ -6969,6 +6987,7 @@ bool InterCodeBasicBlock::MergeIndexedLoadStore(const GrowingInstructionPtrArra ltvalue[dtemp] = ins; } } +#endif if (mTrueJump && mTrueJump->MergeIndexedLoadStore(ltvalue)) changed = true; @@ -7238,7 +7257,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra { InterInstruction* pins = ltvalue[ins->mSrc[1].mTemp]; - if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0) + if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0 && ins->mSrc[1].mIntConst + pins->mSrc[0].mIntConst >= 0) { ins->mSrc[1].Forward(pins->mSrc[1]); pins->mSrc[1].mFinal = false; @@ -7254,7 +7273,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra { InterInstruction* pins = ltvalue[ins->mSrc[0].mTemp]; - if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0) + if (pins->mCode == IC_LEA && pins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst + pins->mSrc[0].mIntConst >= 0) { ins->mSrc[0].Forward(pins->mSrc[1]); pins->mSrc[1].mFinal = false; @@ -8426,6 +8445,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void) { if (tblock->mNumEntries == 1 && fblock->mNumEntries == 2) { + if (tblock->mInstructions.Size() == 2 && tblock->mInstructions[0]->mCode == IC_LEA && tblock->mInstructions[0]->mSrc[0].mTemp < 0 && tblock->mInstructions[0]->mSrc[1].mTemp >= 0) + { + InterInstruction* lins = tblock->mInstructions[0]; + + // Single "lea temp, imm" in diamond + int i = mInstructions.Size(); + while (i > 0 && mInstructions[i - 1]->mDst.mTemp != lins->mSrc[1].mTemp) + i--; + + if (i > 0) + { + i--; + InterInstruction* tins = mInstructions[i]; + + if (mInstructions[i]->mCode == IC_LOAD_TEMPORARY) + { + int offset = 0; + bool fail = false; + for (int j = i + 1; j < mInstructions.Size(); j++) + { + if (mInstructions[j]->mDst.mTemp == tins->mSrc[0].mTemp) + { + if (mInstructions[j]->mCode == IC_LEA && mInstructions[j]->mSrc[1].mTemp == tins->mSrc[0].mTemp && mInstructions[j]->mSrc[0].mTemp < 0) + { + offset += mInstructions[j]->mSrc[0].mIntConst; + } + else + fail = true; + } + } + + if (!fail) + { + mExitRequiredTemps += tins->mSrc[0].mTemp; + tblock->mEntryRequiredTemps += tins->mSrc[0].mTemp; + + lins->mSrc[1].mTemp = tins->mSrc[0].mTemp; + lins->mSrc[0].mIntConst -= offset; + changed = true; + } + } + + } + } + for (int i = mInstructions.Size() - 1; i >= 0; i--) { InterInstruction* mins = mInstructions[i]; @@ -8792,6 +8856,91 @@ bool InterCodeBasicBlock::IsLeafProcedure(void) } +void InterCodeBasicBlock::ExpandSelect(InterCodeProcedure* proc) +{ + if (!mVisited) + { + mVisited = true; + + int i = 0; + while (i < mInstructions.Size() && mInstructions[i]->mCode != IC_SELECT) + i++; + + if (i < mInstructions.Size()) + { + InterInstruction* sins = mInstructions[i]; + + InterCodeBasicBlock* tblock = new InterCodeBasicBlock(); + proc->Append(tblock); + InterCodeBasicBlock* fblock = new InterCodeBasicBlock(); + proc->Append(fblock); + InterCodeBasicBlock* eblock = new InterCodeBasicBlock(); + proc->Append(eblock); + + for (int j = i + 1; j < mInstructions.Size(); j++) + eblock->mInstructions.Push(mInstructions[j]); + eblock->Close(mTrueJump, mFalseJump); + + mInstructions.SetSize(i); + + InterInstruction* bins = new InterInstruction(); + bins->mCode = IC_BRANCH; + bins->mSrc[0] = sins->mSrc[2]; + mInstructions.Push(bins); + + InterInstruction* tins = new InterInstruction(); + if (sins->mSrc[1].mTemp < 0) + { + tins->mCode = IC_CONSTANT; + tins->mConst = sins->mSrc[1]; + } + else + { + tins->mCode = IC_LOAD_TEMPORARY; + tins->mSrc[0] = sins->mSrc[1]; + } + + tins->mDst = sins->mDst; + + InterInstruction* fins = new InterInstruction(); + if (sins->mSrc[0].mTemp < 0) + { + fins->mCode = IC_CONSTANT; + fins->mConst = sins->mSrc[0]; + } + else + { + fins->mCode = IC_LOAD_TEMPORARY; + fins->mSrc[0] = sins->mSrc[0]; + } + + fins->mDst = sins->mDst; + + tblock->mInstructions.Push(tins); + InterInstruction* jins = new InterInstruction(); + jins->mCode = IC_JUMP; + tblock->mInstructions.Push(jins); + + tblock->Close(eblock, nullptr); + + fblock->mInstructions.Push(fins); + jins = new InterInstruction(); + jins->mCode = IC_JUMP; + fblock->mInstructions.Push(jins); + + fblock->Close(eblock, nullptr); + + mTrueJump = tblock; + mFalseJump = fblock; + } + + if (mTrueJump) + mTrueJump->ExpandSelect(proc); + if (mFalseJump) + mFalseJump->ExpandSelect(proc); + } +} + void InterCodeBasicBlock::SplitBranches(InterCodeProcedure* proc) { if (!mVisited) @@ -9893,6 +10042,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa } while (changed); GrowingArray indexins(nullptr); + GrowingArray pindexins(nullptr); int j = 0; for (int i = 0; i < mInstructions.Size(); i++) @@ -10028,35 +10178,60 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa } else if (ins->mCode == IC_LEA && (ins->mSrc[1].mTemp < 0 || dep[ins->mSrc[1].mTemp] == DEP_UNKNOWN || dep[ins->mSrc[1].mTemp] == DEP_DEFINED) && dep[ins->mSrc[0].mTemp] == DEP_INDEX_DERIVED) { - indexStep[ins->mDst.mTemp] = indexStep[ins->mSrc[0].mTemp]; - indexBase[ins->mDst.mTemp] = 0; +#if 1 + int k = 0; + while (k < pindexins.Size() && !( + ins->mSrc[0].mTemp == pindexins[k]->mSrc[0].mTemp && + ins->mSrc[1].mTemp == pindexins[k]->mSrc[1].mTemp && + ins->mSrc[1].mMemory == pindexins[k]->mSrc[1].mMemory && + ins->mSrc[1].mVarIndex == pindexins[k]->mSrc[1].mVarIndex)) + k++; - mLoopPrefix->mInstructions.Insert(mLoopPrefix->mInstructions.Size() - 1, ins); - - InterInstruction* ains = new InterInstruction(); - ains->mCode = IC_LEA; - ains->mDst = ins->mDst; - ains->mSrc[1] = ins->mDst; - ains->mSrc[1].mMemory = IM_INDIRECT; - ains->mSrc[1].mIntConst = 0; - ains->mSrc[0].mType = IT_INT16; - ains->mSrc[0].mTemp = -1; - ains->mSrc[0].mIntConst = indexStep[ins->mSrc[0].mTemp]; - - if (tailBlock->mEntryRequiredTemps[ains->mDst.mTemp]) + if (k < pindexins.Size() && ins->mSrc[1].mIntConst >= pindexins[k]->mSrc[1].mIntConst) { - InterInstruction* dins = new InterInstruction(); - dins->mCode = IC_LEA; - dins->mDst = ins->mDst; - dins->mSrc[1] = ins->mDst; - dins->mSrc[1].mMemory = IM_INDIRECT; - dins->mSrc[1].mIntConst = 0; - dins->mSrc[0].mType = IT_INT16; - dins->mSrc[0].mTemp = -1; - dins->mSrc[0].mIntConst = - indexStep[ins->mSrc[0].mTemp]; - tailBlock->mInstructions.Insert(0, dins); + ins->mSrc[0].mTemp = -1; + ins->mSrc[0].mIntConst = ins->mSrc[1].mIntConst - pindexins[k]->mSrc[1].mIntConst; + ins->mSrc[1].mTemp = pindexins[k]->mDst.mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mSrc[1].mIntConst = 0; + mInstructions[j++] = ins; + } + else +#endif + { + indexStep[ins->mDst.mTemp] = indexStep[ins->mSrc[0].mTemp]; + indexBase[ins->mDst.mTemp] = 0; + + mLoopPrefix->mInstructions.Insert(mLoopPrefix->mInstructions.Size() - 1, ins); + + InterInstruction* ains = new InterInstruction(); + ains->mCode = IC_LEA; + ains->mDst = ins->mDst; + ains->mSrc[1] = ins->mDst; + ains->mSrc[1].mMemory = IM_INDIRECT; + ains->mSrc[1].mIntConst = 0; + ains->mSrc[0].mType = IT_INT16; + ains->mSrc[0].mTemp = -1; + ains->mSrc[0].mIntConst = indexStep[ins->mSrc[0].mTemp]; + + if (tailBlock->mEntryRequiredTemps[ains->mDst.mTemp]) + { + InterInstruction* dins = new InterInstruction(); + dins->mCode = IC_LEA; + dins->mDst = ins->mDst; + dins->mSrc[1] = ins->mDst; + dins->mSrc[1].mMemory = IM_INDIRECT; + dins->mSrc[1].mIntConst = 0; + dins->mSrc[0].mType = IT_INT16; + dins->mSrc[0].mTemp = -1; + dins->mSrc[0].mIntConst = -indexStep[ins->mSrc[0].mTemp]; + tailBlock->mInstructions.Insert(0, dins); + } + indexins.Push(ains); + + if (indexStep[ins->mSrc[0].mTemp] > 1) + pindexins.Push(ins); } - indexins.Push(ains); } } else if (ins->mDst.mTemp >= 0 && dep[ins->mDst.mTemp] == DEP_INDEX_EXTENDED) @@ -10130,6 +10305,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa { int dt = ins->mDst.mTemp, st = ins->mSrc[0].mTemp; + int toffset = 0; int j = i + 1; while (j < mInstructions.Size()) { @@ -10140,7 +10316,12 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa else if (cins->mCode == IC_LOAD_TEMPORARY && cins->mSrc[0].mTemp == st && cins->mSrc[0].mFinal) st = cins->mDst.mTemp; else if (cins->mDst.mTemp == st) - break; + { + if (cins->mCode == IC_LEA && cins->mSrc[1].mTemp == st && cins->mSrc[0].mTemp < 0) + toffset += cins->mSrc[0].mIntConst; + else + break; + } j++; } @@ -10148,6 +10329,18 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa if (j == mInstructions.Size()) { ins->mSrc[0].mTemp = st; + if (toffset != 0) + { + if (ins->mDst.mType == IT_POINTER) + { + ins->mCode = IC_LEA; + ins->mNumOperands = 2; + ins->mSrc[1] = ins->mSrc[0]; + ins->mSrc[0].mTemp = -1; + ins->mSrc[0].mType = IT_INT16; + ins->mSrc[0].mIntConst = -toffset; + } + } tailBlock->mInstructions.Insert(0, ins); mInstructions.Remove(i); } @@ -10700,6 +10893,7 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati mInstructions[i + 0]->mDst.mTemp = mInstructions[i + 1]->mDst.mTemp; mInstructions[i + 1]->mDst.mTemp = mInstructions[i + 1]->mSrc[0].mTemp; mInstructions[i + 1]->mSrc[0].mTemp = mInstructions[i + 0]->mDst.mTemp; + mInstructions[i + 0]->mSingleAssignment = mInstructions[i + 1]->mSingleAssignment; changed = true; } #endif @@ -11293,7 +11487,7 @@ void InterCodeProcedure::DisassembleDebug(const char* name) void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) { // Count number of entries -// + // ResetVisited(); for (int i = 0; i < mBlocks.Size(); i++) { @@ -11702,6 +11896,11 @@ void InterCodeProcedure::MergeIndexedLoadStore(void) ResetVisited(); } while (mEntryBlock->MergeIndexedLoadStore(silvalues)); + BuildDataFlowSets(); + + TempForwarding(); + RemoveUnusedInstructions(); + DisassembleDebug("MergeIndexedLoadStore"); } @@ -11743,6 +11942,25 @@ void InterCodeProcedure::SimplifyIntegerNumeric(FastNumberSet& activeSet) DisassembleDebug("SimplifyIntegerNumeric"); } +void InterCodeProcedure::ExpandSelect(void) +{ +#if 1 + ResetVisited(); + mEntryBlock->ExpandSelect(this); + + ResetVisited(); + for (int i = 0; i < mBlocks.Size(); i++) + mBlocks[i]->mNumEntries = 0; + mEntryBlock->CollectEntries(); + + ResetEntryBlocks(); + ResetVisited(); + mEntryBlock->CollectEntryBlocks(nullptr); + + DisassembleDebug("ExpandSelect"); +#endif +} + void InterCodeProcedure::EliminateAliasValues() { GrowingInstructionPtrArray eivalues(nullptr); @@ -11970,6 +12188,12 @@ void InterCodeProcedure::Close(void) #endif CheckUsedDefinedTemps(); + ExpandSelect(); + + BuildDataFlowSets(); + + CheckUsedDefinedTemps(); + SingleAssignmentForwarding(); CheckUsedDefinedTemps(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 8ebee37..076ed59 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -36,6 +36,7 @@ enum InterCode IC_RETURN, IC_ASSEMBLER, IC_JUMPF, + IC_SELECT, IC_UNREACHABLE }; @@ -478,6 +479,8 @@ public: InterCodeBasicBlock* BuildLoopPrefix(InterCodeProcedure * proc); void BuildLoopSuffix(InterCodeProcedure* proc); + void ExpandSelect(InterCodeProcedure* proc); + void SplitBranches(InterCodeProcedure* proc); void FollowJumps(void); @@ -567,6 +570,7 @@ protected: void MergeIndexedLoadStore(void); void EliminateAliasValues(); void LoadStoreForwarding(InterMemory paramMemory); + void ExpandSelect(void); void MergeBasicBlocks(void); void CheckUsedDefinedTemps(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f860b19..9b47d60 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2848,113 +2848,207 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } case EX_CONDITIONAL: - { - InterInstruction * jins0 = new InterInstruction(); - jins0->mCode = IC_JUMP; - InterInstruction* jins1 = new InterInstruction(); - jins1->mCode = IC_JUMP; - - InterCodeBasicBlock* tblock = new InterCodeBasicBlock(); - proc->Append(tblock); - InterCodeBasicBlock* fblock = new InterCodeBasicBlock(); - proc->Append(fblock); - InterCodeBasicBlock* eblock = new InterCodeBasicBlock(); - proc->Append(eblock); - - TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper); - - vl = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); - - int ttemp; - InterType ttype, stypel, styper; - - stypel = InterTypeOf(vl.mType); - styper = InterTypeOf(vr.mType); - - Declaration* dtype; - if (stypel == IT_POINTER || styper == IT_POINTER) + { +#if 1 + if ((exp->mRight->mLeft->mType == EX_CONSTANT || exp->mRight->mLeft->mType == EX_VARIABLE) && + (exp->mRight->mRight->mType == EX_CONSTANT || exp->mRight->mRight->mType == EX_VARIABLE)) { - if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, tblock, vl, 1); - else - vl = Dereference(proc, tblock, vl); + ExValue vc = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); - if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, fblock, vr, 1); - else - vr = Dereference(proc, fblock, vr); + vl = TranslateExpression(procType, proc, block, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); - if (vl.mType->mBase->IsSubType(vr.mType->mBase)) - dtype = vr.mType; - else if (vr.mType->mBase->IsSubType(vl.mType->mBase)) - dtype = vl.mType; + vc = Dereference(proc, block, vc); + vl = Dereference(proc, block, vl); + vr = Dereference(proc, block, vr); + + int ttemp; + InterType ttype, stypel, styper; + + stypel = InterTypeOf(vl.mType); + styper = InterTypeOf(vr.mType); + + Declaration* dtype; + if (stypel == IT_POINTER || styper == IT_POINTER) + { + if (vl.mType->mType == DT_TYPE_ARRAY) + vl = Dereference(proc, block, vl, 1); + else + vl = Dereference(proc, block, vl); + + if (vr.mType->mType == DT_TYPE_ARRAY) + vr = Dereference(proc, block, vr, 1); + else + vr = Dereference(proc, block, vr); + + if (vl.mType->mBase->IsSubType(vr.mType->mBase)) + dtype = vr.mType; + else if (vr.mType->mBase->IsSubType(vl.mType->mBase)) + dtype = vl.mType; + else + { + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible conditional types"); + dtype = vl.mType; + } + + Declaration* ntype = new Declaration(dtype->mLocation, DT_TYPE_POINTER); + ntype->mBase = dtype->mBase; + dtype = ntype; + + ttype = IT_POINTER; + } else { - mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible conditional types"); - dtype = vl.mType; + + if (stypel == styper) + { + ttype = stypel; + dtype = vl.mType; + } + else if (stypel > styper) + { + ttype = stypel; + dtype = vl.mType; + + vr = CoerceType(proc, block, vr, dtype); + } + else + { + ttype = styper; + dtype = vr.mType; + + vl = CoerceType(proc, block, vl, dtype); + } } - Declaration* ntype = new Declaration(dtype->mLocation, DT_TYPE_POINTER); - ntype->mBase = dtype->mBase; - dtype = ntype; - - ttype = IT_POINTER; + vc = CoerceType(proc, block, vc, TheBoolTypeDeclaration); + + ttemp = proc->AddTemporary(ttype); + + InterInstruction* sins = new InterInstruction(); + sins->mCode = IC_SELECT; + sins->mSrc[2].mType = InterTypeOf(vc.mType); + sins->mSrc[2].mTemp = vc.mTemp; + sins->mSrc[1].mType = ttype; + sins->mSrc[1].mTemp = vl.mTemp; + sins->mSrc[0].mType = ttype; + sins->mSrc[0].mTemp = vr.mTemp; + sins->mDst.mType = ttype; + sins->mDst.mTemp = ttemp; + block->Append(sins); + + return ExValue(dtype, ttemp); } else +#endif { - vl = Dereference(proc, tblock, vl); - vr = Dereference(proc, fblock, vr); + InterInstruction* jins0 = new InterInstruction(); + jins0->mCode = IC_JUMP; + InterInstruction* jins1 = new InterInstruction(); + jins1->mCode = IC_JUMP; - if (stypel == styper) - { - ttype = stypel; - dtype = vl.mType; - } - else if (stypel > styper) - { - ttype = stypel; - dtype = vl.mType; + InterCodeBasicBlock* tblock = new InterCodeBasicBlock(); + proc->Append(tblock); + InterCodeBasicBlock* fblock = new InterCodeBasicBlock(); + proc->Append(fblock); + InterCodeBasicBlock* eblock = new InterCodeBasicBlock(); + proc->Append(eblock); - vr = CoerceType(proc, fblock, vr, dtype); + TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper); + + vl = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); + + int ttemp; + InterType ttype, stypel, styper; + + stypel = InterTypeOf(vl.mType); + styper = InterTypeOf(vr.mType); + + Declaration* dtype; + if (stypel == IT_POINTER || styper == IT_POINTER) + { + if (vl.mType->mType == DT_TYPE_ARRAY) + vl = Dereference(proc, tblock, vl, 1); + else + vl = Dereference(proc, tblock, vl); + + if (vr.mType->mType == DT_TYPE_ARRAY) + vr = Dereference(proc, fblock, vr, 1); + else + vr = Dereference(proc, fblock, vr); + + if (vl.mType->mBase->IsSubType(vr.mType->mBase)) + dtype = vr.mType; + else if (vr.mType->mBase->IsSubType(vl.mType->mBase)) + dtype = vl.mType; + else + { + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible conditional types"); + dtype = vl.mType; + } + + Declaration* ntype = new Declaration(dtype->mLocation, DT_TYPE_POINTER); + ntype->mBase = dtype->mBase; + dtype = ntype; + + ttype = IT_POINTER; } else { - ttype = styper; - dtype = vr.mType; + vl = Dereference(proc, tblock, vl); + vr = Dereference(proc, fblock, vr); - vl = CoerceType(proc, tblock, vl, dtype); + if (stypel == styper) + { + ttype = stypel; + dtype = vl.mType; + } + else if (stypel > styper) + { + ttype = stypel; + dtype = vl.mType; + + vr = CoerceType(proc, fblock, vr, dtype); + } + else + { + ttype = styper; + dtype = vr.mType; + + vl = CoerceType(proc, tblock, vl, dtype); + } } + + ttemp = proc->AddTemporary(ttype); + + InterInstruction* rins = new InterInstruction(); + rins->mCode = IC_LOAD_TEMPORARY; + rins->mSrc[0].mType = ttype; + rins->mSrc[0].mTemp = vr.mTemp; + rins->mDst.mType = ttype; + rins->mDst.mTemp = ttemp; + fblock->Append(rins); + + InterInstruction* lins = new InterInstruction(); + lins->mCode = IC_LOAD_TEMPORARY; + lins->mSrc[0].mType = ttype; + lins->mSrc[0].mTemp = vl.mTemp; + lins->mDst.mType = ttype; + lins->mDst.mTemp = ttemp; + tblock->Append(lins); + + tblock->Append(jins0); + tblock->Close(eblock, nullptr); + + fblock->Append(jins1); + fblock->Close(eblock, nullptr); + + block = eblock; + + return ExValue(dtype, ttemp); } - ttemp = proc->AddTemporary(ttype); - - InterInstruction * rins = new InterInstruction(); - rins->mCode = IC_LOAD_TEMPORARY; - rins->mSrc[0].mType = ttype; - rins->mSrc[0].mTemp = vr.mTemp; - rins->mDst.mType = ttype; - rins->mDst.mTemp = ttemp; - fblock->Append(rins); - - InterInstruction * lins = new InterInstruction(); - lins->mCode = IC_LOAD_TEMPORARY; - lins->mSrc[0].mType = ttype; - lins->mSrc[0].mTemp = vl.mTemp; - lins->mDst.mType = ttype; - lins->mDst.mTemp = ttemp; - tblock->Append(lins); - - tblock->Append(jins0); - tblock->Close(eblock, nullptr); - - fblock->Append(jins1); - fblock->Close(eblock, nullptr); - - block = eblock; - - return ExValue(dtype, ttemp); - break; } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 091604d..43dfbd2 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -11503,8 +11503,24 @@ bool NativeCodeBasicBlock::OptimizeXYPairUsage(void) j++; if (j + 1 == mIns.Size() || !(mIns[j].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Y))) { + bool tox = ins.mType == ASMIT_LDY, toy = ins.mType == ASMIT_LDX; for (int k = i; k <= j; k++) - mIns[k].SwapXYReg(); + { + if (mIns[k].ChangesXReg()) + tox = false; + if (mIns[k].ChangesYReg()) + toy = false; + + if (tox) + mIns[k].ReplaceYRegWithXReg(); + else if (toy) + mIns[k].ReplaceXRegWithYReg(); + else + mIns[k].SwapXYReg(); + } + + CheckLive(); + changed = true; } } @@ -11915,6 +11931,49 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) break; } #endif +#if 1 + if (i + 4 < mIns.Size() && + (mIns[i + 0].mType == ASMIT_CPX || mIns[i + 0].mType == ASMIT_CPY) && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x01 && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0x00 && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && + mIns[i + 3].mType == ASMIT_AND && mIns[i + 3].mMode == ASMIM_IMMEDIATE && + mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE) + { + char veq = mIns[i + 3].mAddress ^ mIns[i + 4].mAddress, vne = mIns[i + 4].mAddress; + + 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 + 5; j < mIns.Size(); j++) + rblock->mIns.Push(mIns[j]); + mIns.SetSize(i + 1); + if (mIns[i + 0].mType == ASMIT_CPX) + mIns[i + 0].mType = ASMIT_TXA; + else if (mIns[i + 0].mType == ASMIT_CPY) + mIns[i + 0].mType = ASMIT_TYA; + mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 0].mLive |= LIVE_CPU_REG_Z; + + mTrueJump = neblock; + mFalseJump = eblock; + mBranch = ASMIT_BNE; + + if (veq != 0) + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, veq)); + neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, vne)); + + eblock->Close(rblock, nullptr, ASMIT_JMP); + neblock->Close(rblock, nullptr, ASMIT_JMP); + break; + } +#endif #if 1 if (i + 4 < mIns.Size() && mIns[i + 0].ChangesAccuAndFlag() && @@ -20950,7 +21009,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #if 1 // replace zero page down - for (int i = 1; i + 1 < mIns.Size(); i++) + 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 + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && (mIns[i + 0].mLive & LIVE_MEM)) { @@ -24463,7 +24522,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } } - +#if 1 if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & (LIVE_MEM | LIVE_CPU_REG_Y))) { int apos, breg; @@ -24473,7 +24532,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } } - +#endif +#if 1 if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO)) { int apos, breg; @@ -24483,6 +24543,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } } +#endif #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f232664..7f11619 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2165,13 +2165,13 @@ Expression* Parser::ParseStatement(void) { int startValue = initExp->mRight->mDecValue->mInteger; int endValue = conditionExp->mRight->mDecValue->mInteger; - + int remain = (endValue - startValue) % unrollLoop; endValue -= remain; conditionExp->mRight->mDecValue->mInteger = endValue; - Expression * unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE); + Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE); unrollBody->mLeft = bodyExp; Expression* bexp = unrollBody; if (endValue > startValue) @@ -2206,7 +2206,11 @@ Expression* Parser::ParseStatement(void) bodyExp = unrollBody; } + else + mErrors->Error(exp->mLocation, EWARN_LOOP_UNROLL_IGNORED, "Loop unroll ignored, bounds and step not integer"); } + else + mErrors->Error(exp->mLocation, EWARN_LOOP_UNROLL_IGNORED, "Loop unroll ignored, bounds and step not const"); } exp->mLeft->mRight = initExp; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 3870972..49c209d 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.7.140"); + strcpy(strProductVersion, "1.7.141"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 5a28b3c..5b749e2 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,140,0 - PRODUCTVERSION 1,7,140,0 + FILEVERSION 1,7,141,0 + PRODUCTVERSION 1,7,141,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.7.140.0" + VALUE "FileVersion", "1.7.141.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.7.140.0" + VALUE "ProductVersion", "1.7.141.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index d7e1e46..a908e01 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -4153,15 +4153,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{4AC1A78B-6BCA-4D2F-A54D-DEA5F627B017}" - "PackageCode" = "8:{ED70C89A-F338-434F-9FB2-90C1BD8EB020}" + "ProductCode" = "8:{AAAF5F55-0261-47DA-B051-EF84642395A5}" + "PackageCode" = "8:{A7501921-EE58-422B-AEE2-4491A2249AC0}" "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.7.140" + "ProductVersion" = "8:1.7.141" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" diff --git a/samples/scrolling/bigfont.c b/samples/scrolling/bigfont.c index c196a84..2160469 100644 --- a/samples/scrolling/bigfont.c +++ b/samples/scrolling/bigfont.c @@ -46,7 +46,7 @@ void expand(char c, byte f) byte * fp = font + 8 * c; // Unroll eight times for each byte in glyph data -// #pragma unroll(full) + //#pragma unroll(full) for(char y=0; y<8; y++) { char t = (fp[y] & f) ? 160 : 32;