diff --git a/README.md b/README.md index 9d62e71..9f76cf6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ There are still several open areas, but most targets have been reached. The cur ### Optimizing -* Complex loop optimization * Auto variables placed on fixed stack for known call sequence ### Intermediate code generation @@ -118,6 +117,30 @@ A section of the file can be selected by providing a limit and or an offset into 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. +### Marking functions as native + +Routines can be marked to be compiled to 6502 machine code with the native pragma: + + void Plot(int x, int y) + { + (*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7); + } + + #pragma native(Plot) + +Or alternatively with a __native storage class specifier + + __native void Plot(int x, int y) + { + (*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7); + } + +### Linker control + +The linker includes only objects that are referenced, starting by the startup code into main() and so on. + +If you need to have a function or variable present regardless, you can specify it with the __export storage class specifier or use the #pragma reference(name) pragma. + ## Inline Assembler @@ -263,15 +286,6 @@ The intermediate code generator assumes a large number of registers so the zero * **0x43-0x52** caller saved registers * **0x53-0x8f** callee saved registers -Routines can be marked to be compiled to 6502 machine code with the native pragma: - - void Plot(int x, int y) - { - (*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7); - } - - #pragma native(Plot) - diff --git a/include/c64/rasterirq.c b/include/c64/rasterirq.c index 5c1a351..2b76241 100644 --- a/include/c64/rasterirq.c +++ b/include/c64/rasterirq.c @@ -3,6 +3,7 @@ #include #include #include +#include volatile char npos = 1, tpos = 0; @@ -176,40 +177,32 @@ void rirq_build(RIRQCode * ic, byte size) asm_ab(ic->code + 4, ASM_CPX, 0xd012); asm_rl(ic->code + 7, ASM_BCS, -5); asm_ab(ic->code + 9, ASM_STY, 0x0000); - /* - ic->code[0] = 0xa0; // ldy # - ic->code[2] = 0xa9; // lda # - ic->code[4] = 0xec; // cpx - ic->code[5] = 0x12; - ic->code[6] = 0xd0; - ic->code[7] = 0xb0; // bcs - ic->code[8] = -5; - ic->code[9] = 0x8c; // sty - */ + if (size == 1) { asm_np(ic->code + 12, ASM_RTS); - //ic->code[12] = 0x60; // rts } else { asm_ab(ic->code + 12, ASM_STA, 0x0000); - // ic->code[12] = 0x8d; // sty byte p = 15; for(byte i=2; icode + p, ASM_LDA, 0x00); p += asm_ab(ic->code + p, ASM_STA, 0x0000); - //ic->code[p] = 0xa9; // lda # - //ic->code[p + 2] = 0x8d; // sta - //p += 5; } asm_np(ic->code + p, ASM_RTS); - //ic->code[p] = 0x60; } } +RIRQCode * rirq_alloc(byte size) +{ + RIRQCode * ic = (RIRQCode *)malloc(1 + RIRQ_SIZE + 5 * size); + rirq_build(ic, size); + return ic; +} + #pragma native(rirq_build) void rirq_set(byte n, byte row, RIRQCode * write) @@ -220,8 +213,15 @@ void rirq_set(byte n, byte row, RIRQCode * write) rasterIRQRows[n] = row; } -static const byte irqai[6] = {RIRQ_ADDR_0, RIRQ_ADDR_1, RIRQ_ADDR_2, RIRQ_ADDR_3, RIRQ_ADDR_4}; -static const byte irqdi[6] = {RIRQ_DATA_0, RIRQ_DATA_1, RIRQ_DATA_2, RIRQ_DATA_3, RIRQ_DATA_4}; +static const byte irqai[16] = { + RIRQ_ADDR_0, RIRQ_ADDR_1, RIRQ_ADDR_2, RIRQ_ADDR_3, RIRQ_ADDR_4, RIRQ_ADDR_5, RIRQ_ADDR_6, RIRQ_ADDR_7, + RIRQ_ADDR_8, RIRQ_ADDR_9, RIRQ_ADDR_10, RIRQ_ADDR_11, RIRQ_ADDR_12, RIRQ_ADDR_13, RIRQ_ADDR_14, RIRQ_ADDR_15 +}; + +static const byte irqdi[16] = { + RIRQ_DATA_0, RIRQ_DATA_1, RIRQ_DATA_2, RIRQ_DATA_3, RIRQ_DATA_4, RIRQ_DATA_5, RIRQ_DATA_6, RIRQ_DATA_7, + RIRQ_DATA_8, RIRQ_DATA_9, RIRQ_DATA_10, RIRQ_DATA_11, RIRQ_DATA_12, RIRQ_DATA_13, RIRQ_DATA_14, RIRQ_DATA_15 +}; void rirq_addr(RIRQCode * ic, byte n, void * addr) { diff --git a/include/c64/rasterirq.h b/include/c64/rasterirq.h index 8b61345..5a45318 100644 --- a/include/c64/rasterirq.h +++ b/include/c64/rasterirq.h @@ -23,7 +23,40 @@ enum RIRQCodeIndex RIRQ_DATA_4 = 26, RIRQ_ADDR_4 = 28, - RIRQ_SIZE = 31 + RIRQ_SIZE = 31, + + RIRQ_DATA_5 = 31, + RIRQ_ADDR_5 = 33, + + RIRQ_DATA_6 = 36, + RIRQ_ADDR_6 = 38, + + RIRQ_DATA_7 = 41, + RIRQ_ADDR_7 = 43, + + RIRQ_DATA_8 = 46, + RIRQ_ADDR_8 = 48, + + RIRQ_DATA_9 = 51, + RIRQ_ADDR_9 = 53, + + RIRQ_DATA_10 = 56, + RIRQ_ADDR_10 = 58, + + RIRQ_DATA_11 = 61, + RIRQ_ADDR_11 = 63, + + RIRQ_DATA_12 = 66, + RIRQ_ADDR_12 = 68, + + RIRQ_DATA_13 = 71, + RIRQ_ADDR_13 = 73, + + RIRQ_DATA_14 = 76, + RIRQ_ADDR_14 = 78, + + RIRQ_DATA_15 = 81, + RIRQ_ADDR_15 = 88, }; // One raster interrupt operation, handles up to five writes @@ -34,9 +67,12 @@ typedef struct RIRQCode byte code[RIRQ_SIZE]; } RIRQCode; -// Build one raster IRQ operation of the given size (wait + #ops) +// Build one raster IRQ operation of the given size (wait + #ops) for up to 5 instructions void rirq_build(RIRQCode * ic, byte size); +// Allocate one raster IRQ operation of the given size (wait + #ops) +RIRQCode * rirq_alloc(byte size); + // Add a write command to a raster IRQ inline void rirq_write(RIRQCode * ic, byte n, void * addr, byte data); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 4e2da77..943d115 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -66,14 +66,16 @@ static const uint32 DTF_FASTCALL = 0x00004000; static const uint32 DTF_INLINE = 0x00008000; static const uint32 DTF_ANALYZED = 0x00010000; static const uint32 DTF_REQUEST_INLINE = 0x00020000; +static const uint32 DTF_INTERRUPT = 0x00040000; +static const uint32 DTF_EXPORT = 0x00080000; -static const uint32 DTF_FUNC_VARIABLE = 0x00040000; -static const uint32 DTF_FUNC_ASSEMBLER = 0x00080000; -static const uint32 DTF_FUNC_RECURSIVE = 0x00100000; -static const uint32 DTF_FUNC_ANALYZING = 0x00200000; -static const uint32 DTF_FUNC_CONSTEXPR = 0x00400000; +static const uint32 DTF_FUNC_VARIABLE = 0x00100000; +static const uint32 DTF_FUNC_ASSEMBLER = 0x00200000; +static const uint32 DTF_FUNC_RECURSIVE = 0x00400000; +static const uint32 DTF_FUNC_ANALYZING = 0x00800000; +static const uint32 DTF_FUNC_CONSTEXPR = 0x01000000; -static const uint32 DTF_VAR_ALIASING = 0x00800000; +static const uint32 DTF_VAR_ALIASING = 0x02000000; class Declaration; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 108600c..a0001ba 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -54,6 +54,7 @@ enum ErrorID ERRR_PREPROCESSOR, ERRR_INVALID_CASE, ERRR_INSUFFICIENT_MEMORY, + ERRR_INTERRUPT_TO_COMPLEX, EERR_INVALID_PREPROCESSOR, }; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 5d7704e..342cb57 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -8022,7 +8022,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1), mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mIdent(ident), mLinkerObject(linkerObject), - mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false) + mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mInterrupt(false) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); @@ -8729,6 +8729,8 @@ void InterCodeProcedure::Close(void) BuildLoopPrefix(); DisassembleDebug("added dominators"); + BuildDataFlowSets(); + ResetVisited(); mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index cb7534b..0a1e75c 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -476,7 +476,7 @@ public: GrowingTypeArray mTemporaries; GrowingIntArray mTempOffset, mTempSizes; int mTempSize, mCommonFrameSize, mCallerSavedTemps; - bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; + bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure, mInterrupt; GrowingInterCodeProcedurePtrArray mCalledFunctions; InterCodeModule * mModule; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index b1aaf10..c67fe39 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3363,6 +3363,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod if (dec->mFlags & DTF_NATIVE) proc->mNativeProcedure = true; + if (dec->mFlags & DTF_INTERRUPT) + proc->mInterrupt = true; + if (dec->mBase->mFlags & DTF_FASTCALL) { proc->mFastCallProcedure = true; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 96577c9..19d8bc6 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -33,6 +33,34 @@ enum LinkerSectionType LST_STACK }; +struct ZeroPageSet +{ + ZeroPageSet(void) + { + for (int i = 0; i < 8; i++) + mBits[i] = 0; + } + + uint32 mBits[8]; + + void operator += (int n) + { + mBits[n >> 5] |= 1 << (n & 31); + } + + bool operator[] (int n) const + { + return (mBits[n >> 5] & (1 << (n & 31))) != 0; + } + + ZeroPageSet& operator |= (const ZeroPageSet& set) + { + for (int i = 0; i < 8; i++) + mBits[i] |= set.mBits[i]; + return *this; + } +}; + class LinkerObject; class LinkerSection; @@ -110,6 +138,7 @@ public: uint32 mFlags; uint8 mTemporaries[16], mTempSizes[16]; int mNumTemporaries; + ZeroPageSet mZeroPageSet; LinkerObject(void); ~LinkerObject(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 3b5a995..d4d6b9b 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -8430,6 +8430,50 @@ void NativeCodeBasicBlock::FindZeroPageAlias(const NumberSet& statics, NumberSet } } +void NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + switch (mIns[i].mMode) + { + case ASMIM_ZERO_PAGE: + if (mIns[i].ChangesAddress()) + locals += mIns[i].mAddress; + break; + case ASMIM_ABSOLUTE: + if (mIns[i].mType == ASMIT_JSR) + { + if (mIns[i].mFlags & NCIF_RUNTIME) + { + for (int j = 0; j < 4; j++) + { + locals += BC_REG_ACCU + j; + locals += BC_REG_WORK + j; + } + } + + if (mIns[i].mLinkerObject) + { + LinkerObject* lo = mIns[i].mLinkerObject; + + global |= lo->mZeroPageSet; + } + } + break; + } + } + + if (mTrueJump) + mTrueJump->CollectZeroPageSet(locals, global); + if (mFalseJump) + mFalseJump->CollectZeroPageSet(locals, global); + } +} + void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used, NumberSet &modified, NumberSet& pairs) { if (!mVisited) @@ -8451,14 +8495,28 @@ void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used, NumberSet &modi pairs += mIns[i].mAddress; break; case ASMIM_ABSOLUTE: - if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject) + if (mIns[i].mType == ASMIT_JSR) { - LinkerObject* lo = mIns[i].mLinkerObject; - - for (int i = 0; i < lo->mNumTemporaries; i++) + if (mIns[i].mFlags & NCIF_RUNTIME) { - for (int j = 0; j < lo->mTempSizes[i]; j++) - used += lo->mTemporaries[i] + j; + for (int j = 0; j < 4; j++) + { + used += BC_REG_ACCU + j; + used += BC_REG_WORK + j; + modified += BC_REG_ACCU + j; + modified += BC_REG_WORK + j; + } + } + + if (mIns[i].mLinkerObject) + { + LinkerObject* lo = mIns[i].mLinkerObject; + + for (int i = 0; i < lo->mNumTemporaries; i++) + { + for (int j = 0; j < lo->mTempSizes[i]; j++) + used += lo->mTemporaries[i] + j; + } } } break; @@ -13728,7 +13786,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) { int yoffset = mIns[i + 0].mAddress; - if (breg == mIns[i + 2].mAddress) + if (breg == mIns[i + 2].mAddress || ireg == mIns[i + 2].mAddress) { mIns[apos + 3].mType = ASMIT_NOP; mIns[apos + 3].mMode = ASMIM_IMPLIED; mIns[apos + 6].mType = ASMIT_NOP; mIns[apos + 6].mMode = ASMIM_IMPLIED; @@ -14067,7 +14125,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_INX; else - mIns[i + 3].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STX; progress = true; } @@ -14083,7 +14142,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_DEX; else - mIns[i + 3].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STX; progress = true; } @@ -14099,7 +14159,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_INY; else - mIns[i + 3].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STY; progress = true; } @@ -14115,7 +14176,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) if (mIns[i + 2].mAddress == 2) mIns[i + 2].mType = ASMIT_DEY; else - mIns[i + 3].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_STY; progress = true; } @@ -15054,163 +15116,224 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) bool ignoreExpandCommonFrame = false; - if (mNoFrame) + if (mInterProc->mInterrupt) { - if (mStackExpand > 0) + if (!mNoFrame || mStackExpand > 0 || commonFrameSize > 0) + mGenerator->mErrors->Error(mInterProc->mLocation, ERRR_INTERRUPT_TO_COMPLEX, "Function to complex for interrupt"); + + ZeroPageSet zpLocal, zpGlobal; + ResetVisited(); + mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal); + zpLocal |= zpGlobal; + + for (int i = 2; i < 256; i++) { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (mStackExpand + commonFrameSize) & 0xff)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - ignoreExpandCommonFrame = true; - - if (tempSave) + if (zpLocal[i]) { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); - if (tempSave == 1) - { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - } - else if (tempSave == 2) - { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, i)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA)); + } + } - } - else if (commonFrameSize > 0) - { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); - } - else - { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); - } + for (int i = 255; i >= 2; i--) + { + if (zpLocal[i]) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_PLA)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i)); } } } else { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, mStackExpand & 0xff)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (mStackExpand >> 8) & 0xff)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - - if (tempSave) + if (mNoFrame) { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + if (mStackExpand > 0) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (mStackExpand + commonFrameSize) & 0xff)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + ignoreExpandCommonFrame = true; - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + if (tempSave) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); + if (tempSave == 1) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + } + else if (tempSave == 2) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + + } + else if (commonFrameSize > 0) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + else + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + } + } + } + else + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, mStackExpand & 0xff)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (mStackExpand >> 8) & 0xff)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - if (tempSave > 1) + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + + if (tempSave) { mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + if (tempSave > 1) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + } + + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, frameSpace + 2)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + } + + if (!proc->mLeafProcedure && commonFrameSize > 0 && !ignoreExpandCommonFrame) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + if (commonFrameSize >= 256) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + else + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2)); + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + if (commonFrameSize >= 256) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + else + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); } } - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, frameSpace + 2)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); - } - - if (!proc->mLeafProcedure && commonFrameSize > 0 && !ignoreExpandCommonFrame) - { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - if (commonFrameSize >= 256) + if (mNoFrame) { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + if (mStackExpand > 0) + { + if (tempSave) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); + if (tempSave == 1) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); + } + else if (tempSave == 2) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); + + } + else if (commonFrameSize > 0) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + else + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); + } + } + + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (mStackExpand + commonFrameSize) & 0xff)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } } else { - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2)); - mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - } + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - if (commonFrameSize >= 256) - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - } - else - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - } - } - - if (mNoFrame) - { - if (mStackExpand > 0) - { if (tempSave) { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1)); - if (tempSave == 1) - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); - } - else if (tempSave == 2) - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED + 1)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP_SAVED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - } - else if (commonFrameSize > 0) + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + if (tempSave > 1) { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); - } - else - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); } @@ -15218,43 +15341,20 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (mStackExpand + commonFrameSize) & 0xff)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, mStackExpand & 0xff)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - } - } - else - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (mStackExpand >> 8) & 0xff)); + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - if (tempSave) - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); - if (tempSave > 1) - { - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8)); - } } - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, mStackExpand & 0xff)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (mStackExpand >> 8) & 0xff)); - mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + ZeroPageSet zpLocal, zpGlobal; + ResetVisited(); + mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal); + zpLocal |= zpGlobal; + proc->mLinkerObject->mZeroPageSet = zpLocal; } mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED)); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 45f9720..944ad47 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -243,6 +243,7 @@ public: void BuildEntryDataSet(const NativeRegisterDataSet& set); bool ApplyEntryDataSet(void); + void CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global); void CollectZeroPageUsage(NumberSet& used, NumberSet& modified, NumberSet& pairs); void FindZeroPageAlias(const NumberSet& statics, NumberSet& invalid, uint8* alias, int accu); bool RemapZeroPage(const uint8* remap); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3ee00ea..fb963d4 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -376,10 +376,21 @@ Declaration* Parser::ParsePostfixDeclaration(void) Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); ndec->mSize = 2; ndec->mFlags |= DTF_DEFINED; - if (mScanner->mToken == TK_CONST) + + for (;;) { - ndec->mFlags |= DTF_CONST; - mScanner->NextToken(); + if (mScanner->mToken == TK_CONST) + { + ndec->mFlags |= DTF_CONST; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_VOLATILE) + { + ndec->mFlags |= DTF_VOLATILE; + mScanner->NextToken(); + } + else + break; } Declaration* dec = ParsePostfixDeclaration(); @@ -605,6 +616,7 @@ Declaration * Parser::CopyConstantInitializer(int offset, Declaration* dtype, Ex ndec->mValue = exp; ndec->mBase = dtype; dec = ndec; + dec->mOffset = offset; } else mErrors->Error(exp->mLocation, EERR_CONSTANT_INITIALIZER, "Incompatible constant initializer"); @@ -886,22 +898,45 @@ Declaration* Parser::ParseDeclaration(bool variable) } else { - if (mScanner->mToken == TK_STATIC) + for (;;) { - storageFlags |= DTF_STATIC; - mScanner->NextToken(); - } - - if (mScanner->mToken == TK_EXTERN) - { - storageFlags |= DTF_EXTERN; - mScanner->NextToken(); - } - - if (mScanner->mToken == TK_INLINE) - { - storageFlags |= DTF_REQUEST_INLINE; - mScanner->NextToken(); + if (mScanner->mToken == TK_STATIC) + { + storageFlags |= DTF_STATIC; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_EXTERN) + { + storageFlags |= DTF_EXTERN; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_INLINE) + { + storageFlags |= DTF_REQUEST_INLINE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_EXPORT) + { + storageFlags |= DTF_EXPORT; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_FASTCALL) + { + storageFlags |= DTF_FASTCALL; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_NATIVE) + { + storageFlags |= DTF_NATIVE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_INTERRUPT) + { + storageFlags |= DTF_INTERRUPT | DTF_NATIVE; + mScanner->NextToken(); + } + else + break; } } @@ -1057,6 +1092,11 @@ Declaration* Parser::ParseDeclaration(bool variable) ndec->mSection = mDataSection; ndec->mSize = ndec->mBase->mSize; } + + if (storageFlags & DTF_EXPORT) + { + mCompilationUnits->AddReferenced(ndec); + } } if (mScanner->mToken == TK_COMMA) diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 7876cba..4d75b82 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -50,6 +50,10 @@ const char* TokenNames[] = "'__assume'", "__asm", + "__interrupt", + "__native", + "__fastcall", + "__export", "number", "char", @@ -1257,6 +1261,14 @@ void Scanner::NextRawToken(void) mToken = TK_ASM; else if (!strcmp(tkident, "__assume")) mToken = TK_ASSUME; + else if (!strcmp(tkident, "__interrupt")) + mToken = TK_INTERRUPT; + else if (!strcmp(tkident, "__native")) + mToken = TK_NATIVE; + else if (!strcmp(tkident, "__fastcall")) + mToken = TK_FASTCALL; + else if (!strcmp(tkident, "__export")) + mToken = TK_EXPORT; else { mToken = TK_IDENT; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 8f54b3a..88687ac 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -48,6 +48,10 @@ enum Token TK_ASSUME, TK_ASM, + TK_INTERRUPT, + TK_NATIVE, + TK_FASTCALL, + TK_EXPORT, TK_NUMBER, TK_CHARACTER, diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index e59e5df..32b5b25 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -73,7 +73,7 @@ int main(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.2.67"); + strcpy(strProductVersion, "1.2.68"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index c556bec..65971cb 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,67,0 - PRODUCTVERSION 1,2,67,0 + FILEVERSION 1,2,68,0 + PRODUCTVERSION 1,2,68,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.2.67.0" + VALUE "FileVersion", "1.2.68.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.2.67.0" + VALUE "ProductVersion", "1.2.68.0" END END BLOCK "VarFileInfo" diff --git a/samples/resources/scifiglyph.bin b/samples/resources/scifiglyph.bin new file mode 100644 index 0000000..f87531c Binary files /dev/null and b/samples/resources/scifiglyph.bin differ diff --git a/samples/sprites/build.sh b/samples/sprites/build.sh index 9988474..8ac1784 100644 --- a/samples/sprites/build.sh +++ b/samples/sprites/build.sh @@ -1,3 +1,4 @@ #!/bin/sh ../../bin/oscar64 joycontrol.c ../../bin/oscar64 multiplexer.c -n +../../bin/oscar64 creditroll.c -n diff --git a/samples/sprites/creditroll.c b/samples/sprites/creditroll.c new file mode 100644 index 0000000..470d9a4 --- /dev/null +++ b/samples/sprites/creditroll.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include + +#define Screen ((char *)0x400) + +// make space until 0x2000 for code and data + +#pragma region( lower, 0x0a00, 0x2000, , , {code, data} ) + +// then space for our sprite data + +#pragma section( spriteset, 0) + +#pragma region( spriteset, 0x2000, 0x2c00, , , {spriteset} ) + + +// everything beyond will be code, data, bss and heap to the end + +#pragma region( main, 0x2c00, 0xa000, , , {code, data, bss, heap, stack} ) + + +// spriteset at fixed location + +#pragma data(spriteset) + +char spriteset[64 * 48] = {0}; + +#pragma data(data) + +char charset[32 * 8] = { + #embed "../resources/scifiglyph.bin" +} + + +const char * scrolltext[] = { + + +"This sample uses", +"six sprites", +"multiplexed six", +"times to provide", +"twelve lines of", +"text with eighteen", +"characters each", +"", +"each character is", +"extracted from a", +"custom font into a", +"new sprite and the", +"sprites are then", +"moved up the", +"screen", +"", +"interrupts are", +"used to switch the", +"sprite vertical", +"position and", +"graphics", +"data every two", +"character lines" +"", +"", +"", +"", +}; + + +RIRQCode * spmux[6], final; + +void readline(char * dp, char n) +{ + const char * sp = scrolltext[n]; + + char s = 0; + while (sp[s]) + s++; + + char l = (18 - s) >> 1; + char i = 0; + while (i < l) + dp[i++] = ' '; + + s = 0; + while (sp[s]) + { + dp[i++] = sp[s]; + s++; + } + + while (i < 18) + dp[i++] = ' '; +} + +void expandline(const char * line, char sppos, char ty) +{ + char * dp = spriteset + 64 * sppos + 3 * ty; + + char xl = 0; + for(char x=0; x<6; x++) + { + const char * sp = charset + 8 * (line[x] & 0x1f); + + dp[ 0] = sp[0]; dp[ 3] = sp[1]; dp[ 6] = sp[2]; dp[ 9] = sp[3]; + dp[12] = sp[4]; dp[15] = sp[5]; dp[18] = sp[6]; dp[21] = sp[7]; + + dp++; + xl++; + if (xl == 3) + { + dp += 61; + xl = 0; + } + } +} + +int main(void) +{ + rirq_init(true); + spr_init(Screen); + + int oy = 0; + char sy = 128; + + for(int i=0; i<5; i++) + { + spmux[i] = rirq_alloc(12); + for(int x=0; x<6; x++) + { + rirq_write(spmux[i], 2 * x + 0, &vic.spr_pos[x].y, 48 * (i + 1) + oy); + rirq_write(spmux[i], 2 * x + 1, Screen + 0x3f8 + x, sy + 1 + i); + } + rirq_set(i, 48 * i + 46 + oy, spmux[i]); + } + + rirq_build(&final, 0); + rirq_set(5, 250, &final); + rirq_sort(); + + rirq_start(); + + for(int x=0; x<6; x++) + { + spr_set(x, true, 40 + 48 * x, oy, 128, 1, false, true, true); + } + + char line[20]; + char lpos = 0; + + for(;;) + { + rirq_wait(); + + oy--; + if (oy < 0) + { + oy += 48; + sy += 6; + if (sy == 128 + 36) + sy = 128; + } + + for(char i=0; i<5; i++) + { + int ty = 48 * i + 46 + oy; + if (ty < 250) + rirq_move(i, ty); + else + rirq_clear(i); + } + rirq_sort(); + + char sty = sy; + for(int x=0; x<6; x++) + { + spr_move(x, 40 + 48 * x, oy); + spr_image(x, sty); + sty ++; + } + + + for(char i=0; i<5; i++) + { + if (sty == 128 + 36) + sty = 128; + + char py = 48 * (i + 1) + oy; + for(char x=0; x<6; x++) + { + rirq_data(spmux[i], 2 * x + 0, py); + rirq_data(spmux[i], 2 * x + 1, sty); + sty ++; + } + } + rirq_sort(); + + vic.color_border++; + + switch (oy) + { + case 46: + case 42: + readline(line, lpos); + lpos++; + if (lpos == 28) + lpos = 0; + break; + case 45: + expandline(line + 0, sty - 6 - 128, 0); + break; + case 44: + expandline(line + 6, sty - 4 - 128, 0); + break; + case 43: + expandline(line + 12, sty - 2 - 128, 0); + break; + + case 41: + expandline(line + 0, sty - 6 - 128, 12); + break; + case 40: + expandline(line + 6, sty - 4 - 128, 12); + break; + case 39: + expandline(line + 12, sty - 2 - 128, 12); + break; + } + vic.color_border--; + } + + return 0; +} diff --git a/samples/sprites/make.bat b/samples/sprites/make.bat index f3c3378..7f6747e 100644 --- a/samples/sprites/make.bat +++ b/samples/sprites/make.bat @@ -1,2 +1,3 @@ call ..\..\bin\oscar64 joycontrol.c call ..\..\bin\oscar64 multiplexer.c -n +call ..\..\bin\oscar64 creditroll.c -n