Add __export, __native and __interrupt storage class specifiers
This commit is contained in:
parent
94532fe038
commit
5c8b1c6daf
34
README.md
34
README.md
|
@ -43,7 +43,6 @@ There are still several open areas, but most targets have been reached. The cur
|
||||||
|
|
||||||
### Optimizing
|
### Optimizing
|
||||||
|
|
||||||
* Complex loop optimization
|
|
||||||
* Auto variables placed on fixed stack for known call sequence
|
* Auto variables placed on fixed stack for known call sequence
|
||||||
|
|
||||||
### Intermediate code generation
|
### 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.
|
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
|
## Inline Assembler
|
||||||
|
|
||||||
|
@ -263,15 +286,6 @@ The intermediate code generator assumes a large number of registers so the zero
|
||||||
* **0x43-0x52** caller saved registers
|
* **0x43-0x52** caller saved registers
|
||||||
* **0x53-0x8f** callee 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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <c64/vic.h>
|
#include <c64/vic.h>
|
||||||
#include <c64/cia.h>
|
#include <c64/cia.h>
|
||||||
#include <c64/asm6502.h>
|
#include <c64/asm6502.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
volatile char npos = 1, tpos = 0;
|
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_ab(ic->code + 4, ASM_CPX, 0xd012);
|
||||||
asm_rl(ic->code + 7, ASM_BCS, -5);
|
asm_rl(ic->code + 7, ASM_BCS, -5);
|
||||||
asm_ab(ic->code + 9, ASM_STY, 0x0000);
|
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)
|
if (size == 1)
|
||||||
{
|
{
|
||||||
asm_np(ic->code + 12, ASM_RTS);
|
asm_np(ic->code + 12, ASM_RTS);
|
||||||
//ic->code[12] = 0x60; // rts
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asm_ab(ic->code + 12, ASM_STA, 0x0000);
|
asm_ab(ic->code + 12, ASM_STA, 0x0000);
|
||||||
// ic->code[12] = 0x8d; // sty
|
|
||||||
|
|
||||||
byte p = 15;
|
byte p = 15;
|
||||||
for(byte i=2; i<size; i++)
|
for(byte i=2; i<size; i++)
|
||||||
{
|
{
|
||||||
p += asm_im(ic->code + p, ASM_LDA, 0x00);
|
p += asm_im(ic->code + p, ASM_LDA, 0x00);
|
||||||
p += asm_ab(ic->code + p, ASM_STA, 0x0000);
|
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);
|
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)
|
#pragma native(rirq_build)
|
||||||
|
|
||||||
void rirq_set(byte n, byte row, RIRQCode * write)
|
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;
|
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 irqai[16] = {
|
||||||
static const byte irqdi[6] = {RIRQ_DATA_0, RIRQ_DATA_1, RIRQ_DATA_2, RIRQ_DATA_3, RIRQ_DATA_4};
|
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)
|
void rirq_addr(RIRQCode * ic, byte n, void * addr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,40 @@ enum RIRQCodeIndex
|
||||||
RIRQ_DATA_4 = 26,
|
RIRQ_DATA_4 = 26,
|
||||||
RIRQ_ADDR_4 = 28,
|
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
|
// One raster interrupt operation, handles up to five writes
|
||||||
|
@ -34,9 +67,12 @@ typedef struct RIRQCode
|
||||||
byte code[RIRQ_SIZE];
|
byte code[RIRQ_SIZE];
|
||||||
} RIRQCode;
|
} 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);
|
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
|
// Add a write command to a raster IRQ
|
||||||
inline void rirq_write(RIRQCode * ic, byte n, void * addr, byte data);
|
inline void rirq_write(RIRQCode * ic, byte n, void * addr, byte data);
|
||||||
|
|
||||||
|
|
|
@ -66,14 +66,16 @@ static const uint32 DTF_FASTCALL = 0x00004000;
|
||||||
static const uint32 DTF_INLINE = 0x00008000;
|
static const uint32 DTF_INLINE = 0x00008000;
|
||||||
static const uint32 DTF_ANALYZED = 0x00010000;
|
static const uint32 DTF_ANALYZED = 0x00010000;
|
||||||
static const uint32 DTF_REQUEST_INLINE = 0x00020000;
|
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_VARIABLE = 0x00100000;
|
||||||
static const uint32 DTF_FUNC_ASSEMBLER = 0x00080000;
|
static const uint32 DTF_FUNC_ASSEMBLER = 0x00200000;
|
||||||
static const uint32 DTF_FUNC_RECURSIVE = 0x00100000;
|
static const uint32 DTF_FUNC_RECURSIVE = 0x00400000;
|
||||||
static const uint32 DTF_FUNC_ANALYZING = 0x00200000;
|
static const uint32 DTF_FUNC_ANALYZING = 0x00800000;
|
||||||
static const uint32 DTF_FUNC_CONSTEXPR = 0x00400000;
|
static const uint32 DTF_FUNC_CONSTEXPR = 0x01000000;
|
||||||
|
|
||||||
static const uint32 DTF_VAR_ALIASING = 0x00800000;
|
static const uint32 DTF_VAR_ALIASING = 0x02000000;
|
||||||
|
|
||||||
|
|
||||||
class Declaration;
|
class Declaration;
|
||||||
|
|
|
@ -54,6 +54,7 @@ enum ErrorID
|
||||||
ERRR_PREPROCESSOR,
|
ERRR_PREPROCESSOR,
|
||||||
ERRR_INVALID_CASE,
|
ERRR_INVALID_CASE,
|
||||||
ERRR_INSUFFICIENT_MEMORY,
|
ERRR_INSUFFICIENT_MEMORY,
|
||||||
|
ERRR_INTERRUPT_TO_COMPLEX,
|
||||||
|
|
||||||
EERR_INVALID_PREPROCESSOR,
|
EERR_INVALID_PREPROCESSOR,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8022,7 +8022,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
|
||||||
mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
|
mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
|
||||||
mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod),
|
mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod),
|
||||||
mIdent(ident), mLinkerObject(linkerObject),
|
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();
|
mID = mModule->mProcedures.Size();
|
||||||
mModule->mProcedures.Push(this);
|
mModule->mProcedures.Push(this);
|
||||||
|
@ -8729,6 +8729,8 @@ void InterCodeProcedure::Close(void)
|
||||||
BuildLoopPrefix();
|
BuildLoopPrefix();
|
||||||
DisassembleDebug("added dominators");
|
DisassembleDebug("added dominators");
|
||||||
|
|
||||||
|
BuildDataFlowSets();
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet);
|
mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet);
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ public:
|
||||||
GrowingTypeArray mTemporaries;
|
GrowingTypeArray mTemporaries;
|
||||||
GrowingIntArray mTempOffset, mTempSizes;
|
GrowingIntArray mTempOffset, mTempSizes;
|
||||||
int mTempSize, mCommonFrameSize, mCallerSavedTemps;
|
int mTempSize, mCommonFrameSize, mCallerSavedTemps;
|
||||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure;
|
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure, mInterrupt;
|
||||||
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
||||||
|
|
||||||
InterCodeModule * mModule;
|
InterCodeModule * mModule;
|
||||||
|
|
|
@ -3363,6 +3363,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
|
||||||
if (dec->mFlags & DTF_NATIVE)
|
if (dec->mFlags & DTF_NATIVE)
|
||||||
proc->mNativeProcedure = true;
|
proc->mNativeProcedure = true;
|
||||||
|
|
||||||
|
if (dec->mFlags & DTF_INTERRUPT)
|
||||||
|
proc->mInterrupt = true;
|
||||||
|
|
||||||
if (dec->mBase->mFlags & DTF_FASTCALL)
|
if (dec->mBase->mFlags & DTF_FASTCALL)
|
||||||
{
|
{
|
||||||
proc->mFastCallProcedure = true;
|
proc->mFastCallProcedure = true;
|
||||||
|
|
|
@ -33,6 +33,34 @@ enum LinkerSectionType
|
||||||
LST_STACK
|
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 LinkerObject;
|
||||||
class LinkerSection;
|
class LinkerSection;
|
||||||
|
|
||||||
|
@ -110,6 +138,7 @@ public:
|
||||||
uint32 mFlags;
|
uint32 mFlags;
|
||||||
uint8 mTemporaries[16], mTempSizes[16];
|
uint8 mTemporaries[16], mTempSizes[16];
|
||||||
int mNumTemporaries;
|
int mNumTemporaries;
|
||||||
|
ZeroPageSet mZeroPageSet;
|
||||||
|
|
||||||
LinkerObject(void);
|
LinkerObject(void);
|
||||||
~LinkerObject(void);
|
~LinkerObject(void);
|
||||||
|
|
|
@ -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)
|
void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used, NumberSet &modified, NumberSet& pairs)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
|
@ -8451,14 +8495,28 @@ void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used, NumberSet &modi
|
||||||
pairs += mIns[i].mAddress;
|
pairs += mIns[i].mAddress;
|
||||||
break;
|
break;
|
||||||
case ASMIM_ABSOLUTE:
|
case ASMIM_ABSOLUTE:
|
||||||
if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject)
|
if (mIns[i].mType == ASMIT_JSR)
|
||||||
{
|
{
|
||||||
LinkerObject* lo = mIns[i].mLinkerObject;
|
if (mIns[i].mFlags & NCIF_RUNTIME)
|
||||||
|
|
||||||
for (int i = 0; i < lo->mNumTemporaries; i++)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < lo->mTempSizes[i]; j++)
|
for (int j = 0; j < 4; j++)
|
||||||
used += lo->mTemporaries[i] + 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;
|
break;
|
||||||
|
@ -13728,7 +13786,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
{
|
{
|
||||||
int yoffset = mIns[i + 0].mAddress;
|
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 + 3].mType = ASMIT_NOP; mIns[apos + 3].mMode = ASMIM_IMPLIED;
|
||||||
mIns[apos + 6].mType = ASMIT_NOP; mIns[apos + 6].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)
|
if (mIns[i + 2].mAddress == 2)
|
||||||
mIns[i + 2].mType = ASMIT_INX;
|
mIns[i + 2].mType = ASMIT_INX;
|
||||||
else
|
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;
|
mIns[i + 3].mType = ASMIT_STX;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14083,7 +14142,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
if (mIns[i + 2].mAddress == 2)
|
if (mIns[i + 2].mAddress == 2)
|
||||||
mIns[i + 2].mType = ASMIT_DEX;
|
mIns[i + 2].mType = ASMIT_DEX;
|
||||||
else
|
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;
|
mIns[i + 3].mType = ASMIT_STX;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14099,7 +14159,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
if (mIns[i + 2].mAddress == 2)
|
if (mIns[i + 2].mAddress == 2)
|
||||||
mIns[i + 2].mType = ASMIT_INY;
|
mIns[i + 2].mType = ASMIT_INY;
|
||||||
else
|
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;
|
mIns[i + 3].mType = ASMIT_STY;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -14115,7 +14176,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
||||||
if (mIns[i + 2].mAddress == 2)
|
if (mIns[i + 2].mAddress == 2)
|
||||||
mIns[i + 2].mType = ASMIT_DEY;
|
mIns[i + 2].mType = ASMIT_DEY;
|
||||||
else
|
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;
|
mIns[i + 3].mType = ASMIT_STY;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
@ -15054,163 +15116,224 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
bool ignoreExpandCommonFrame = false;
|
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));
|
if (zpLocal[i])
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, i));
|
||||||
if (tempSave == 1)
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA));
|
||||||
{
|
}
|
||||||
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));
|
|
||||||
|
|
||||||
}
|
for (int i = 255; i >= 2; i--)
|
||||||
else if (commonFrameSize > 0)
|
{
|
||||||
{
|
if (zpLocal[i])
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, tempSave - 1));
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE_X, BC_REG_TMP_SAVED));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_PLA));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i));
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
if (mNoFrame)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
if (mStackExpand > 0)
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
{
|
||||||
|
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));
|
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_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));
|
if (mNoFrame)
|
||||||
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));
|
if (mStackExpand > 0)
|
||||||
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 (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
|
else
|
||||||
{
|
{
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCS, ASMIM_RELATIVE, 2));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
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)
|
if (tempSave)
|
||||||
{
|
{
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, commonFrameSize + tempSave - 1));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
||||||
if (tempSave == 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 (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_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
||||||
else if (commonFrameSize > 0)
|
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_DEY, ASMIM_IMPLIED));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
|
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_CLC, ASMIM_IMPLIED));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
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_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BCC, ASMIM_RELATIVE, 2));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, 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));
|
||||||
}
|
|
||||||
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));
|
|
||||||
|
|
||||||
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));
|
ZeroPageSet zpLocal, zpGlobal;
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
ResetVisited();
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, mStackExpand & 0xff));
|
mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal);
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
zpLocal |= zpGlobal;
|
||||||
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));
|
|
||||||
|
|
||||||
|
proc->mLinkerObject->mZeroPageSet = zpLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
||||||
|
|
|
@ -243,6 +243,7 @@ public:
|
||||||
void BuildEntryDataSet(const NativeRegisterDataSet& set);
|
void BuildEntryDataSet(const NativeRegisterDataSet& set);
|
||||||
bool ApplyEntryDataSet(void);
|
bool ApplyEntryDataSet(void);
|
||||||
|
|
||||||
|
void CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global);
|
||||||
void CollectZeroPageUsage(NumberSet& used, NumberSet& modified, NumberSet& pairs);
|
void CollectZeroPageUsage(NumberSet& used, NumberSet& modified, NumberSet& pairs);
|
||||||
void FindZeroPageAlias(const NumberSet& statics, NumberSet& invalid, uint8* alias, int accu);
|
void FindZeroPageAlias(const NumberSet& statics, NumberSet& invalid, uint8* alias, int accu);
|
||||||
bool RemapZeroPage(const uint8* remap);
|
bool RemapZeroPage(const uint8* remap);
|
||||||
|
|
|
@ -376,10 +376,21 @@ Declaration* Parser::ParsePostfixDeclaration(void)
|
||||||
Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
|
Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
|
||||||
ndec->mSize = 2;
|
ndec->mSize = 2;
|
||||||
ndec->mFlags |= DTF_DEFINED;
|
ndec->mFlags |= DTF_DEFINED;
|
||||||
if (mScanner->mToken == TK_CONST)
|
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
ndec->mFlags |= DTF_CONST;
|
if (mScanner->mToken == TK_CONST)
|
||||||
mScanner->NextToken();
|
{
|
||||||
|
ndec->mFlags |= DTF_CONST;
|
||||||
|
mScanner->NextToken();
|
||||||
|
}
|
||||||
|
else if (mScanner->mToken == TK_VOLATILE)
|
||||||
|
{
|
||||||
|
ndec->mFlags |= DTF_VOLATILE;
|
||||||
|
mScanner->NextToken();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Declaration* dec = ParsePostfixDeclaration();
|
Declaration* dec = ParsePostfixDeclaration();
|
||||||
|
@ -605,6 +616,7 @@ Declaration * Parser::CopyConstantInitializer(int offset, Declaration* dtype, Ex
|
||||||
ndec->mValue = exp;
|
ndec->mValue = exp;
|
||||||
ndec->mBase = dtype;
|
ndec->mBase = dtype;
|
||||||
dec = ndec;
|
dec = ndec;
|
||||||
|
dec->mOffset = offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mErrors->Error(exp->mLocation, EERR_CONSTANT_INITIALIZER, "Incompatible constant initializer");
|
mErrors->Error(exp->mLocation, EERR_CONSTANT_INITIALIZER, "Incompatible constant initializer");
|
||||||
|
@ -886,22 +898,45 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mScanner->mToken == TK_STATIC)
|
for (;;)
|
||||||
{
|
{
|
||||||
storageFlags |= DTF_STATIC;
|
if (mScanner->mToken == TK_STATIC)
|
||||||
mScanner->NextToken();
|
{
|
||||||
}
|
storageFlags |= DTF_STATIC;
|
||||||
|
mScanner->NextToken();
|
||||||
if (mScanner->mToken == TK_EXTERN)
|
}
|
||||||
{
|
else if (mScanner->mToken == TK_EXTERN)
|
||||||
storageFlags |= DTF_EXTERN;
|
{
|
||||||
mScanner->NextToken();
|
storageFlags |= DTF_EXTERN;
|
||||||
}
|
mScanner->NextToken();
|
||||||
|
}
|
||||||
if (mScanner->mToken == TK_INLINE)
|
else if (mScanner->mToken == TK_INLINE)
|
||||||
{
|
{
|
||||||
storageFlags |= DTF_REQUEST_INLINE;
|
storageFlags |= DTF_REQUEST_INLINE;
|
||||||
mScanner->NextToken();
|
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->mSection = mDataSection;
|
||||||
ndec->mSize = ndec->mBase->mSize;
|
ndec->mSize = ndec->mBase->mSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (storageFlags & DTF_EXPORT)
|
||||||
|
{
|
||||||
|
mCompilationUnits->AddReferenced(ndec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mScanner->mToken == TK_COMMA)
|
if (mScanner->mToken == TK_COMMA)
|
||||||
|
|
|
@ -50,6 +50,10 @@ const char* TokenNames[] =
|
||||||
"'__assume'",
|
"'__assume'",
|
||||||
|
|
||||||
"__asm",
|
"__asm",
|
||||||
|
"__interrupt",
|
||||||
|
"__native",
|
||||||
|
"__fastcall",
|
||||||
|
"__export",
|
||||||
|
|
||||||
"number",
|
"number",
|
||||||
"char",
|
"char",
|
||||||
|
@ -1257,6 +1261,14 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_ASM;
|
mToken = TK_ASM;
|
||||||
else if (!strcmp(tkident, "__assume"))
|
else if (!strcmp(tkident, "__assume"))
|
||||||
mToken = TK_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
|
else
|
||||||
{
|
{
|
||||||
mToken = TK_IDENT;
|
mToken = TK_IDENT;
|
||||||
|
|
|
@ -48,6 +48,10 @@ enum Token
|
||||||
TK_ASSUME,
|
TK_ASSUME,
|
||||||
|
|
||||||
TK_ASM,
|
TK_ASM,
|
||||||
|
TK_INTERRUPT,
|
||||||
|
TK_NATIVE,
|
||||||
|
TK_FASTCALL,
|
||||||
|
TK_EXPORT,
|
||||||
|
|
||||||
TK_NUMBER,
|
TK_NUMBER,
|
||||||
TK_CHARACTER,
|
TK_CHARACTER,
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.2.67");
|
strcpy(strProductVersion, "1.2.68");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,2,67,0
|
FILEVERSION 1,2,68,0
|
||||||
PRODUCTVERSION 1,2,67,0
|
PRODUCTVERSION 1,2,68,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,12 +43,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "oscar64"
|
VALUE "CompanyName", "oscar64"
|
||||||
VALUE "FileDescription", "oscar64 compiler"
|
VALUE "FileDescription", "oscar64 compiler"
|
||||||
VALUE "FileVersion", "1.2.67.0"
|
VALUE "FileVersion", "1.2.68.0"
|
||||||
VALUE "InternalName", "oscar64.exe"
|
VALUE "InternalName", "oscar64.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "oscar64.exe"
|
VALUE "OriginalFilename", "oscar64.exe"
|
||||||
VALUE "ProductName", "oscar64"
|
VALUE "ProductName", "oscar64"
|
||||||
VALUE "ProductVersion", "1.2.67.0"
|
VALUE "ProductVersion", "1.2.68.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Binary file not shown.
|
@ -1,3 +1,4 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
../../bin/oscar64 joycontrol.c
|
../../bin/oscar64 joycontrol.c
|
||||||
../../bin/oscar64 multiplexer.c -n
|
../../bin/oscar64 multiplexer.c -n
|
||||||
|
../../bin/oscar64 creditroll.c -n
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
call ..\..\bin\oscar64 joycontrol.c
|
call ..\..\bin\oscar64 joycontrol.c
|
||||||
call ..\..\bin\oscar64 multiplexer.c -n
|
call ..\..\bin\oscar64 multiplexer.c -n
|
||||||
|
call ..\..\bin\oscar64 creditroll.c -n
|
||||||
|
|
Loading…
Reference in New Issue