From 056df56eef67cda24b91c915f0e602e001e5a25d Mon Sep 17 00:00:00 2001
From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com>
Date: Tue, 7 Sep 2021 22:35:11 +0200
Subject: [PATCH] First shot native code generator
Implements basic load, store compare and add/sub/shift for native compiled functions
---
oscar64/ByteCodeGenerator.cpp | 151 ++--
oscar64/ByteCodeGenerator.h | 35 +-
oscar64/Compiler.cpp | 36 +-
oscar64/Declaration.h | 1 +
oscar64/InterCode.cpp | 140 +++-
oscar64/InterCode.h | 8 +-
oscar64/InterCodeGenerator.cpp | 8 +-
oscar64/NativeCodeGenerator.cpp | 1349 +++++++++++++++++++++++++++++--
oscar64/NativeCodeGenerator.h | 31 +-
oscar64/Parser.cpp | 15 +
10 files changed, 1589 insertions(+), 185 deletions(-)
diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp
index b4ab708..9caf047 100644
--- a/oscar64/ByteCodeGenerator.cpp
+++ b/oscar64/ByteCodeGenerator.cpp
@@ -405,7 +405,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
ByteCodeRelocation rl;
rl.mAddr = block->mCode.Size();
- rl.mFunction = false;
+ rl.mFunction = mFunction;
rl.mLower = true;
rl.mUpper = true;
rl.mIndex = mVIndex;
@@ -1481,6 +1481,7 @@ void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInst
ByteCodeInstruction bins(BC_JSR);
bins.mRelocate = true;
bins.mVIndex = ins.mVarIndex;
+ bins.mFunction = ins.mMemory == IM_PROCEDURE;
mIns.Push(bins);
}
}
@@ -3394,78 +3395,88 @@ void ByteCodeGenerator::WriteAsmFile(FILE* file)
{
for (int i = 0; i < mGlobalAddr.Size(); i++)
{
- if (mGlobalAddr[i].mAssembler)
+ WriteAsmFile(file, mGlobalAddr[i]);
+ }
+ for (int i = 0; i < mProcedureAddr.Size(); i++)
+ {
+ WriteAsmFile(file, mProcedureAddr[i]);
+ }
+}
+
+void ByteCodeGenerator::WriteAsmFile(FILE * file, Address & addr)
+{
+
+ if (addr.mAssembler)
+ {
+ fprintf(file, "--------------------------------------------------------------------\n");
+ if (addr.mIdent)
+ fprintf(file, "%s:\n", addr.mIdent->mString);
+
+ int ip = addr.mAddress;
+ while (ip < addr.mAddress + addr.mSize)
{
- fprintf(file, "--------------------------------------------------------------------\n");
- if (mGlobalAddr[i].mIdent)
- fprintf(file, "%s:\n", mGlobalAddr[i].mIdent->mString);
+ int iip = ip;
+ uint8 opcode = mMemory[ip++];
+ AsmInsData d = DecInsData[opcode];
+ int addr = 0;
- int ip = mGlobalAddr[i].mAddress;
- while (ip < mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize)
+ switch (d.mMode)
{
- int iip = ip;
- uint8 opcode = mMemory[ip++];
- AsmInsData d = DecInsData[opcode];
- int addr = 0;
-
- switch (d.mMode)
- {
- case ASMIM_IMPLIED:
- fprintf(file, "%04x : %04x %02x __ __ %s\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType]);
- break;
- case ASMIM_IMMEDIATE:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s #$%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_ZERO_PAGE:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_ZERO_PAGE_X:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_ZERO_PAGE_Y:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_ABSOLUTE:
- addr = mMemory[ip] + 256 * mMemory[ip + 1];
- fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
- ip += 2;
- break;
- case ASMIM_ABSOLUTE_X:
- addr = mMemory[ip] + 256 * mMemory[ip + 1];
- fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
- ip += 2;
- break;
- case ASMIM_ABSOLUTE_Y:
- addr = mMemory[ip] + 256 * mMemory[ip + 1];
- fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
- ip += 2;
- break;
- case ASMIM_INDIRECT:
- addr = mMemory[ip] + 256 * mMemory[ip + 1];
- ip += 2;
- fprintf(file, "%04x : %04x %02x %02x %02x %s ($%04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_INDIRECT_X:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x,x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_INDIRECT_Y:
- addr = mMemory[ip++];
- fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x),y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- case ASMIM_RELATIVE:
- addr = mMemory[ip++];
- if (addr & 0x80)
- addr = addr + ip - 256;
- else
- addr = addr + ip;
- fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
- break;
- }
+ case ASMIM_IMPLIED:
+ fprintf(file, "%04x : %02x __ __ %s\n", iip, mMemory[ip], AsmInstructionNames[d.mType]);
+ break;
+ case ASMIM_IMMEDIATE:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s #$%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_ZERO_PAGE:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_ZERO_PAGE_X:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s $%02x,x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_ZERO_PAGE_Y:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s $%02x,y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_ABSOLUTE:
+ addr = mMemory[ip] + 256 * mMemory[ip + 1];
+ fprintf(file, "%04x : %02x %02x %02x %s $%04x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
+ ip += 2;
+ break;
+ case ASMIM_ABSOLUTE_X:
+ addr = mMemory[ip] + 256 * mMemory[ip + 1];
+ fprintf(file, "%04x : %02x %02x %02x %s $%04x,x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
+ ip += 2;
+ break;
+ case ASMIM_ABSOLUTE_Y:
+ addr = mMemory[ip] + 256 * mMemory[ip + 1];
+ fprintf(file, "%04x : %02x %02x %02x %s $%04x,y\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
+ ip += 2;
+ break;
+ case ASMIM_INDIRECT:
+ addr = mMemory[ip] + 256 * mMemory[ip + 1];
+ ip += 2;
+ fprintf(file, "%04x : %02x %02x %02x %s ($%04x)\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_INDIRECT_X:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s ($%02x,x)\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_INDIRECT_Y:
+ addr = mMemory[ip++];
+ fprintf(file, "%04x : %02x %02x __ %s ($%02x),y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
+ case ASMIM_RELATIVE:
+ addr = mMemory[ip++];
+ if (addr & 0x80)
+ addr = addr + ip - 256;
+ else
+ addr = addr + ip;
+ fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr);
+ break;
}
}
}
diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h
index b0821cf..165db05 100644
--- a/oscar64/ByteCodeGenerator.h
+++ b/oscar64/ByteCodeGenerator.h
@@ -253,26 +253,11 @@ public:
ByteCodeGenerator(void);
~ByteCodeGenerator(void);
- void WriteBasicHeader(void);
- void WriteByteCodeHeader(void);
- void SetBasicEntry(int index);
-
- bool WritePRGFile(const char* filename);
- bool WriteMapFile(const char* filename);
-
- void WriteAsmFile(FILE * file);
-
- void ResolveRelocations(void);
-
- int AddGlobal(int index, const Ident* ident, int size, const uint8* data, bool assembler);
-
- void AddAddress(int index, bool function, int address, int size, const Ident * ident, bool assembler);
-
struct Address
{
int mIndex, mAddress, mSize;
bool mFunction, mAssembler;
- const Ident * mIdent;
+ const Ident* mIdent;
};
GrowingArray
mProcedureAddr, mGlobalAddr;
@@ -282,4 +267,22 @@ public:
uint8 mMemory[0x10000];
int mProgEnd, mProgStart, mProgEntry;
+
+ void WriteBasicHeader(void);
+ void WriteByteCodeHeader(void);
+ void SetBasicEntry(int index);
+
+ bool WritePRGFile(const char* filename);
+ bool WriteMapFile(const char* filename);
+
+ void WriteAsmFile(FILE * file);
+
+ void WriteAsmFile(FILE* file, Address & addr);
+
+ void ResolveRelocations(void);
+
+ int AddGlobal(int index, const Ident* ident, int size, const uint8* data, bool assembler);
+
+ void AddAddress(int index, bool function, int address, int size, const Ident * ident, bool assembler);
+
};
diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp
index 16fc48f..6f31fbc 100644
--- a/oscar64/Compiler.cpp
+++ b/oscar64/Compiler.cpp
@@ -4,6 +4,7 @@
#include "InterCodeGenerator.h"
#include "InterCode.h"
#include "ByteCodeGenerator.h"
+#include "NativeCodeGenerator.h"
#include "Emulator.h"
#include
@@ -85,27 +86,38 @@ bool Compiler::GenerateCode(void)
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++)
{
- ByteCodeProcedure* bgproc = new ByteCodeProcedure();
+ InterCodeProcedure* proc = mInterCodeModule->mProcedures[i];
- mInterCodeModule->mProcedures[i]->ReduceTemporaries();
+ proc->ReduceTemporaries();
#if _DEBUG
- mInterCodeModule->mProcedures[i]->Disassemble("final");
+ proc->Disassemble("final");
#endif
- bgproc->Compile(mByteCodeGenerator, mInterCodeModule->mProcedures[i]);
- mByteCodeFunctions.Push(bgproc);
-#if _DEBUG
- FILE* file;
- fopen_s(&file, "r:\\cldiss.txt", "a");
-
- if (file)
+ if (proc->mNativeProcedure)
{
- bgproc->Disassemble(file, mByteCodeGenerator, mInterCodeModule->mProcedures[i]);
- fclose(file);
+ NativeCodeProcedure* ncproc = new NativeCodeProcedure();
+ ncproc->Compile(mByteCodeGenerator, proc);
}
+ else
+ {
+ ByteCodeProcedure* bgproc = new ByteCodeProcedure();
+
+ bgproc->Compile(mByteCodeGenerator, proc);
+ mByteCodeFunctions.Push(bgproc);
+
+#if _DEBUG
+ FILE* file;
+ fopen_s(&file, "r:\\cldiss.txt", "a");
+
+ if (file)
+ {
+ bgproc->Disassemble(file, mByteCodeGenerator, mInterCodeModule->mProcedures[i]);
+ fclose(file);
+ }
#endif
+ }
}
for (int i = 0; i < 128; i++)
diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h
index 35f5f7c..4f8ee09 100644
--- a/oscar64/Declaration.h
+++ b/oscar64/Declaration.h
@@ -52,6 +52,7 @@ static const uint32 DTF_STATIC = 0x00000020;
static const uint32 DTF_CONST = 0x00000040;
static const uint32 DTF_VOLATILE = 0x00000080;
static const uint32 DTF_EXTERN = 0x00000100;
+static const uint32 DTF_NATIVE = 0x00000200;
class Declaration;
diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp
index 2846595..34ce1a2 100644
--- a/oscar64/InterCode.cpp
+++ b/oscar64/InterCode.cpp
@@ -2554,9 +2554,12 @@ void InterCodeBasicBlock::MapVariables(GrowingVariableArray& globalVars, Growing
switch (mInstructions[i].mCode)
{
+ case IC_CONSTANT:
+ if (mInstructions[i].mTType != IT_POINTER)
+ break;
+
case IC_STORE:
case IC_LOAD:
- case IC_CONSTANT:
case IC_JSR:
if (mInstructions[i].mMemory == IM_GLOBAL)
{
@@ -2619,7 +2622,7 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
mVisited = true;
for (i = 0; i < mInstructions.Size(); i++)
- if (mInstructions[i].mCode == IC_CALL)
+ if (mInstructions[i].mCode == IC_CALL || mInstructions[i].mCode == IC_JSR)
return false;
if (mTrueJump && !mTrueJump->IsLeafProcedure())
@@ -2631,6 +2634,91 @@ bool InterCodeBasicBlock::IsLeafProcedure(void)
return true;
}
+void InterCodeBasicBlock::PeepholeOptimization(void)
+{
+ int i;
+
+ if (!mVisited)
+ {
+ mVisited = true;
+
+ bool changed;
+ do
+ {
+ int j = 0;
+ for (i = 0; i < mInstructions.Size(); i++)
+ {
+ if (mInstructions[i].mCode != IC_NONE)
+ {
+ mInstructions[j++] = mInstructions[i];
+ }
+ }
+ mInstructions.SetSize(j);
+
+ changed = false;
+
+ for (i = 0; i < mInstructions.Size(); i++)
+ {
+ if (i + 2 < mInstructions.Size())
+ {
+ if (mInstructions[i + 0].mTTemp >= 0 &&
+ mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
+ (mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[0] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[0])
+ {
+ mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
+ mInstructions[i + 1].mCode = IC_NONE;
+ mInstructions[i + 2].mSTemp[0] = mInstructions[i + 1].mTTemp;
+ mInstructions[i + 2].mSFinal[0] = false;
+ changed = true;
+ }
+ else if (mInstructions[i + 0].mTTemp >= 0 &&
+ mInstructions[i + 1].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mSTemp[0] == mInstructions[i].mTTemp &&
+ (mInstructions[i + 2].mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2].mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2].mSTemp[1] == mInstructions[i].mTTemp && mInstructions[i + 2].mSFinal[1])
+ {
+ mInstructions[i + 0].mTTemp = mInstructions[i + 1].mTTemp;
+ mInstructions[i + 1].mCode = IC_NONE;
+ mInstructions[i + 2].mSTemp[1] = mInstructions[i + 1].mTTemp;
+ mInstructions[i + 2].mSFinal[1] = false;
+ changed = true;
+ }
+
+ // Postincrement artifact
+ if (mInstructions[i + 0].mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1].mCode == IC_BINARY_OPERATOR &&
+ mInstructions[i + 1].mSTemp[0] < 0 &&
+ mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mSTemp[1] &&
+ mInstructions[i + 0].mSTemp[0] == mInstructions[i + 1].mTTemp)
+ {
+ InterInstruction ins = mInstructions[i + 1];
+ int ttemp = mInstructions[i + 1].mTTemp;
+ int k = i + 1;
+ while (k + 2 < mInstructions.Size() &&
+ mInstructions[k + 1].mSTemp[0] != ttemp &&
+ mInstructions[k + 1].mSTemp[1] != ttemp &&
+ mInstructions[k + 1].mSTemp[2] != ttemp &&
+ mInstructions[k + 1].mTTemp != ttemp)
+ {
+ mInstructions[k] = mInstructions[k + 1];
+ k++;
+ }
+ if (k > i + 1)
+ {
+ mInstructions[k] = ins;
+ changed = true;
+ }
+ }
+ }
+
+
+ }
+
+ } while (changed);
+
+ if (mTrueJump) mTrueJump->PeepholeOptimization();
+ if (mFalseJump) mFalseJump->PeepholeOptimization();
+ }
+}
+
+
void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars)
{
int i;
@@ -2783,7 +2871,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
: mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1),
mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
mValueForwardingTable(NULL), mLocalVars(InterVariable()), mModule(mod),
- mIdent(ident)
+ mIdent(ident), mNativeProcedure(false), mLeafProcedure(false)
{
mID = mModule->mProcedures.Size();
mModule->mProcedures.Push(this);
@@ -2964,6 +3052,27 @@ void InterCodeProcedure::TempForwarding(void)
DisassembleDebug("temp forwarding");
}
+void InterCodeProcedure::RemoveUnusedInstructions(void)
+{
+ int numTemps = mTemporaries.Size();
+
+ do {
+ ResetVisited();
+ mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
+
+ ResetVisited();
+ mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
+
+ NumberSet totalRequired2(numTemps);
+
+ do {
+ ResetVisited();
+ } while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
+
+ ResetVisited();
+ } while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
+}
+
void InterCodeProcedure::Close(void)
{
int i, j, k, start;
@@ -3139,25 +3248,18 @@ void InterCodeProcedure::Close(void)
// Now remove unused instructions
//
- do {
- ResetVisited();
- mBlocks[0]->BuildLocalTempSets(numTemps, numFixedTemporaries);
-
- ResetVisited();
- mBlocks[0]->BuildGlobalProvidedTempSet(NumberSet(numTemps));
-
- NumberSet totalRequired2(numTemps);
-
- do {
- ResetVisited();
- } while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired2));
-
- ResetVisited();
- } while (mBlocks[0]->RemoveUnusedResultInstructions(numFixedTemporaries));
+ RemoveUnusedInstructions();
DisassembleDebug("removed unused instructions 2");
+ ResetVisited();
+ mBlocks[0]->PeepholeOptimization();
+
+ TempForwarding();
+ RemoveUnusedInstructions();
+
+ DisassembleDebug("Peephole optimized");
FastNumberSet activeSet(numTemps);
@@ -3173,6 +3275,8 @@ void InterCodeProcedure::Close(void)
mTemporaries.SetSize(activeSet.Num());
+
+
ResetVisited();
mBlocks[0]->ShrinkActiveTemporaries(activeSet, mTemporaries);
diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h
index 4a3fabf..0292294 100644
--- a/oscar64/InterCode.h
+++ b/oscar64/InterCode.h
@@ -253,6 +253,9 @@ public:
}
};
+
+typedef GrowingArray GrowingInterVariableReferenceArray;
+
class InterInstruction
{
public:
@@ -415,6 +418,8 @@ public:
void CollectOuterFrame(int level, int& size);
bool IsLeafProcedure(void);
+
+ void PeepholeOptimization(void);
};
class InterCodeModule;
@@ -434,7 +439,7 @@ public:
GrowingTypeArray mTemporaries;
GrowingIntArray mTempOffset;
int mTempSize, mCommonFrameSize;
- bool mLeafProcedure;
+ bool mLeafProcedure, mNativeProcedure;
InterCodeModule * mModule;
int mID;
@@ -463,6 +468,7 @@ protected:
void BuildDataFlowSets(void);
void RenameTemporaries(void);
void TempForwarding(void);
+ void RemoveUnusedInstructions(void);
void DisassembleDebug(const char* name);
};
diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp
index befedee..ba9b904 100644
--- a/oscar64/InterCodeGenerator.cpp
+++ b/oscar64/InterCodeGenerator.cpp
@@ -1397,7 +1397,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
mErrors->Error(exp->mLocation, "Not enough arguments for function call");
InterInstruction cins;
- cins.mCode = IC_CALL;
+ if (exp->mLeft->mDecValue->mFlags & DTF_NATIVE)
+ cins.mCode = IC_JSR;
+ else
+ cins.mCode = IC_CALL;
cins.mSType[0] = IT_POINTER;
cins.mSTemp[0] = vl.mTemp;
if (ftype->mBase->mType != DT_TYPE_VOID)
@@ -2210,6 +2213,9 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent);
dec->mVarIndex = proc->mID;
+ if (dec->mFlags & DTF_NATIVE)
+ proc->mNativeProcedure = true;
+
InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock();
proc->Append(entryBlock);
diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp
index a8f77bf..15b5c92 100644
--- a/oscar64/NativeCodeGenerator.cpp
+++ b/oscar64/NativeCodeGenerator.cpp
@@ -1,52 +1,66 @@
#include "NativeCodeGenerator.h"
-NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode)
- : mType(type), mMode(mode), mGlobal(false), mAddress(0), mVarIndex(-1)
+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)
{}
-void NativeCodeInstruction::Assemble(ByteCodeGenerator* generator, NativeCodeBasicBlock* block)
+void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
{
+ block->PutByte(AsmInsOpcodes[mType][mMode]);
+
switch (mMode)
{
- block->PutByte(AsmInsOpcodes[mType][mMode]);
-
- switch (mMode)
+ case ASMIM_IMPLIED:
+ break;
+ case ASMIM_ZERO_PAGE:
+ case ASMIM_ZERO_PAGE_X:
+ case ASMIM_INDIRECT_X:
+ case ASMIM_INDIRECT_Y:
+ block->PutByte(uint8(mAddress));
+ break;
+ case ASMIM_IMMEDIATE:
+ if (mVarIndex != -1)
{
- case ASMIM_IMPLIED:
- break;
- case ASMIM_IMMEDIATE:
- case ASMIM_ZERO_PAGE:
- case ASMIM_ZERO_PAGE_X:
- case ASMIM_INDIRECT_X:
- case ASMIM_INDIRECT_Y:
- block->PutByte(uint8(mAddress));
- break;
- case ASMIM_ABSOLUTE:
- case ASMIM_INDIRECT:
- case ASMIM_ABSOLUTE_X:
- case ASMIM_ABSOLUTE_Y:
- if (mGlobal)
- {
- ByteCodeRelocation rl;
- rl.mAddr = block->mCode.Size();
- rl.mFunction = false;
- rl.mLower = true;
- rl.mUpper = true;
- rl.mIndex = mVarIndex;
- rl.mOffset = mAddress;
- block->mRelocations.Push(rl);
- block->PutWord(0);
- }
- else
- {
- block->PutWord(uint16(mAddress));
- }
- break;
- case ASMIM_RELATIVE:
- block->PutByte(uint8(mAddress - block->mCode.Size() - 1));
- break;
+ ByteCodeRelocation rl;
+ rl.mAddr = block->mCode.Size();
+ rl.mFunction = false;
+ rl.mLower = mLower;
+ rl.mUpper = mUpper;
+ rl.mIndex = mVarIndex;
+ rl.mOffset = mAddress;
+ block->mRelocations.Push(rl);
+ block->PutByte(0);
}
+ else
+ {
+ block->PutByte(uint16(mAddress));
+ }
+ break;
+ case ASMIM_ABSOLUTE:
+ case ASMIM_INDIRECT:
+ case ASMIM_ABSOLUTE_X:
+ case ASMIM_ABSOLUTE_Y:
+ if (mVarIndex != - 1)
+ {
+ ByteCodeRelocation rl;
+ rl.mAddr = block->mCode.Size();
+ rl.mFunction = false;
+ rl.mLower = true;
+ rl.mUpper = true;
+ rl.mIndex = mVarIndex;
+ rl.mOffset = mAddress;
+ block->mRelocations.Push(rl);
+ block->PutWord(0);
+ }
+ else
+ {
+ block->PutWord(uint16(mAddress));
+ }
+ break;
+ case ASMIM_RELATIVE:
+ block->PutByte(uint8(mAddress));
+ break;
}
}
@@ -61,17 +75,17 @@ void NativeCodeBasicBlock::PutWord(uint16 code)
this->mCode.Insert((uint8)(code & 0xff));
this->mCode.Insert((uint8)(code >> 8));
}
-#if 0
+
static AsmInsType InvertBranchCondition(AsmInsType code)
{
switch (code)
{
- case BC_BRANCHS_EQ: return BC_BRANCHS_NE;
- case BC_BRANCHS_NE: return BC_BRANCHS_EQ;
- case BC_BRANCHS_GT: return BC_BRANCHS_LE;
- case BC_BRANCHS_GE: return BC_BRANCHS_LT;
- case BC_BRANCHS_LT: return BC_BRANCHS_GE;
- case BC_BRANCHS_LE: return BC_BRANCHS_GT;
+ case ASMIT_BEQ: return ASMIT_BNE;
+ case ASMIT_BNE: return ASMIT_BEQ;
+ case ASMIT_BPL: return ASMIT_BMI;
+ case ASMIT_BMI: return ASMIT_BPL;
+ case ASMIT_BCS: return ASMIT_BCC;
+ case ASMIT_BCC: return ASMIT_BCS;
default:
return code;
}
@@ -81,19 +95,36 @@ static AsmInsType TransposeBranchCondition(AsmInsType code)
{
switch (code)
{
- case BC_BRANCHS_EQ: return BC_BRANCHS_EQ;
- case BC_BRANCHS_NE: return BC_BRANCHS_NE;
- case BC_BRANCHS_GT: return BC_BRANCHS_LT;
- case BC_BRANCHS_GE: return BC_BRANCHS_LE;
- case BC_BRANCHS_LT: return BC_BRANCHS_GT;
- case BC_BRANCHS_LE: return BC_BRANCHS_GE;
+ case ASMIT_BEQ: return ASMIT_BEQ;
+ case ASMIT_BNE: return ASMIT_BNE;
+ case ASMIT_BPL: return ASMIT_BMI;
+ case ASMIT_BMI: return ASMIT_BPL;
+ case ASMIT_BCS: return ASMIT_BCC;
+ case ASMIT_BCC: return ASMIT_BCS;
default:
return code;
}
}
-int NativeCodeBasicBlock::PutBranch(ByteCodeGenerator* generator, AsmInsType code, int offset)
+int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, int offset)
+{
+ PutByte(0x4c);
+
+ ByteCodeRelocation rl;
+ rl.mAddr = mCode.Size();
+ rl.mFunction = true;
+ rl.mLower = true;
+ rl.mUpper = true;
+ rl.mIndex = proc->mIndex;
+ rl.mOffset = mOffset + mCode.Size() + offset - 1;
+ mRelocations.Push(rl);
+
+ PutWord(0);
+ return 3;
+}
+
+int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset)
{
if (offset >= -126 && offset <= 129)
{
@@ -103,11 +134,1213 @@ int NativeCodeBasicBlock::PutBranch(ByteCodeGenerator* generator, AsmInsType cod
}
else
{
- PutByte(AsmInsOpcodes[code][ASMIM_RELATIVE]);
+ PutByte(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]);
+ PutByte(3);
+ PutByte(0x4c);
- PutCode(generator, ByteCode(code + (BC_JUMPF - BC_JUMPS)));
- PutWord(offset - 3);
- return 3;
+ ByteCodeRelocation rl;
+ rl.mAddr = mCode.Size();
+ rl.mFunction = true;
+ rl.mLower = true;
+ rl.mUpper = true;
+ rl.mIndex = proc->mIndex;
+ rl.mOffset = mOffset + mCode.Size() + offset - 3;
+ mRelocations.Push(rl);
+
+ PutWord(0);
+ return 5;
}
}
-#endif
+
+void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+ if (ins.mTType == IT_FLOAT)
+ {
+ }
+ else if (ins.mTType == IT_POINTER)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue, ins.mVarIndex, true, false));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue, ins.mVarIndex, false, true));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mIntValue >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mIntValue;
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, (mNoFrame ? BC_REG_STACK : BC_REG_LOCALS) + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ }
+ else if (ins.mMemory == IM_PROCEDURE)
+ {
+ }
+ }
+ else
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mIntValue >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ }
+
+}
+
+void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+ if (ins.mSType[0] == IT_FLOAT)
+ {
+ }
+ else if (ins.mSType[0] == IT_POINTER)
+ {
+ if (ins.mSTemp[1] < 0)
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1, ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ else
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1, ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ }
+ else
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ }
+ }
+ else
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ins.mSTemp[1] < 0)
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mOperandSize == 1)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ else if (ins.mOperandSize == 2)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1, ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ }
+ else
+ {
+ if (ins.mOperandSize == 1)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ else if (ins.mOperandSize == 2)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1], ins.mVarIndex));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1, ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1]));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins.mSIntConst[1] + 1));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[1];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (ins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+
+ if (ins.mOperandSize == 2)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ }
+ }
+ }
+ else
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+
+ if (ins.mOperandSize == 2)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]));
+ }
+ }
+ }
+ }
+ }
+
+}
+
+void NativeCodeBasicBlock::LoadStoreValue(InterCodeProcedure* proc, const InterInstruction& rins, const InterInstruction& wins)
+{
+ if (rins.mTType == IT_FLOAT)
+ {
+
+ }
+ else if (rins.mTType == IT_POINTER)
+ {
+
+ }
+ else
+ {
+ if (wins.mOperandSize == 1)
+ {
+ if (rins.mSTemp[0] < 0)
+ {
+ if (rins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins.mSIntConst[0], rins.mVarIndex));
+ }
+ else if (rins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins.mSIntConst[0]));
+ }
+ else if (rins.mMemory == IM_LOCAL || rins.mMemory == IM_PARAM)
+ {
+ int index = rins.mSIntConst[0];
+ if (rins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[rins.mVarIndex].mOffset;
+ else
+ index += rins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ }
+ else
+ {
+ if (rins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins.mSTemp[0]]));
+ }
+ }
+
+ if (wins.mSTemp[1] < 0)
+ {
+ if (wins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins.mSIntConst[1], wins.mVarIndex));
+ }
+ else if (wins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins.mSIntConst[1]));
+ }
+ else if (wins.mMemory == IM_LOCAL || wins.mMemory == IM_PARAM)
+ {
+ int index = wins.mSIntConst[1];
+ if (wins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[wins.mVarIndex].mOffset;
+ else
+ index += wins.mVarIndex + proc->mLocalSize + 2;
+
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS));
+ }
+ else if (wins.mMemory == IM_FRAME)
+ {
+ }
+ }
+ else
+ {
+ if (wins.mMemory == IM_INDIRECT)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
+ mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins.mSTemp[1]]));
+ }
+ }
+ }
+ }
+}
+
+void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+ if (ins.mTType == IT_FLOAT)
+ {
+ }
+ else if (ins.mTType == IT_POINTER)
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ 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]));
+ 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));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ 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));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[0];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ 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]));
+ 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));
+ }
+ }
+ else
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ 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]));
+ 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));
+ }
+ }
+ }
+ else
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mOperandSize == 1)
+ {
+ if (ins.mMemory == IM_GLOBAL)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0]));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[0];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ 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 (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));
+ }
+ 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));
+ }
+ 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]));
+ 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));
+ }
+ else if (ins.mMemory == IM_ABSOLUTE)
+ {
+ 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));
+ }
+ else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM)
+ {
+ int index = ins.mSIntConst[0];
+ if (ins.mMemory == IM_LOCAL)
+ index += proc->mLocalVars[ins.mVarIndex].mOffset;
+ else
+ index += ins.mVarIndex + proc->mLocalSize + 2;
+
+ 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]));
+ 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));
+ }
+ }
+ }
+ else
+ {
+ if (ins.mMemory == IM_INDIRECT)
+ {
+ if (ins.mOperandSize == 1)
+ {
+ 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 (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));
+ }
+ 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));
+ }
+ 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]));
+ 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));
+ }
+ }
+ }
+ }
+}
+
+void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+ switch (ins.mOperator)
+ {
+ case IA_ADD:
+ {
+ 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)
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]));
+ mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, 2));
+ mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ }
+ else
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
+ 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_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));
+ }
+ } break;
+ case IA_SUB:
+ {
+ mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
+ 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_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_SBC, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff));
+ else
+ 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, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1));
+ } break;
+ case IA_SHL:
+ {
+ if (ins.mSTemp[0] < 0)
+ {
+ if (ins.mSIntConst[0] == 1)
+ {
+ 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));
+ }
+ else
+ {
+ 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_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));
+ }
+ }
+ }
+ } break;
+ }
+}
+
+void NativeCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+
+}
+
+void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump)
+{
+ switch (ins.mOperator)
+ {
+ 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;
+ 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]]));
+
+ 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;
+ }
+}
+
+void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins)
+{
+ mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
+ 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_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));
+}
+
+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)
+ {
+ mAssembled = true;
+
+ //PeepHoleOptimizer();
+
+ for (int i = 0; i < mIns.Size(); i++)
+ mIns[i].Assemble(this);
+
+ if (this->mTrueJump)
+ this->mTrueJump->Assemble();
+ if (this->mFalseJump)
+ this->mFalseJump->Assemble();
+ }
+}
+
+void NativeCodeBasicBlock::Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch)
+{
+ this->mTrueJump = trueJump;
+ this->mFalseJump = falseJump;
+ this->mBranch = branch;
+}
+
+
+static int BranchByteSize(int from, int to)
+{
+ if (to - from >= -126 && to - from <= 129)
+ return 2;
+ else
+ return 5;
+}
+
+static int JumpByteSize(int from, int to)
+{
+ return 3;
+}
+
+NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
+{
+ if (mBypassed)
+ return this;
+ else if (!mFalseJump && mCode.Size() == 0)
+ return mTrueJump->BypassEmptyBlocks();
+ else
+ {
+ mBypassed = true;
+
+ if (mFalseJump)
+ mFalseJump = mFalseJump->BypassEmptyBlocks();
+ if (mTrueJump)
+ mTrueJump = mTrueJump->BypassEmptyBlocks();
+
+ return this;
+ }
+}
+
+void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
+{
+ int i;
+ int next;
+ int pos, at;
+ uint8 b;
+
+ if (!mCopied)
+ {
+ mCopied = true;
+
+
+ next = mOffset + mCode.Size();
+
+ if (mFalseJump)
+ {
+ if (mFalseJump->mOffset <= mOffset)
+ {
+ if (mTrueJump->mOffset <= mOffset)
+ {
+ next += PutBranch(proc, mBranch, mTrueJump->mOffset - next);
+ next += PutJump(proc, mFalseJump->mOffset - next);
+
+ }
+ else
+ {
+ next += PutBranch(proc, InvertBranchCondition(mBranch), mFalseJump->mOffset - next);
+ }
+ }
+ else
+ {
+ next += PutBranch(proc, mBranch, mTrueJump->mOffset - next);
+ }
+ }
+ else if (mTrueJump)
+ {
+ if (mTrueJump->mOffset != next)
+ {
+ next += PutJump(proc, mTrueJump->mOffset - next);
+ }
+ }
+
+ assert(next - mOffset == mSize);
+
+ for (i = 0; i < mCode.Size(); i++)
+ {
+ mCode.Lookup(i, target[i + mOffset]);
+ }
+
+ for (int i = 0; i < mRelocations.Size(); i++)
+ {
+ ByteCodeRelocation& rl(mRelocations[i]);
+ rl.mAddr += mOffset;
+ proc->mRelocations.Push(rl);
+ }
+
+ if (mTrueJump) mTrueJump->CopyCode(proc, target);
+ if (mFalseJump) mFalseJump->CopyCode(proc, target);
+ }
+}
+
+void NativeCodeBasicBlock::CalculateOffset(int& total)
+{
+ int next;
+
+ if (mOffset > total)
+ {
+ mOffset = total;
+ next = total + mCode.Size();
+
+ if (mFalseJump)
+ {
+ if (mFalseJump->mOffset <= total)
+ {
+ // falseJump has been placed
+
+ if (mTrueJump->mOffset <= total)
+ {
+ // trueJump and falseJump have been placed, not much to do
+
+ next = next + BranchByteSize(next, mTrueJump->mOffset);
+ total = next + JumpByteSize(next, mFalseJump->mOffset);
+ mSize = total - mOffset;
+ }
+ else
+ {
+ // trueJump has not been placed, but falseJump has
+
+ total = next + BranchByteSize(next, mFalseJump->mOffset);
+ mSize = total - mOffset;
+ mTrueJump->CalculateOffset(total);
+ }
+ }
+ else if (mTrueJump->mOffset <= total)
+ {
+ // falseJump has not been placed, but trueJump has
+
+ total = next + BranchByteSize(next, mTrueJump->mOffset);
+ mSize = total - mOffset;
+ mFalseJump->CalculateOffset(total);
+ }
+ else if (mKnownShortBranch)
+ {
+ // neither falseJump nor trueJump have been placed,
+ // but we know from previous iteration that we can do
+ // a short branch
+
+ total = next + 2;
+ mSize = total - mOffset;
+
+ mFalseJump->CalculateOffset(total);
+ if (mTrueJump->mOffset > total)
+ {
+ // trueJump was not placed in the process, so lets place it now
+ mTrueJump->CalculateOffset(total);
+ }
+ }
+ else
+ {
+ // neither falseJump nor trueJump have been placed
+ // this may lead to some undo operation...
+ // first assume a full size branch:
+
+ total = next + 5;
+ mSize = total - mOffset;
+
+ mFalseJump->CalculateOffset(total);
+ if (mTrueJump->mOffset > total)
+ {
+ // trueJump was not placed in the process, so lets place it now
+
+ mTrueJump->CalculateOffset(total);
+ }
+
+ if (BranchByteSize(next, mTrueJump->mOffset) < 3)
+ {
+ // oh, we can replace by a short branch
+
+ mKnownShortBranch = true;
+
+ total = next + 2;
+ mSize = total - mOffset;
+
+ mFalseJump->CalculateOffset(total);
+ if (mTrueJump->mOffset > total)
+ {
+ // trueJump was not placed in the process, so lets place it now
+
+ mTrueJump->CalculateOffset(total);
+ }
+ }
+ }
+ }
+ else if (mTrueJump)
+ {
+ if (mTrueJump->mOffset <= total)
+ {
+ // trueJump has been placed, so append the branch size
+
+ total = next + JumpByteSize(next, mTrueJump->mOffset);
+ mSize = total - mOffset;
+ }
+ else
+ {
+ // we have to place trueJump, so just put it right behind us
+
+ total = next;
+ mSize = total - mOffset;
+
+ mTrueJump->CalculateOffset(total);
+ }
+ }
+ else
+ {
+ // no exit from block
+
+ total += mCode.Size();
+ mSize = total - mOffset;
+ }
+ }
+}
+
+NativeCodeBasicBlock::NativeCodeBasicBlock(void)
+ : mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 })
+{
+ mTrueJump = mFalseJump = NULL;
+ mOffset = 0x7fffffff;
+ mCopied = false;
+ mKnownShortBranch = false;
+ mBypassed = false;
+}
+
+NativeCodeBasicBlock::~NativeCodeBasicBlock(void)
+{
+
+}
+
+NativeCodeProcedure::NativeCodeProcedure(void)
+ : mRelocations({ 0 })
+{
+
+}
+
+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++)
+ tblocks[i] = nullptr;
+
+ mIndex = proc->mID;
+ mNoFrame = true;
+
+ entryBlock = new NativeCodeBasicBlock();
+ entryBlock->mNoFrame = mNoFrame;
+
+ tblocks[0] = entryBlock;
+
+ exitBlock = new NativeCodeBasicBlock();
+ exitBlock->mNoFrame = mNoFrame;
+
+ exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
+
+ entryBlock->Compile(proc, this, proc->mBlocks[0]);
+ entryBlock->Assemble();
+
+ int total, base;
+
+ NativeCodeBasicBlock* lentryBlock = entryBlock->BypassEmptyBlocks();
+
+ total = 0;
+ base = generator->mProgEnd;
+
+ lentryBlock->CalculateOffset(total);
+
+ generator->AddAddress(proc->mID, true, base, total, proc->mIdent, true);
+
+ lentryBlock->CopyCode(this, generator->mMemory + base);
+
+ generator->mProgEnd += total;
+
+ for (int i = 0; i < mRelocations.Size(); i++)
+ {
+ ByteCodeRelocation& rl(mRelocations[i]);
+ rl.mAddr += base;
+ generator->mRelocations.Push(rl);
+ }
+}
+
+NativeCodeBasicBlock* NativeCodeProcedure::CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* sblock)
+{
+ if (tblocks[sblock->mIndex])
+ return tblocks[sblock->mIndex];
+
+ NativeCodeBasicBlock* block = new NativeCodeBasicBlock();
+ block->mNoFrame = mNoFrame;
+
+ tblocks[sblock->mIndex] = block;
+ block->Compile(iproc, this, sblock);
+
+ return block;
+}
diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h
index 04b6be7..a27bbe9 100644
--- a/oscar64/NativeCodeGenerator.h
+++ b/oscar64/NativeCodeGenerator.h
@@ -9,15 +9,15 @@ class NativeCodeBasicBlock;
class NativeCodeInstruction
{
public:
- NativeCodeInstruction(AsmInsType type, AsmInsMode mode);
+ NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, int varIndex = -1, bool lower = true, bool upper = true);
AsmInsType mType;
AsmInsMode mMode;
int mAddress, mVarIndex;
- bool mGlobal;
+ bool mLower, mUpper;
- void Assemble(ByteCodeGenerator* generator, NativeCodeBasicBlock* block);
+ void Assemble(NativeCodeBasicBlock* block);
};
class NativeCodeBasicBlock
@@ -36,21 +36,30 @@ public:
GrowingArray mRelocations;
int mOffset, mSize;
- bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled;
+ bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame;
- int PutBranch(ByteCodeGenerator* generator, AsmInsType code, int offset);
+ int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
+ int PutJump(NativeCodeProcedure* proc, int offset);
NativeCodeBasicBlock* BypassEmptyBlocks(void);
void CalculateOffset(int& total);
- void CopyCode(ByteCodeGenerator* generator, uint8* target);
- void Assemble(ByteCodeGenerator* generator);
+ 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 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 UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins);
+ void RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
+ void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins);
};
class NativeCodeProcedure
@@ -62,10 +71,14 @@ class NativeCodeProcedure
NativeCodeBasicBlock* entryBlock, * exitBlock;
NativeCodeBasicBlock** tblocks;
- int mProgStart, mProgSize;
+ int mProgStart, mProgSize, mIndex;
+ bool mNoFrame;
- void Compile(ByteCodeGenerator* generator, InterCodeProcedure* proc);
+ GrowingArray mRelocations;
+
+ void Compile( ByteCodeGenerator * generator, InterCodeProcedure* proc);
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
+ NativeCodeBasicBlock* TransientBlock(void);
};
diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp
index d4c002b..8a2a577 100644
--- a/oscar64/Parser.cpp
+++ b/oscar64/Parser.cpp
@@ -2106,6 +2106,21 @@ void Parser::ParsePragma(void)
}
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
+ else if (!strcmp(mScanner->mTokenIdent->mString, "native"))
+ {
+ mScanner->NextToken();
+ ConsumeToken(TK_OPEN_PARENTHESIS);
+ if (mScanner->mToken == TK_IDENT)
+ {
+ Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent);
+ if (dec && dec->mType == DT_CONST_FUNCTION)
+ dec->mFlags |= DTF_NATIVE;
+ else
+ mErrors->Error(mScanner->mLocation, "Native function not found");
+ mScanner->NextToken();
+ }
+ ConsumeToken(TK_CLOSE_PARENTHESIS);
+ }
else if (!strcmp(mScanner->mTokenIdent->mString, "startup"))
{
if (mCompilationUnits->mStartup)