diff --git a/autotest/autotest.bat b/autotest/autotest.bat index c35817a..4f666e7 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -96,6 +96,9 @@ if %errorlevel% neq 0 goto :error call :test structassigntest.c if %errorlevel% neq 0 goto :error +call :test structmembertest.c +if %errorlevel% neq 0 goto :error + exit /b 0 :error diff --git a/autotest/structmembertest.c b/autotest/structmembertest.c new file mode 100644 index 0000000..f59b361 --- /dev/null +++ b/autotest/structmembertest.c @@ -0,0 +1,50 @@ +#include + +struct A +{ + int x[100], y[100]; +}; + +struct V +{ + int x, y, z; +}; + + +void copy(A * a) +{ + for(int i=0; i<100; i++) + a->x[i] = a->y[i]; +} + +void shuffle(V * v) +{ + for(int i=0; i<100; i++) + v[i].x = v[i].y; +} + +int main(void) +{ + A a; + V v[100]; + + for(int i=0; i<100; i++) + { + a.y[i] = i; + v[i].y = i; + } + + copy(&a); + shuffle(v); + + for(int i=0; i<100; i++) + { + assert(a.x[i] == i); + assert(v[i].x == i); + } + + return 0; +} + + + diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 212a596..939856b 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -2068,6 +2068,68 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn } } +void ByteCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins) +{ + int ri = rins->mSrc[0].mIntConst, wi = wins->mSrc[1].mIntConst; + + if (ri < 252 && wi < 252 && rins->mSrc[0].mTemp == wins->mSrc[1].mTemp && rins->mSrc[0].mMemory == IM_INDIRECT && wins->mSrc[1].mMemory == IM_INDIRECT) + { + ByteCodeInstruction lins(BC_ADDR_REG); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp]; + lins.mRegisterFinal = wins->mSrc[1].mFinal; + mIns.Push(lins); + + if (InterTypeSize[rins->mDst.mType] == 1) + { + ByteCodeInstruction bins(BC_LOAD_ADDR_8); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp]; + bins.mValue = ri; + mIns.Push(bins); + } + else if (InterTypeSize[rins->mDst.mType] == 2) + { + ByteCodeInstruction bins(BC_LOAD_ADDR_16); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp]; + bins.mValue = ri; + mIns.Push(bins); + } + else if (InterTypeSize[rins->mDst.mType] == 4) + { + ByteCodeInstruction bins(BC_LOAD_ADDR_32); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp]; + bins.mValue = ri; + mIns.Push(bins); + } + + if (InterTypeSize[wins->mSrc[0].mType] == 1) + { + ByteCodeInstruction bins(BC_STORE_ADDR_8); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp]; + bins.mValue = wi; + mIns.Push(bins); + } + else if (InterTypeSize[wins->mSrc[0].mType] == 2) + { + ByteCodeInstruction bins(BC_STORE_ADDR_16); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp]; + bins.mValue = wi; + mIns.Push(bins); + } + else if (InterTypeSize[wins->mSrc[0].mType] == 4) + { + ByteCodeInstruction bins(BC_STORE_ADDR_32); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp]; + bins.mValue = wi; + mIns.Push(bins); + } + } + else + { + LoadDirectValue(proc, rins); + StoreDirectValue(proc, wins); + } +} + void ByteCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins) { if (ins->mSrc[0].mTemp < 0) @@ -3125,7 +3187,13 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p StoreDirectValue(iproc, ins); break; case IC_LOAD: - LoadDirectValue(iproc, ins); + if (i + 1 < sblock->mInstructions.Size() && sblock->mInstructions[i + 1]->mCode == IC_STORE && ins->mDst.mTemp == sblock->mInstructions[i + 1]->mSrc[0].mTemp) + { + LoadStoreIndirectValue(iproc, ins, sblock->mInstructions[i + 1]); + i++; + } + else + LoadDirectValue(iproc, ins); break; case IC_COPY: CopyValue(iproc, ins); diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index 2fc17cd..cb8cf48 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -255,6 +255,8 @@ public: void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins); void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); + void LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins); + void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, const InterInstruction * ins); void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 46afd1c..d8334da 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3787,7 +3787,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa { if (sins->mSrc[1].mTemp >= 0) { - if (ins->mSrc[0].mMemory != IM_PARAM || aliasedParams[ins->mSrc[0].mVarIndex]) + if ((ins->mSrc[0].mMemory != IM_PARAM && ins->mSrc[0].mMemory != IM_FPARAM) || aliasedParams[ins->mSrc[0].mVarIndex]) ins->mInvariant = false; } else if (ins->mSrc[0].mMemory == sins->mSrc[1].mMemory && ins->mSrc[0].mVarIndex == sins->mSrc[1].mVarIndex && ins->mSrc[0].mLinkerObject == sins->mSrc[1].mLinkerObject) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 8e2f695..7d0f50f 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3217,15 +3217,29 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins) { int size = InterTypeSize[wins->mSrc[0].mType]; + int ri = rins->mSrc[0].mIntConst, wi = wins->mSrc[1].mIntConst; - mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp])); - for (int i = 1; i < size; i++) + if (ri == wi) { - mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ri)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp])); + for (int i = 1; i < size; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp])); + } + } + else + { + for (int i = 0; i < size; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ri + i)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, wi + i)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp])); + } } } @@ -8801,7 +8815,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal && ins->mSrc[0].mMemory == IM_INDIRECT && iblock->mInstructions[i + 1]->mSrc[1].mMemory == IM_INDIRECT && - ins->mSrc[0].mIntConst == 0 && iblock->mInstructions[i + 1]->mSrc[1].mIntConst == 0) + ins->mSrc[0].mIntConst <= 252 && iblock->mInstructions[i + 1]->mSrc[1].mIntConst <= 252) { block->LoadStoreIndirectValue(iproc, ins, iblock->mInstructions[i + 1]); i++;