Add __export, __native and __interrupt storage class specifiers

This commit is contained in:
drmortalwombat 2022-01-26 21:48:19 +01:00
parent 94532fe038
commit 5c8b1c6daf
20 changed files with 714 additions and 235 deletions

View File

@ -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)

View File

@ -3,6 +3,7 @@
#include <c64/vic.h>
#include <c64/cia.h>
#include <c64/asm6502.h>
#include <stdlib.h>
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; i<size; i++)
{
p += asm_im(ic->code + 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)
{

View File

@ -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);

View File

@ -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;

View File

@ -54,6 +54,7 @@ enum ErrorID
ERRR_PREPROCESSOR,
ERRR_INVALID_CASE,
ERRR_INSUFFICIENT_MEMORY,
ERRR_INTERRUPT_TO_COMPLEX,
EERR_INVALID_PREPROCESSOR,
};

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -48,6 +48,10 @@ enum Token
TK_ASSUME,
TK_ASM,
TK_INTERRUPT,
TK_NATIVE,
TK_FASTCALL,
TK_EXPORT,
TK_NUMBER,
TK_CHARACTER,

View File

@ -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);

View File

@ -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"

Binary file not shown.

View File

@ -1,3 +1,4 @@
#!/bin/sh
../../bin/oscar64 joycontrol.c
../../bin/oscar64 multiplexer.c -n
../../bin/oscar64 creditroll.c -n

View File

@ -0,0 +1,233 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <c64/sprites.h>
#include <stdlib.h>
#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;
}

View File

@ -1,2 +1,3 @@
call ..\..\bin\oscar64 joycontrol.c
call ..\..\bin\oscar64 multiplexer.c -n
call ..\..\bin\oscar64 creditroll.c -n