diff --git a/make/makefile b/make/makefile index 533d3e1..71074d0 100644 --- a/make/makefile +++ b/make/makefile @@ -3,8 +3,8 @@ sources = $(wildcard ../oscar64/*.cpp) objects = $(patsubst ../oscar64/%.cpp,%.o,$(sources)) -CXX = g++ -CPPFLAGS = -g -O2 +CXX = c++ +CPPFLAGS = -g -O2 -std=c++11 -Wno-switch ifdef WINDIR @@ -21,7 +21,7 @@ else endif %.o: ../oscar64/%.cpp - g++ -c $(CPPFLAGS) $< -o $@ + $(CXX) -c $(CPPFLAGS) $< -o $@ %.d: ../oscar64/%.cpp @set -e; rm -f $@; \ @@ -30,10 +30,16 @@ endif rm -f $@.$$$$ ../bin/oscar64 : $(objects) - g++ $(CPPFLAGS) $(linklibs) $(objects) -o ../bin/oscar64 + $(CXX) $(CPPFLAGS) $(linklibs) $(objects) -o ../bin/oscar64 .PHONY : clean clean : - -rm *.o *.d + -rm *.o *.d oscar64 + +ifeq ($(UNAME_S), Darwin) + +else include $(objects:.o=.d) + +endif diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index a180508..ba59872 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -2473,7 +2473,7 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p } break; case IC_RELATIONAL_OPERATOR: - if (sblock->mInstructions[i + 1]->mCode == IC_BRANCH && sblock->mInstructions[i + 1]->mSFinal[0]) + if (i + 1 < sblock->mInstructions.Size() && sblock->mInstructions[i + 1]->mCode == IC_BRANCH && sblock->mInstructions[i + 1]->mSFinal[0]) { ByteCode code = RelationalOperator(iproc, ins); this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), code); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1909b05..18594d6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1019,6 +1019,7 @@ InterInstruction::InterInstruction(void) mSFinal[0] = mSFinal[1] = mSFinal[2] = false; mInUse = false; + mVolatile = false; } void InterInstruction::SetCode(const Location& loc, InterCode code) @@ -3115,7 +3116,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(void) ins->mInvariant = false; else if (ins->mCode == IC_LOAD) { - if (ins->mSTemp[0] >= 0) + if (ins->mSTemp[0] >= 0 || ins->mVolatile) { ins->mInvariant = false; } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 3390f98..c87225a 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -302,7 +302,7 @@ public: Location mLocation; LinkerObject * mLinkerObject; - bool mInUse, mInvariant; + bool mInUse, mInvariant, mVolatile; InterInstruction(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 329df01..86b9cab 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -50,6 +50,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mTType = v.mReference == 1 ? InterTypeOf(v.mType) : IT_POINTER; ins->mTTemp = proc->AddTemporary(ins->mTType); ins->mOperandSize = v.mReference == 1 ? v.mType->mSize : 2; + if (v.mType->mFlags & DTF_VOLATILE) + ins->mVolatile = true; block->Append(ins); v = ExValue(v.mType, ins->mTTemp, v.mReference - 1); @@ -324,17 +326,22 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e } else if (aexp->mType == DT_LABEL) { - if (!aexp->mBase->mLinkerObject) - TranslateAssembler(mod, aexp->mBase->mValue); + if (aexp->mBase) + { + if (!aexp->mBase->mLinkerObject) + TranslateAssembler(mod, aexp->mBase->mValue); - LinkerReference ref; - ref.mObject = dec->mLinkerObject; - ref.mOffset = offset; - ref.mHighByte = true; - ref.mLowByte = true; - ref.mRefObject = aexp->mBase->mLinkerObject; - ref.mRefOffset = aexp->mInteger; - mLinker->AddReference(ref); + LinkerReference ref; + ref.mObject = dec->mLinkerObject; + ref.mOffset = offset; + ref.mHighByte = true; + ref.mLowByte = true; + ref.mRefObject = aexp->mBase->mLinkerObject; + ref.mRefOffset = aexp->mInteger; + mLinker->AddReference(ref); + } + else + mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined label"); offset += 2; } diff --git a/oscar64/MachineTypes.h b/oscar64/MachineTypes.h index fcc74fd..027c267 100644 --- a/oscar64/MachineTypes.h +++ b/oscar64/MachineTypes.h @@ -10,13 +10,17 @@ typedef unsigned short uint16; typedef unsigned int uint32; typedef signed char int8; typedef signed short int16; -typedef signed short int32; +typedef signed int int32; #ifdef _WIN32 typedef __int64 int64; typedef unsigned __int64 uint64; #define MAXPATHLEN _MAX_PATH #else +#if __APPLE__ +#include "limits.h" +#else /* __linux__ */ #include "linux/limits.h" +#endif typedef long long int64; typedef unsigned long long uint64; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index cac624c..a6a4404 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -546,6 +546,650 @@ bool NativeCodeInstruction::SameEffectiveAddress(const NativeCodeInstruction& in } } +bool NativeCodeInstruction::ApplySimulation(const NativeRegisterDataSet& data) +{ + switch (mType) + { + case ASMIT_LDA: + case ASMIT_LDX: + case ASMIT_LDY: + case ASMIT_CMP: + case ASMIT_CPX: + case ASMIT_CPY: + if (mMode == ASMIM_ZERO_PAGE && data.mRegs[mAddress].mImmediate) + { + mMode = ASMIM_IMMEDIATE; + mAddress = data.mRegs[mAddress].mValue; + return true; + } + break; + } + + return false; +} + +void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data) +{ + int reg = -1; + if (mMode == ASMIM_ZERO_PAGE) + reg = mAddress; + else if (mMode == ASMIM_IMPLIED) + reg = CPU_REG_A; + + switch (mType) + { + case ASMIT_JSR: + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_X].mImmediate = false; + data.mRegs[CPU_REG_Y].mImmediate = false; + + for (int i = 0; i < 4; i++) + { + data.mRegs[BC_REG_ACCU + i].mImmediate = false; + data.mRegs[BC_REG_WORK + i].mImmediate = false; + data.mRegs[BC_REG_ADDR + i].mImmediate = false; + } + break; + + case ASMIT_ROL: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_C].mImmediate) + { + int t = (data.mRegs[reg].mValue << 1) | data.mRegs[CPU_REG_C].mValue; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[reg].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_ROR: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_C].mImmediate) + { + int t = (data.mRegs[reg].mValue >> 1) | (data.mRegs[CPU_REG_C].mValue << 7); + data.mRegs[CPU_REG_C].mValue = data.mRegs[reg].mValue & 1; + data.mRegs[reg].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_ASL: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + int t = (data.mRegs[reg].mValue << 1); + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[reg].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_LSR: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + int t = (data.mRegs[reg].mValue >> 1); + data.mRegs[CPU_REG_C].mValue = data.mRegs[reg].mValue & 1; + data.mRegs[reg].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_INC: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + data.mRegs[reg].mValue = (data.mRegs[reg].mValue + 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[reg].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + data.mRegs[CPU_REG_Z].mImmediate = false; + break; + + case ASMIT_DEC: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + data.mRegs[reg].mValue = (data.mRegs[reg].mValue + 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[reg].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + data.mRegs[CPU_REG_Z].mImmediate = false; + break; + + case ASMIT_ADC: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_C].mImmediate) + { + int t = data.mRegs[reg].mValue + data.mRegs[CPU_REG_A].mValue + data.mRegs[CPU_REG_C].mValue; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[CPU_REG_A].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_SBC: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_C].mImmediate) + { + int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_A].mValue + data.mRegs[CPU_REG_C].mValue; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[CPU_REG_A].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_AND: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate) + { + int t = data.mRegs[reg].mValue & data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_A].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else if ((data.mRegs[reg].mImmediate && data.mRegs[reg].mValue == 0) || (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == 0)) + { + data.mRegs[CPU_REG_A].mValue = 0; + data.mRegs[CPU_REG_A].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = 0; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_ORA: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate) + { + int t = data.mRegs[reg].mValue | data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_A].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else if ((data.mRegs[reg].mImmediate && data.mRegs[reg].mValue == 0xff) || (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == 0xff)) + { + data.mRegs[CPU_REG_A].mValue = 0xff; + data.mRegs[CPU_REG_A].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = 0xff; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_EOR: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate) + { + int t = data.mRegs[reg].mValue | data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_A].mValue = t & 255; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_INX: + if (data.mRegs[CPU_REG_X].mImmediate) + { + data.mRegs[CPU_REG_X].mValue = (data.mRegs[CPU_REG_X].mValue + 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_DEX: + if (data.mRegs[CPU_REG_X].mImmediate) + { + data.mRegs[CPU_REG_X].mValue = (data.mRegs[CPU_REG_X].mValue - 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_INY: + if (data.mRegs[CPU_REG_Y].mImmediate) + { + data.mRegs[CPU_REG_Y].mValue = (data.mRegs[CPU_REG_Y].mValue + 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_DEY: + if (data.mRegs[CPU_REG_Y].mImmediate) + { + data.mRegs[CPU_REG_Y].mValue = (data.mRegs[CPU_REG_Y].mValue - 1) & 255; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_TXA: + if (data.mRegs[CPU_REG_X].mImmediate) + { + data.mRegs[CPU_REG_A].mValue = data.mRegs[CPU_REG_X].mValue; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_TYA: + if (data.mRegs[CPU_REG_Y].mImmediate) + { + data.mRegs[CPU_REG_A].mValue = data.mRegs[CPU_REG_Y].mValue; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_TAX: + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_X].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_X].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_TAY: + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Y].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_Y].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_CMP: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_A].mImmediate) + { + int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_A].mValue + 1; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_CPX: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_X].mImmediate) + { + int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_X].mValue + 1; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_CPY: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate && data.mRegs[CPU_REG_Y].mImmediate) + { + int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_Y].mValue + 1; + data.mRegs[CPU_REG_C].mValue = t >= 256; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t & 255; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else + { + data.mRegs[CPU_REG_C].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_LDA: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + int t = data.mRegs[reg].mValue; + data.mRegs[CPU_REG_A].mValue = t; + data.mRegs[CPU_REG_A].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + data.mRegs[CPU_REG_A].mValue = mAddress; + data.mRegs[CPU_REG_A].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_A].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_LDX: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + int t = data.mRegs[reg].mValue; + data.mRegs[CPU_REG_X].mValue = t; + data.mRegs[CPU_REG_X].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_X].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + data.mRegs[CPU_REG_X].mValue = mAddress; + data.mRegs[CPU_REG_X].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_X].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_LDY: + if (reg >= 0) + { + if (data.mRegs[reg].mImmediate) + { + int t = data.mRegs[reg].mValue; + data.mRegs[CPU_REG_Y].mValue = t; + data.mRegs[CPU_REG_Y].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = t; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_Y].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + } + else if (mMode == ASMIM_IMMEDIATE) + { + data.mRegs[CPU_REG_Y].mValue = mAddress; + data.mRegs[CPU_REG_Y].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; + data.mRegs[CPU_REG_Z].mImmediate = true; + } + else + { + data.mRegs[CPU_REG_Y].mImmediate = false; + data.mRegs[CPU_REG_Z].mImmediate = false; + } + break; + + case ASMIT_STA: + if (reg >= 0) + { + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[reg].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[reg].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + } + } + break; + + case ASMIT_STX: + if (reg >= 0) + { + if (data.mRegs[CPU_REG_X].mImmediate) + { + data.mRegs[reg].mValue = data.mRegs[CPU_REG_X].mValue; + data.mRegs[reg].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + } + } + break; + + case ASMIT_STY: + if (reg >= 0) + { + if (data.mRegs[CPU_REG_Y].mImmediate) + { + data.mRegs[reg].mValue = data.mRegs[CPU_REG_Y].mValue; + data.mRegs[reg].mImmediate = true; + } + else + { + data.mRegs[reg].mImmediate = false; + } + } + break; + } +} + bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) { bool changed = false; @@ -4169,6 +4813,73 @@ void NativeCodeBasicBlock::CollectEntryBlocks(NativeCodeBasicBlock* block) } } +void NativeCodeBasicBlock::BuildEntryDataSet(const NativeRegisterDataSet& set) +{ + if (!mVisited) + mEntryRegisterDataSet = set; + else + { + bool changed = false; + for (int i = 0; i < NUM_REGS; i++) + { + if (set.mRegs[i].mImmediate) + { + if (mEntryRegisterDataSet.mRegs[i].mImmediate && set.mRegs[i].mValue != mEntryRegisterDataSet.mRegs[i].mValue) + { + mEntryRegisterDataSet.mRegs[i].mImmediate = false; + mVisited = false; + } + } + else if (mEntryRegisterDataSet.mRegs[i].mImmediate) + { + mEntryRegisterDataSet.mRegs[i].mImmediate = false; + mVisited = false; + } + } + } + + if (!mVisited) + { + mVisited = true; + + NativeRegisterDataSet nset = mEntryRegisterDataSet; + + for (int i = 0; i < mIns.Size(); i++) + mIns[i].Simulate(nset); + + if (mTrueJump) + mTrueJump->BuildEntryDataSet(nset); + if (mFalseJump) + mFalseJump->BuildEntryDataSet(nset); + } +} + +bool NativeCodeBasicBlock::ApplyEntryDataSet(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + NativeRegisterDataSet nset = mEntryRegisterDataSet; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].ApplySimulation(nset)) + changed = true; + mIns[i].Simulate(nset); + } + + if (mTrueJump && mTrueJump->ApplyEntryDataSet()) + changed = true; + if (mFalseJump && mFalseJump->ApplyEntryDataSet()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const { if (mIns.Size() > 0) @@ -4544,6 +5255,67 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc) changed = true; } } + else if (mIns[sz - 3].mType == ASMIT_INC && mIns[sz - 3].mMode == ASMIM_ZERO_PAGE && + mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && mIns[sz - 3].mAddress == mIns[sz - 2].mAddress && + mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y)) && + mBranch == ASMIT_BCC) + { + // check for usage of Y register + + bool yother = false, yindex = false, lchanged = false; + int lreg = mIns[sz - 1].mAddress; + int zreg = mIns[sz - 3].mAddress; + + for (int i = 0; i < sz - 4; i++) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].ChangesAddress()) + lchanged = true; + if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY) + yother = true; + else if (mIns[i].mType == ASMIT_LDY) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg) + yindex = true; + else + yother = true; + } + else if (mIns[i].mType == ASMIT_LDX && mIns[i].mAddress == zreg) + yother = true; + else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y)) + yother = true; + } + + if (!yother && !lchanged) + { + NativeCodeBasicBlock* lblock = proc->AllocateBlock(); + NativeCodeBasicBlock* eblock = proc->AllocateBlock(); + for (int i = 0; i + 3 < sz; i++) + { + if (mIns[i].mType != ASMIT_LDY) + lblock->mIns.Push(mIns[i]); + else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg) + lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED)); + } + lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_ZERO_PAGE, lreg)); + lblock->mBranch = mBranch; + lblock->mTrueJump = lblock; + lblock->mFalseJump = eblock; + + eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg)); + eblock->mBranch = ASMIT_JMP; + eblock->mTrueJump = mFalseJump; + eblock->mFalseJump = nullptr; + + mIns.Clear(); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg)); + mBranch = ASMIT_JMP; + mTrueJump = lblock; + mFalseJump = nullptr; + + changed = true; + } + } } @@ -4675,6 +5447,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mLive |= LIVE_CPU_REG_Z; } + else if ( + mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress && !(mIns[i + 0].mLive & LIVE_CPU_REG_A)) + { + mIns[i + 1].mType = ASMIT_STA; + mIns[i + 0].mType = ASMIT_ASL; + mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 0].mLive |= LIVE_CPU_REG_A; + } if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && @@ -4754,11 +5535,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 2].mType = ASMIT_NOP; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && + mIns[i + 1].mType == ASMIT_DEC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 0].mAddress && + !(mIns[i + 2].mLive & (LIVE_CPU_REG_C | LIVE_MEM))) + { + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_SEC; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_SBC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 1; + progress = true; + } #if 1 if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mType == ASMIT_LDA && - mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mLive & (LIVE_MEM | LIVE_CPU_REG_Y))) + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mLive & LIVE_MEM)) { int apos, breg, ireg; if (FindAddressSumY(i, mIns[i + 2].mAddress, apos, breg, ireg)) @@ -4770,6 +5562,11 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[apos + 6].mType = ASMIT_NOP; mIns[apos + 6].mMode = ASMIM_IMPLIED; } + if (mIns[i + 2].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 3, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + mIns[i + 3].mLive |= LIVE_CPU_REG_Y; + } if (mIns[i + 1].mMode != ASMIM_INDIRECT_Y && mIns[i + 1].mMode != ASMIM_ABSOLUTE_Y) { mIns[i + 0].mMode = ASMIM_ZERO_PAGE; @@ -4801,6 +5598,28 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 3].mType = ASMIT_INC; progress = true; } + else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) && + mIns[i + 1].mType == ASMIT_SEC && mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) && + (mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 3].mType = ASMIT_DEC; + progress = true; + } + else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) && + mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && (mIns[i + 2].mAddress & 0xff)== 0xff && + (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) && + (mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 3].mType = ASMIT_DEC; + progress = true; + } } @@ -4880,7 +5699,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void) { if (mBypassed) return this; - else if (!mFalseJump && mCode.Size() == 0) + else if (!mFalseJump && mCode.Size() == 0 && this != mTrueJump) return mTrueJump->BypassEmptyBlocks(); else { @@ -4931,7 +5750,7 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target) } else if (mTrueJump) { - if (mTrueJump->mOffset != next) + if (mTrueJump == this || mTrueJump->mOffset != next) { next += PutJump(proc, mTrueJump->mOffset - next); } @@ -5286,6 +6105,14 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) if (entryBlock->JoinTailCodeSequences()) changed = true; + ResetVisited(); + NativeRegisterDataSet data; + entryBlock->BuildEntryDataSet(data); + + ResetVisited(); + if (entryBlock->ApplyEntryDataSet()) + changed = true; + } while (changed); #endif @@ -5510,7 +6337,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode } break; case IC_RELATIONAL_OPERATOR: - if (iblock->mInstructions[i + 1]->mCode == IC_BRANCH && iblock->mInstructions[i + 1]->mSFinal[0]) + if (i + 1 < iblock->mInstructions.Size() && iblock->mInstructions[i + 1]->mCode == IC_BRANCH && iblock->mInstructions[i + 1]->mSFinal[0]) { block->RelationalOperator(iproc, ins, this, CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump)); return; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index f99be0c..b6458b4 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -26,6 +26,7 @@ struct NativeRegisterDataSet void ResetZeroPage(int addr); }; + static const uint32 NCIF_LOWER = 0x00000001; static const uint32 NCIF_UPPER = 0x00000002; static const uint32 NCIF_RUNTIME = 0x00000004; @@ -48,6 +49,8 @@ public: bool IsUsedResultInstructions(NumberSet& requiredTemps); bool ValueForwarding(NativeRegisterDataSet& data); + void Simulate(NativeRegisterDataSet& data); + bool ApplySimulation(const NativeRegisterDataSet& data); bool LoadsAccu(void) const; bool ChangesAccuAndFlag(void) const; @@ -141,6 +144,10 @@ public: bool JoinTailCodeSequences(void); bool SameTail(const NativeCodeInstruction& ins) const; + NativeRegisterDataSet mEntryRegisterDataSet; + + void BuildEntryDataSet(const NativeRegisterDataSet& set); + bool ApplyEntryDataSet(void); }; class NativeCodeProcedure diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 1253a78..eb44fb7 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1920,7 +1920,7 @@ Expression* Parser::ParseAssemblerAddOperand(void) { Declaration* ndec = new Declaration(mScanner->mLocation, DT_VARIABLE_REF); ndec->mBase = nexp->mLeft->mDecValue; - ndec->mOffset = int(nexp->mRight->mDecValue->mInteger); + ndec->mOffset = nexp->mToken == TK_SUB ? -int(nexp->mRight->mDecValue->mInteger) : int(nexp->mRight->mDecValue->mInteger); exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = ndec; } @@ -1933,7 +1933,7 @@ Expression* Parser::ParseAssemblerAddOperand(void) { Declaration* ndec = new Declaration(mScanner->mLocation, DT_FUNCTION_REF); ndec->mBase = nexp->mLeft->mDecValue; - ndec->mOffset = int(nexp->mRight->mDecValue->mInteger); + ndec->mOffset = nexp->mToken == TK_SUB ? -int(nexp->mRight->mDecValue->mInteger) : int(nexp->mRight->mDecValue->mInteger); exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = ndec; } @@ -1946,7 +1946,7 @@ Expression* Parser::ParseAssemblerAddOperand(void) { Declaration* ndec = new Declaration(mScanner->mLocation, DT_LABEL_REF); ndec->mBase = nexp->mLeft->mDecValue; - ndec->mOffset = int(nexp->mRight->mDecValue->mInteger); + ndec->mOffset = nexp->mToken == TK_SUB ? -int(nexp->mRight->mDecValue->mInteger) : int(nexp->mRight->mDecValue->mInteger); exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = ndec; }