From fcedf69affcc24f072ff6fe37237b565c0ee1826 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 8 Sep 2021 22:04:01 +0200 Subject: [PATCH] More native code compiler additions --- autotest/autotest.bat | 3 + autotest/testint16cmp.c | 147 +++++ include/crt.c | 121 +++- oscar64/ByteCodeGenerator.cpp | 20 + oscar64/ByteCodeGenerator.h | 7 +- oscar64/CompilationUnits.cpp | 1 + oscar64/CompilationUnits.h | 2 + oscar64/Compiler.cpp | 47 ++ oscar64/MachineTypes.h | 1 + oscar64/NativeCodeGenerator.cpp | 1072 ++++++++++++++++++++++++------- oscar64/NativeCodeGenerator.h | 12 +- oscar64/Parser.cpp | 50 ++ 12 files changed, 1205 insertions(+), 278 deletions(-) create mode 100644 autotest/testint16cmp.c diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 6dee0ce..874bcea 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -36,6 +36,9 @@ if %errorlevel% neq 0 goto :error ..\release\oscar64 -i=../include -rt=../include/crt.c -e array2stringinittest.c if %errorlevel% neq 0 goto :error +..\release\oscar64 -i=../include -rt=../include/crt.c -e testint16cmp.c +if %errorlevel% neq 0 goto :error + exit /b 0 :error echo Failed with error #%errorlevel%. diff --git a/autotest/testint16cmp.c b/autotest/testint16cmp.c new file mode 100644 index 0000000..096c455 --- /dev/null +++ b/autotest/testint16cmp.c @@ -0,0 +1,147 @@ +#include +#include + +bool beq(int a, int b) +{ + return a == b; +} + +bool blt(int a, int b) +{ + return a < b; +} + +bool bgt(int a, int b) +{ + return a > b; +} + +bool ble(int a, int b) +{ + return a <= b; +} + +bool bge(int a, int b) +{ + return a >= b; +} + +bool neq(int a, int b) +{ + return a == b; +} + +#pragma native(neq) + +bool nlt(int a, int b) +{ + return a < b; +} + +#pragma native(nlt) + +bool ngt(int a, int b) +{ + return a > b; +} + +#pragma native(ngt) + +bool nle(int a, int b) +{ + return a <= b; +} + +#pragma native(nlt) + +bool nge(int a, int b) +{ + return a >= b; +} + +#pragma native(ngt) + +void cmp(int a, int b) +{ + bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = blt(a, b), bgef = bgt(a, b); + bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nlt(a, b), ngef = ngt(a, b); + +// printf("BYTE %d, %d : EQ %d LT %d GT %d\r", a, b, beqf, bltf, bgtf); +// printf("NATIVE %d, %d : EQ %d LT %d GT %d\r", a, b, neqf, nltf, ngtf); + + assert(beqf == neqf); + assert(bltf == nltf); + assert(bgtf == ngtf); + assert(blef == nlef); + assert(bgef == ngef); +} + +int main(void) +{ + cmp( 0, 1); + cmp( 0, -1); + cmp( 1, 0); + cmp(-1, 0); + + cmp(1, 1); + cmp(1, 2); + cmp(2, 1); + + cmp(-1, -1); + cmp(-1, -2); + cmp(-2, -1); + + cmp( 1, -1); + cmp( 1, -2); + cmp( 2, -1); + + cmp(-1, 1); + cmp(-1, 2); + cmp(-2, 1); + + + cmp( 0, 10000); + cmp( 0, -10000); + cmp( 10000, 0); + cmp(-10000, 0); + + cmp(10000, 10000); + cmp(10000, 20000); + cmp(20000, 10000); + + cmp(-10000, -10000); + cmp(-10000, -20000); + cmp(-20000, -10000); + + cmp( 10000, -10000); + cmp( 10000, -20000); + cmp( 20000, -10000); + + cmp(-10000, 10000); + cmp(-10000, 20000); + cmp(-20000, 10000); + + cmp( 0, 1024); + cmp( 0, -1024); + cmp( 1024, 0); + cmp(-1024, 0); + + cmp(1024, 1024); + cmp(1024, 1025); + cmp(1025, 1024); + + cmp(-1024, -1024); + cmp(-1024, -1025); + cmp(-1025, -1024); + + cmp( 1024, -1024); + cmp( 1024, -1025); + cmp( 1025, -1024); + + cmp(-1024, 1024); + cmp(-1024, 1025); + cmp(-1025, 1024); + + return 0; + +} diff --git a/include/crt.c b/include/crt.c index b46dee4..f42c02d 100644 --- a/include/crt.c +++ b/include/crt.c @@ -38,7 +38,31 @@ incip: #pragma startup(startup) -// divide accu by tmp +__asm negaccu +{ + sec + lda #0 + sbc accu + sta accu + lda #0 + sbc accu + 1 + sta accu + 1 + rts +} + +__asm negtmp +{ + sec + lda #0 + sbc tmp + sta tmp + lda #0 + sbc tmp + 1 + sta tmp + 1 + rts +} + +// divide accu by tmp result in accu, remainder in tmp + 2 __asm divmod { @@ -68,6 +92,77 @@ W1: dey ldy tmpy rts } + +// Multiply accu by tmp result in tmp + 2 + +__asm mul16 +{ + lda #0 + sta tmp + 2 + sta tmp + 3 + + ldx #16 +L1: lsr tmp + 1 + ror tmp + bcc W1 + clc + lda tmp + 2 + adc accu + sta tmp + 2 + lda tmp + 3 + adc accu + 1 + sta tmp + 3 +W1: asl accu + rol accu + 1 + dex + bne L1 + rts +} + +__asm divs16 +{ + bit accu + 1 + bpl L1 + jsr negaccu + bit tmp + 1 + bpl L2 + jsr negtmp +L3: jmp divmod +L1: bit tmp + 1 + bpl L3 + jsr negtmp +L2: jsr divmod + jmp negaccu +} + +__asm mods16 +{ + bit accu + 1 + bpl L1 + jsr negaccu + bit tmp + 1 + bpl L2 + jsr negtmp +L3: jmp divmod +L1: bit tmp + 1 + bpl L3 + jsr negtmp +L2: jsr divmod + sec + lda #0 + sbc tmp + 2 + sta tmp + 2 + lda #0 + sbc tmp + 3 + sta tmp + 3 + rts +} + +#pragma runtime(mul16, mul16); +#pragma runtime(divu16, divmod); +#pragma runtime(modu16, divmod); +#pragma runtime(divs16, divs16); +#pragma runtime(mods16, mods16); /* !align 255, 0 @@ -983,30 +1078,6 @@ __asm inp_binop_modr_u16 #pragma bytecode(BC_BINOP_MODR_U16, inp_binop_modr_u16) -__asm negaccu -{ - sec - lda #0 - sbc accu - sta accu - lda #0 - sbc accu + 1 - sta accu + 1 - rts -} - -__asm negtmp -{ - sec - lda #0 - sbc tmp - sta tmp - lda #0 - sbc tmp + 1 - sta tmp + 1 - rts -} - __asm inp_binop_divr_s16 { lda (ip), y diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 9caf047..ffde8d2 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -187,6 +187,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutWord(0); } @@ -233,6 +234,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutWord(0); } @@ -253,6 +255,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutWord(0); } @@ -410,6 +413,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = 0; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutWord(0); @@ -1484,6 +1488,22 @@ void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInst bins.mFunction = ins.mMemory == IM_PROCEDURE; mIns.Push(bins); } + + if (ins.mTTemp >= 0) + { + if (ins.mTType == IT_FLOAT) + { + ByteCodeInstruction bins(BC_STORE_REG_32); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + mIns.Push(bins); + } + else + { + ByteCodeInstruction bins(BC_STORE_REG_16); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + mIns.Push(bins); + } + } } ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins) diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index 165db05..51997d0 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -143,9 +143,10 @@ class ByteCodeGenerator; class ByteCodeRelocation { public: - uint16 mAddr; - bool mFunction, mLower, mUpper; - uint16 mIndex, mOffset; + uint16 mAddr; + bool mFunction, mLower, mUpper; + uint16 mIndex, mOffset; + const char * mRuntime; }; class ByteCodeBasicBlock; diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index c08ff52..983bb69 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -9,6 +9,7 @@ CompilationUnits::CompilationUnits(Errors * errors) mCompilationUnits = nullptr; mPendingUnits = nullptr; mScope = new DeclarationScope(nullptr); + mRuntimeScope = new DeclarationScope(nullptr); mStartup = nullptr; for (int i = 0; i < 128; i++) diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index 9f5c795..2cbc08b 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -24,6 +24,8 @@ public: Declaration* mStartup; Declaration* mByteCodes[128]; + DeclarationScope* mRuntimeScope; + bool AddUnit(Location & location, const char* name, const char * from); CompilationUnit* PendingUnit(void); protected: diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 6f31fbc..162404d 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -120,6 +120,45 @@ bool Compiler::GenerateCode(void) } } + // Compile used runtime functions + + for (int i = 0; i < mByteCodeGenerator->mRelocations.Size(); i++) + { + if (mByteCodeGenerator->mRelocations[i].mRuntime) + { + Declaration* bcdec = mCompilationUnits->mRuntimeScope->Lookup(Ident::Unique(mByteCodeGenerator->mRelocations[i].mRuntime)); + if (bcdec) + { + int index = -1, offset = 0; + if (bcdec->mType == DT_CONST_ASSEMBLER) + { + if (bcdec->mVarIndex < 0) + mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue); + index = bcdec->mVarIndex; + } + else if (bcdec->mType == DT_LABEL) + { + if (bcdec->mBase->mVarIndex < 0) + mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue); + index = bcdec->mBase->mVarIndex; + offset = bcdec->mInteger; + } + + assert(index > 0); + mInterCodeModule->UseGlobal(index); + + mByteCodeGenerator->mRelocations[i].mIndex = index; + mByteCodeGenerator->mRelocations[i].mOffset = offset; + } + else + { + mErrors->Error(loc, "Missing runtime code implementation", mByteCodeGenerator->mRelocations[i].mRuntime); + } + } + } + + // Compile used byte code functions + for (int i = 0; i < 128; i++) { if (mByteCodeGenerator->mByteCodeUsed[i]) @@ -152,8 +191,15 @@ bool Compiler::GenerateCode(void) rel.mUpper = true; rel.mIndex = index; rel.mOffset = offset; + rel.mRuntime = nullptr; mByteCodeGenerator->mRelocations.Push(rel); } + else + { + char n[10]; + sprintf_s(n, "%d", i); + mErrors->Error(loc, "Missing byte code implementation", n); + } } } @@ -177,6 +223,7 @@ bool Compiler::GenerateCode(void) rel.mUpper = ref.mUpper; rel.mIndex = ref.mIndex; rel.mOffset = ref.mOffset; + rel.mRuntime = nullptr; mByteCodeGenerator->mRelocations.Push(rel); } } diff --git a/oscar64/MachineTypes.h b/oscar64/MachineTypes.h index 13b1275..f172a76 100644 --- a/oscar64/MachineTypes.h +++ b/oscar64/MachineTypes.h @@ -7,6 +7,7 @@ typedef signed char int8; typedef signed short int16; typedef signed short int32; +static const uint8 BC_REG_WORK = 0x03; static const uint8 BC_REG_IP = 0x19; static const uint8 BC_REG_ACCU = 0x1b; static const uint8 BC_REG_ADDR = 0x1f; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 15b5c92..477ccc5 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -1,7 +1,11 @@ #include "NativeCodeGenerator.h" NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, int varIndex, bool lower, bool upper) - : mType(type), mMode(mode), mAddress(address), mVarIndex(varIndex), mLower(lower), mUpper(upper) + : mType(type), mMode(mode), mAddress(address), mVarIndex(varIndex), mLower(lower), mUpper(upper), mRuntime(nullptr) +{} + +NativeCodeInstruction::NativeCodeInstruction(const char* runtime) + : mType(ASMIT_JSR), mMode(ASMIM_ABSOLUTE), mAddress(0), mVarIndex(0), mLower(true), mUpper(true), mRuntime(runtime) {} @@ -15,6 +19,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) break; case ASMIM_ZERO_PAGE: case ASMIM_ZERO_PAGE_X: + case ASMIM_ZERO_PAGE_Y: case ASMIM_INDIRECT_X: case ASMIM_INDIRECT_Y: block->PutByte(uint8(mAddress)); @@ -29,6 +34,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) rl.mUpper = mUpper; rl.mIndex = mVarIndex; rl.mOffset = mAddress; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutByte(0); } @@ -41,7 +47,20 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) case ASMIM_INDIRECT: case ASMIM_ABSOLUTE_X: case ASMIM_ABSOLUTE_Y: - if (mVarIndex != - 1) + if (mRuntime) + { + ByteCodeRelocation rl; + rl.mAddr = block->mCode.Size(); + rl.mFunction = false; + rl.mLower = true; + rl.mUpper = true; + rl.mIndex = -1; + rl.mOffset = 0; + rl.mRuntime = mRuntime; + block->mRelocations.Push(rl); + block->PutWord(0); + } + else if (mVarIndex != - 1) { ByteCodeRelocation rl; rl.mAddr = block->mCode.Size(); @@ -50,6 +69,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) rl.mUpper = true; rl.mIndex = mVarIndex; rl.mOffset = mAddress; + rl.mRuntime = nullptr; block->mRelocations.Push(rl); block->PutWord(0); } @@ -118,6 +138,7 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, int offset) rl.mUpper = true; rl.mIndex = proc->mIndex; rl.mOffset = mOffset + mCode.Size() + offset - 1; + rl.mRuntime = nullptr; mRelocations.Push(rl); PutWord(0); @@ -145,6 +166,7 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, AsmInsType code, rl.mUpper = true; rl.mIndex = proc->mIndex; rl.mOffset = mOffset + mCode.Size() + offset - 3; + rl.mRuntime = nullptr; mRelocations.Push(rl); PutWord(0); @@ -571,7 +593,7 @@ void NativeCodeBasicBlock::LoadStoreValue(InterCodeProcedure* proc, const InterI } } -void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstruction& ins) +void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterInstruction& ins, int reg, const NativeCodeInstruction* ainsl, const NativeCodeInstruction* ainsh) { if (ins.mTType == IT_FLOAT) { @@ -583,14 +605,20 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru if (ins.mMemory == IM_GLOBAL) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0] + 1, ins.mVarIndex)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_ABSOLUTE) { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { @@ -602,10 +630,12 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } else @@ -614,10 +644,12 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru { mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } } @@ -627,6 +659,9 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru { if (ins.mOperandSize == 1) { + if (ins.mTType == IT_SIGNED) + mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, 0)); + if (ins.mMemory == IM_GLOBAL) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex)); @@ -647,32 +682,40 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); } - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); if (ins.mTType == IT_SIGNED) { - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED)); } else { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); } - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mOperandSize == 2) { if (ins.mMemory == IM_GLOBAL) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0] + 1, ins.mVarIndex)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_ABSOLUTE) { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { @@ -684,10 +727,12 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } } @@ -699,182 +744,568 @@ void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstru { mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); if (ins.mTType == IT_SIGNED) { - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1)); + mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED)); } else { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); } - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mOperandSize == 2) { mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + if (ainsl) mIns.Push(*ainsl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + if (ainsh) mIns.Push(*ainsh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } } } } -void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins) +void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstruction& ins) { + LoadValueToReg(proc, ins, BC_REG_TMP + proc->mTempOffset[ins.mTTemp], nullptr, nullptr); +} + +void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction * sins1, const InterInstruction * sins0) +{ + int treg = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + switch (ins.mOperator) { case IA_ADD: + case IA_OR: + case IA_AND: + case IA_XOR: { - if (ins.mSTemp[0] < 0 && ins.mSIntConst[0] == 1 && ins.mSTemp[1] == ins.mTTemp || - ins.mSTemp[1] < 0 && ins.mSIntConst[1] == 1 && ins.mSTemp[0] == ins.mTTemp) + if (ins.mOperator == IA_ADD && ( + ins.mSTemp[0] < 0 && ins.mSIntConst[0] == 1 && !sins1 && ins.mSTemp[1] == ins.mTTemp || + ins.mSTemp[1] < 0 && ins.mSIntConst[1] == 1 && !sins0 && ins.mSTemp[0] == ins.mTTemp)) { - mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, 2)); - mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg + 1)); } else { - mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + NativeCodeInstruction insl, insh; + + AsmInsType atype; + switch (ins.mOperator) + { + case IA_ADD: + atype = ASMIT_ADC; + mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + break; + case IA_OR: + atype = ASMIT_ORA; + break; + case IA_AND: + atype = ASMIT_AND; + break; + case IA_XOR: + atype = ASMIT_EOR; + break; + } + if (ins.mSTemp[1] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + { + insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff); + insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff); + if (sins0) + LoadValueToReg(proc, *sins0, treg, &insl, &insh); + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(insl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (ins.mSTemp[0] < 0) + { + insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff); + insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff); + if (sins1) + LoadValueToReg(proc, *sins1, treg, &insl, &insh); + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(insl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } else - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); - if (ins.mSTemp[1] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + { + if (sins1 && sins0) + { + insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg); + insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg + 1); + + LoadValueToReg(proc, *sins1, treg, nullptr, nullptr); + LoadValueToReg(proc, *sins0, treg, &insl, &insh); + } + else if (sins1) + { + insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]); + insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1); + + LoadValueToReg(proc, *sins1, treg, &insl, &insh); + } + else if (sins0) + { + insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]); + insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1); + + LoadValueToReg(proc, *sins0, treg, &insl, &insh); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } } } break; case IA_SUB: { + NativeCodeInstruction insl, insh; + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); - if (ins.mSTemp[1] < 0) + if (ins.mSTemp[0] < 0) + { + insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff); + insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff); + if (sins1) + LoadValueToReg(proc, *sins1, treg, &insl, &insh); + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(insl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (ins.mSTemp[1] < 0) + { + if (sins0) + { + insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg); + insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + + LoadValueToReg(proc, *sins0, treg, &insl, &insh); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else + { + if (sins0) + { + insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg); + insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1); + + LoadValueToReg(proc, *sins0, treg, nullptr, nullptr); + } + else + { + insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]); + insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1); + } + + if (sins1) + { + LoadValueToReg(proc, *sins1, treg, &insl, &insh); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(insl); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(insh); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + } break; + case IA_MUL: + case IA_DIVS: + case IA_MODS: + case IA_DIVU: + case IA_MODU: + { + if (sins1) + LoadValueToReg(proc, *sins1, BC_REG_ACCU, nullptr, nullptr); + else if (ins.mSTemp[1] < 0) + { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); - if (ins.mSTemp[1] < 0) + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + + if (sins0) + LoadValueToReg(proc, *sins0, BC_REG_WORK, nullptr, nullptr); + else if (ins.mSTemp[0] < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1)); + } else - mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1)); + } + + int reg = BC_REG_ACCU; + switch (ins.mOperator) + { + case IA_MUL: + mIns.Push(NativeCodeInstruction("mul16")); + reg = BC_REG_WORK + 2; + break; + case IA_DIVS: + mIns.Push(NativeCodeInstruction("divs16")); + break; + case IA_MODS: + mIns.Push(NativeCodeInstruction("mods16")); + reg = BC_REG_WORK + 2; + break; + case IA_DIVU: + mIns.Push(NativeCodeInstruction("divu16")); + break; + case IA_MODU: + mIns.Push(NativeCodeInstruction("modu16")); + reg = BC_REG_WORK + 2; + break; + } + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); } break; case IA_SHL: { if (ins.mSTemp[0] < 0) { - if (ins.mSIntConst[0] == 1) + int shift = ins.mSIntConst[0] & 15; + if (shift == 0) { - if (ins.mSTemp[1] == ins.mTTemp) + if (ins.mSTemp[1] != ins.mTTemp) { - mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } - else + } + else if (shift == 1) + { + if (ins.mSTemp[1] != ins.mTTemp) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + } + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + for (int i = 1; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + } + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } } break; + case IA_SAR: + { + if (sins1) LoadValueToReg(proc, *sins1, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]], nullptr, nullptr); + if (sins0) LoadValueToReg(proc, *sins0, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]], nullptr, nullptr); + + if (ins.mSTemp[0] < 0) + { + int shift = ins.mSIntConst[0] & 15; + if (shift == 0) + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } + + for (int i = 0; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (ins.mSTemp[1] < 0 && ins.mSIntConst[1] < 0x100) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 4)); + + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -4)); + + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + if (ins.mSTemp[1] < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + } + else if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 2 + 1 + 2)); + + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 2 + 1 + 2))); + + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } break; + } } void NativeCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins) { + int treg = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + if (ins.mTType == IT_FLOAT) + { + } + else + { + switch (ins.mOperator) + { + case IA_NEG: + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + break; + + case IA_NOT: + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + break; + } + } } void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump) { - switch (ins.mOperator) + InterOperator op = ins.mOperator; + + NativeCodeBasicBlock* eblock = new NativeCodeBasicBlock(); + eblock->mNoFrame = mNoFrame; + eblock->mIndex = 1000; + + NativeCodeBasicBlock* nblock = new NativeCodeBasicBlock(); + nblock->mNoFrame = mNoFrame; + nblock->mIndex = 1000; + + int li = 1, ri = 0; + if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS) + { + li = 0; ri = 1; + } + + if (op >= IA_CMPGES && ins.mOperator <= IA_CMPLS) + { + if (ins.mSTemp[ri] >= 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[ri]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK)); + } + + if (ins.mSTemp[li] < 0) + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ((ins.mSIntConst[li] >> 8) & 0xff) ^ 0x80)); + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[li]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80)); + } + + if (ins.mSTemp[ri] < 0) + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ((ins.mSIntConst[ri] >> 8) & 0xff) ^ 0x80)); + else + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_WORK)); + } + else + { + if (ins.mSTemp[li] < 0) + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[li] >> 8) & 0xff)); + else + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[li]] + 1)); + if (ins.mSTemp[ri] < 0) + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins.mSIntConst[ri] >> 8) & 0xff)); + else + mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[ri]] + 1)); + } + + this->Close(eblock, nblock, ASMIT_BEQ); + + if (ins.mSTemp[li] < 0) + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[li] & 0xff)); + else + eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[li]])); + if (ins.mSTemp[ri] < 0) + eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ins.mSIntConst[ri] & 0xff)); + else + eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[ri]])); + + switch (op) { case IA_CMPEQ: - { - if (ins.mSTemp[1] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - - NativeCodeBasicBlock* tblock = new NativeCodeBasicBlock(); - tblock->mNoFrame = mNoFrame; - tblock->mIndex = 1000; - - this->Close(falseJump, tblock, ASMIT_BNE); - - if (ins.mSTemp[1] < 0) - tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); - else - tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); - if (ins.mSTemp[0] < 0) - tblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); - else - tblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); - - tblock->Close(falseJump, trueJump, ASMIT_BNE); - } break; + nblock->Close(falseJump, nullptr, ASMIT_JMP); + eblock->Close(trueJump, falseJump, ASMIT_BEQ); + break; case IA_CMPNE: - { - if (ins.mSTemp[1] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); - if (ins.mSTemp[0] < 0) - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); - else - mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + nblock->Close(trueJump, nullptr, ASMIT_JMP); + eblock->Close(falseJump, trueJump, ASMIT_BEQ); + break; + case IA_CMPLU: + case IA_CMPLS: + case IA_CMPGU: + case IA_CMPGS: + eblock->Close(nblock, nullptr, ASMIT_JMP); + nblock->Close(trueJump, falseJump, ASMIT_BCC); + break; + case IA_CMPLEU: + case IA_CMPLES: + case IA_CMPGEU: + case IA_CMPGES: + eblock->Close(nblock, nullptr, ASMIT_JMP); + nblock->Close(falseJump, trueJump, ASMIT_BCC); + break; - NativeCodeBasicBlock* tblock = new NativeCodeBasicBlock(); - tblock->mNoFrame = mNoFrame; - tblock->mIndex = 1000; - - this->Close(trueJump, tblock, ASMIT_BNE); - - if (ins.mSTemp[1] < 0) - tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); - else - tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); - if (ins.mSTemp[0] < 0) - tblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); - else - tblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); - - tblock->Close(trueJump, falseJump, ASMIT_BNE); - } break; } } @@ -901,125 +1332,6 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); } -void NativeCodeBasicBlock::Compile(InterCodeProcedure* iproc, NativeCodeProcedure* proc, InterCodeBasicBlock* sblock) -{ - mIndex = sblock->mIndex; - - int i = 0; - while (i < sblock->mInstructions.Size()) - { - const InterInstruction& ins = sblock->mInstructions[i]; - - switch (ins.mCode) - { - case IC_STORE: - StoreValue(iproc, ins); - break; - case IC_LOAD: - if (i + 1 < sblock->mInstructions.Size() && - sblock->mInstructions[i + 1].mCode == IC_STORE && - sblock->mInstructions[i + 1].mSTemp[0] == ins.mTTemp && - sblock->mInstructions[i + 1].mSFinal[0] && - sblock->mInstructions[i + 1].mOperandSize == 1) - { - LoadStoreValue(iproc, ins, sblock->mInstructions[i + 1]); - i++; - } - else - LoadValue(iproc, ins); - break; - case IC_COPY: -// CopyValue(iproc, ins); - break; - case IC_LOAD_TEMPORARY: - { - if (ins.mSTemp[0] != ins.mTTemp) - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp] + 1)); - } - } break; - case IC_BINARY_OPERATOR: - BinaryOperator(iproc, ins); - break; - case IC_UNARY_OPERATOR: - UnaryOperator(iproc, ins); - break; - case IC_CONVERSION_OPERATOR: -// NumericConversion(iproc, ins); - break; - case IC_LEA: - LoadEffectiveAddress(iproc, ins); - break; - case IC_CONSTANT: - LoadConstant(iproc, ins); - break; - case IC_CALL: -// CallFunction(iproc, ins); - break; - case IC_JSR: -// CallAssembler(iproc, ins); - break; - case IC_PUSH_FRAME: - { - } break; - case IC_POP_FRAME: - { - } break; - - case IC_RELATIONAL_OPERATOR: - if (sblock->mInstructions[i + 1].mCode == IC_BRANCH) - { - RelationalOperator(iproc, ins, proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump)); - return; - } - break; - - case IC_RETURN_VALUE: - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - - this->Close(proc->exitBlock, nullptr, ASMIT_JMP); - return; - } - - case IC_RETURN: - this->Close(proc->exitBlock, nullptr, ASMIT_JMP); - return; - - case IC_TYPECAST: - break; - - case IC_BRANCH: - if (ins.mSTemp[0] < 0) - { - if (ins.mSIntConst[0] == 0) - this->Close(proc->CompileBlock(iproc, sblock->mFalseJump), nullptr, ASMIT_JMP); - else - this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, ASMIT_JMP); - } - else - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); - - this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), ASMIT_BNE); - } - return; - - } - - i++; - } - - this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, ASMIT_JMP); -} - void NativeCodeBasicBlock::Assemble(void) { if (!mAssembled) @@ -1278,7 +1590,7 @@ NativeCodeBasicBlock::~NativeCodeBasicBlock(void) NativeCodeProcedure::NativeCodeProcedure(void) : mRelocations({ 0 }) { - + mTempBlocks = 1000; } NativeCodeProcedure::~NativeCodeProcedure(void) @@ -1288,24 +1600,95 @@ NativeCodeProcedure::~NativeCodeProcedure(void) void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure* proc) { - tblocks = new NativeCodeBasicBlock * [proc->mBlocks.Size()]; - for (int i = 0; i < proc->mBlocks.Size(); i++) + int nblocks = proc->mBlocks.Size(); + tblocks = new NativeCodeBasicBlock * [nblocks]; + for (int i = 0; i < nblocks; i++) tblocks[i] = nullptr; mIndex = proc->mID; - mNoFrame = true; + + int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0; + int stackExpand = tempSave + proc->mLocalSize + 2; + + mNoFrame = proc->mLocalSize == 0 && tempSave == 0; entryBlock = new NativeCodeBasicBlock(); entryBlock->mNoFrame = mNoFrame; - + entryBlock->mIndex = 0; + + if (!mNoFrame) + { + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, tempSave + 2)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + + if (tempSave) + { + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED - 1)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, - 6)); + } + + } + tblocks[0] = entryBlock; exitBlock = new NativeCodeBasicBlock(); exitBlock->mNoFrame = mNoFrame; + if (!mNoFrame) + { + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + + if (tempSave) + { + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -6)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED)); + } + + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + + } + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED)); - entryBlock->Compile(proc, this, proc->mBlocks[0]); + CompileInterBlock(proc, proc->mBlocks[0], entryBlock); entryBlock->Assemble(); int total, base; @@ -1331,6 +1714,15 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu } } +NativeCodeBasicBlock* NativeCodeProcedure::AllocateBlock(void) +{ + NativeCodeBasicBlock* block = new NativeCodeBasicBlock(); + block->mNoFrame = mNoFrame; + block->mIndex = mTempBlocks++; + + return block; +} + NativeCodeBasicBlock* NativeCodeProcedure::CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* sblock) { if (tblocks[sblock->mIndex]) @@ -1340,7 +1732,191 @@ NativeCodeBasicBlock* NativeCodeProcedure::CompileBlock(InterCodeProcedure* ipro block->mNoFrame = mNoFrame; tblocks[sblock->mIndex] = block; - block->Compile(iproc, this, sblock); + block->mIndex = sblock->mIndex; + + CompileInterBlock(iproc, sblock, block); return block; } + +void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* iblock, NativeCodeBasicBlock* block) +{ + int i = 0; + while (i < iblock->mInstructions.Size()) + { + const InterInstruction& ins = iblock->mInstructions[i]; + + switch (ins.mCode) + { + case IC_STORE: + block->StoreValue(iproc, ins); + break; + case IC_LOAD: + if (i + 1 < iblock->mInstructions.Size() && + iblock->mInstructions[i + 1].mCode == IC_STORE && + iblock->mInstructions[i + 1].mSTemp[0] == ins.mTTemp && + iblock->mInstructions[i + 1].mSFinal[0] && + iblock->mInstructions[i + 1].mOperandSize == 1) + { + block->LoadStoreValue(iproc, ins, iblock->mInstructions[i + 1]); + i++; + } + else if (i + 1 < iblock->mInstructions.Size() && + ins.mOperandSize == 2 && + iblock->mInstructions[i + 1].mCode == IC_BINARY_OPERATOR && + iblock->mInstructions[i + 1].mSTemp[0] == ins.mTTemp && iblock->mInstructions[i + 1].mSFinal[0]) + { + block->BinaryOperator(iproc, iblock->mInstructions[i + 1], nullptr, &ins); + i++; + } + else if (i + 1 < iblock->mInstructions.Size() && + ins.mOperandSize == 2 && + iblock->mInstructions[i + 1].mCode == IC_BINARY_OPERATOR && + iblock->mInstructions[i + 1].mSTemp[1] == ins.mTTemp && iblock->mInstructions[i + 1].mSFinal[1]) + { + block->BinaryOperator(iproc, iblock->mInstructions[i + 1], &ins, nullptr); + i++; + } + else if (i + 2 < iblock->mInstructions.Size() && + ins.mOperandSize == 2 && + iblock->mInstructions[i + 1].mCode == IC_LOAD && iblock->mInstructions[i + 1].mOperandSize == 2 && + iblock->mInstructions[i + 2].mCode == IC_BINARY_OPERATOR && + iblock->mInstructions[i + 2].mSTemp[0] == iblock->mInstructions[i + 1].mTTemp && iblock->mInstructions[i + 2].mSFinal[0] && + iblock->mInstructions[i + 2].mSTemp[1] == ins.mTTemp && iblock->mInstructions[i + 2].mSFinal[1]) + { + block->BinaryOperator(iproc, iblock->mInstructions[i + 2], &ins, &(iblock->mInstructions[i + 1])); + i += 2; + } + else if (i + 2 < iblock->mInstructions.Size() && + ins.mOperandSize == 2 && + iblock->mInstructions[i + 1].mCode == IC_LOAD && iblock->mInstructions[i + 1].mOperandSize == 2 && + iblock->mInstructions[i + 2].mCode == IC_BINARY_OPERATOR && + iblock->mInstructions[i + 2].mSTemp[1] == iblock->mInstructions[i + 1].mTTemp && iblock->mInstructions[i + 2].mSFinal[1] && + iblock->mInstructions[i + 2].mSTemp[0] == ins.mTTemp && iblock->mInstructions[i + 2].mSFinal[0]) + { + block->BinaryOperator(iproc, iblock->mInstructions[i + 2], &(iblock->mInstructions[i + 1]), &ins); + i += 2; + } + else + block->LoadValue(iproc, ins); + break; + case IC_COPY: + // CopyValue(iproc, ins); + break; + case IC_LOAD_TEMPORARY: + { + if (ins.mSTemp[0] != ins.mTTemp) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp])); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp] + 1)); + } + } break; + case IC_BINARY_OPERATOR: + block->BinaryOperator(iproc, ins, nullptr, nullptr); + break; + case IC_UNARY_OPERATOR: + block->UnaryOperator(iproc, ins); + break; + case IC_CONVERSION_OPERATOR: + // NumericConversion(iproc, ins); + break; + case IC_LEA: + block->LoadEffectiveAddress(iproc, ins); + break; + case IC_CONSTANT: + block->LoadConstant(iproc, ins); + break; + case IC_CALL: + // CallFunction(iproc, ins); + break; + case IC_JSR: + // CallAssembler(iproc, ins); + break; + case IC_PUSH_FRAME: + { + } break; + case IC_POP_FRAME: + { + } break; + + case IC_RELATIONAL_OPERATOR: + if (iblock->mInstructions[i + 1].mCode == IC_BRANCH) + { + block->RelationalOperator(iproc, ins, CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump)); + return; + } + else + { + NativeCodeBasicBlock* tblock, * fblock, * rblock; + + tblock = AllocateBlock(); + fblock = AllocateBlock(); + rblock = AllocateBlock(); + + block->RelationalOperator(iproc, ins, tblock, fblock); + + tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 1)); + tblock->Close(rblock, nullptr, ASMIT_JMP); + fblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + fblock->Close(rblock, nullptr, ASMIT_JMP); + + rblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp])); + rblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + rblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp] + 1)); + + block = rblock; + } + break; + + case IC_RETURN_VALUE: + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + + block->Close(exitBlock, nullptr, ASMIT_JMP); + return; + } + + case IC_RETURN: + block->Close(exitBlock, nullptr, ASMIT_JMP); + return; + + case IC_TYPECAST: + if (ins.mSTemp[0] != ins.mTTemp) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp])); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mTTemp] + 1)); + } + break; + + case IC_BRANCH: + if (ins.mSTemp[0] < 0) + { + if (ins.mSIntConst[0] == 0) + block->Close(CompileBlock(iproc, iblock->mFalseJump), nullptr, ASMIT_JMP); + else + block->Close(CompileBlock(iproc, iblock->mTrueJump), nullptr, ASMIT_JMP); + } + else + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); + block->mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); + + block->Close(CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump), ASMIT_BNE); + } + return; + + } + + i++; + } + + block->Close(CompileBlock(iproc, iblock->mTrueJump), nullptr, ASMIT_JMP); +} + diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index a27bbe9..cc92d53 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -10,12 +10,14 @@ class NativeCodeInstruction { public: NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, int varIndex = -1, bool lower = true, bool upper = true); + NativeCodeInstruction(const char* runtime); AsmInsType mType; AsmInsMode mMode; int mAddress, mVarIndex; bool mLower, mUpper; + const char * mRuntime; void Assemble(NativeCodeBasicBlock* block); }; @@ -46,17 +48,18 @@ public: void CopyCode(NativeCodeProcedure* proc, uint8* target); void Assemble(void); - void Compile(InterCodeProcedure* iproc, NativeCodeProcedure* proc, InterCodeBasicBlock* block); void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch); void PutByte(uint8 code); void PutWord(uint16 code); + void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction& ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh); + void LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins); void StoreValue(InterCodeProcedure* proc, const InterInstruction& ins); void LoadValue(InterCodeProcedure* proc, const InterInstruction& ins); void LoadStoreValue(InterCodeProcedure* proc, const InterInstruction& rins, const InterInstruction& wins); - void BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins); + void BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction* sins1, const InterInstruction* sins0); void UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins); void RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump); void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins); @@ -73,12 +76,17 @@ class NativeCodeProcedure int mProgStart, mProgSize, mIndex; bool mNoFrame; + int mTempBlocks; GrowingArray mRelocations; void Compile( ByteCodeGenerator * generator, InterCodeProcedure* proc); NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block); + NativeCodeBasicBlock* AllocateBlock(void); NativeCodeBasicBlock* TransientBlock(void); + void CompileInterBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* iblock, NativeCodeBasicBlock*block); + + }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8a2a577..57753e1 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2186,6 +2186,56 @@ void Parser::ParsePragma(void) } ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "runtime")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + const Ident* rtident = nullptr; + + if (mScanner->mToken == TK_IDENT) + { + rtident = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, "Identifier expected"); + + ConsumeToken(TK_COMMA); + if (mScanner->mToken == TK_IDENT) + { + Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_CONST_ASSEMBLER) + { + mScanner->NextToken(); + if (ConsumeTokenIf(TK_DOT)) + { + if (mScanner->mToken == TK_IDENT) + { + Declaration* ndec = dec->mBase->mScope->Lookup(mScanner->mTokenIdent); + if (ndec) + dec = ndec; + else + mErrors->Error(mScanner->mLocation, "Label not found in assembler code"); + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, "Identifier expected"); + } + + if (rtident) + { + mCompilationUnits->mRuntimeScope->Insert(rtident, dec); + } + } + else + { + mErrors->Error(mScanner->mLocation, "Runtime function not found"); + mScanner->NextToken(); + } + + } + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else { mScanner->NextToken();