From 135d357dbc0f3b1660d634db65522bb57b696d53 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 31 Oct 2021 19:14:07 +0100 Subject: [PATCH] Strcpy as intrinsic --- include/crt.c | 26 ++++++++++++++---- include/crt.h | 1 + include/string.c | 30 ++++++++++++--------- include/string.h | 2 ++ oscar64/ByteCodeGenerator.cpp | 23 +++++++++++++++- oscar64/ByteCodeGenerator.h | 2 ++ oscar64/Declaration.cpp | 12 +++++++++ oscar64/Declaration.h | 1 + oscar64/Disassembler.cpp | 3 +++ oscar64/InterCode.cpp | 14 ++++++---- oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 47 ++++++++++++++++++++++++++++++--- oscar64/NativeCodeGenerator.cpp | 32 ++++++++++++++++++++++ oscar64/NativeCodeGenerator.h | 1 + 14 files changed, 167 insertions(+), 28 deletions(-) diff --git a/include/crt.c b/include/crt.c index c757748..5219457 100644 --- a/include/crt.c +++ b/include/crt.c @@ -276,10 +276,6 @@ __asm negtmp32 __asm divmod { - lda #0 - sta tmp + 2 - sta tmp + 3 - lda accu + 1 bne WB lda tmp + 1 @@ -287,7 +283,8 @@ __asm divmod // byte / byte BB: - lda #0 + // accu is zero at this point + sta tmp + 3 ldx #4 asl accu LBB1: rol @@ -325,6 +322,7 @@ WB: // word / byte lda #0 + sta tmp + 3 ldx #16 asl accu rol accu + 1 @@ -341,6 +339,10 @@ WWB1: rol accu // word / word WW: + lda #0 + sta tmp + 2 + sta tmp + 3 + sty tmpy ldy #16 clc @@ -2296,6 +2298,20 @@ W1: #pragma bytecode(BC_COPY, inp_copy) +__asm inp_strcpy +{ + sty tmpy + ldy #$ff +L1: iny + lda (accu), y + sta (addr), y + bne L1 + ldy tmpy + jmp startup.exec +} + +#pragma bytecode(BC_STRCPY, inp_strcpy) + __asm inp_copyl { jmp startup.exec diff --git a/include/crt.h b/include/crt.h index 09691cc..3d82972 100644 --- a/include/crt.h +++ b/include/crt.h @@ -144,6 +144,7 @@ enum ByteCode BC_COPY, BC_COPY_LONG, + BC_STRCPY, BC_EXTRT, diff --git a/include/string.c b/include/string.c index d0a60b4..25c4412 100644 --- a/include/string.c +++ b/include/string.c @@ -48,7 +48,13 @@ int strcmp(const char * ptr1, const char * ptr2) __asm { ldy #0 + sty accu + 1 L1: lda (ptr1), y + beq W1 + cmp (ptr2), y + bne W2 + iny + lda (ptr1), y beq W1 cmp (ptr2), y bne W2 @@ -57,22 +63,20 @@ int strcmp(const char * ptr1, const char * ptr2) inc ptr1 + 1 inc ptr2 + 1 bne L1 - W2: bcs gt - lda #$ff - sta accu - bmi E - - gt: lda #$01 - sta accu - lda #$00 - beq E W1: cmp (ptr2), y - bne W2 - lda #$00 - sta accu - E: + beq E + + W2: bcs W3 + + lda #$ff sta accu + 1 + bmi E + + W3: lda #$01 + + E: + sta accu } } diff --git a/include/string.h b/include/string.h index 5aa4102..75396e6 100644 --- a/include/string.h +++ b/include/string.h @@ -19,6 +19,8 @@ int memcmp(const void * ptr1, const void * ptr2, int size); void * memmove(void * dst, const void * src, int size); +#pragma intrinsic(strcpy) + #pragma compile("string.c") #endif diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 29ff8d4..dba9005 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -115,7 +115,7 @@ bool ByteCodeInstruction::IsLocalStore(void) const bool ByteCodeInstruction::IsLocalLoad(void) const { - return mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32 || mCode == BC_COPY; + return mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32 || mCode == BC_COPY || mCode == BC_STRCPY; } bool ByteCodeInstruction::IsLocalAccess(void) const @@ -511,6 +511,10 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl } break; + case BC_STRCPY: + block->PutCode(generator, BC_STRCPY); + break; + case BC_CONV_I16_I32: case BC_CONV_U16_U32: case BC_OP_NEGATE_32: @@ -770,6 +774,20 @@ void ByteCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruct mIns.Push(cins); } +void ByteCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins) +{ + ByteCodeInstruction sins(BC_ADDR_REG); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + sins.mRegisterFinal = ins->mSrc[1].mFinal; + mIns.Push(sins); + ByteCodeInstruction dins(BC_LOAD_REG_16); + dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + dins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(dins); + ByteCodeInstruction cins(BC_STRCPY); + mIns.Push(cins); +} + void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins) { if (ins->mSrc[0].mType == IT_FLOAT) @@ -3198,6 +3216,9 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p case IC_COPY: CopyValue(iproc, ins); break; + case IC_STRCPY: + StrcpyValue(iproc, ins); + break; case IC_LOAD_TEMPORARY: { if (ins->mSrc[0].mTemp != ins->mDst.mTemp) diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index cb8cf48..8c87237 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -145,6 +145,7 @@ enum ByteCode BC_COPY, BC_COPY_LONG, + BC_STRCPY, BC_EXTRT, @@ -252,6 +253,7 @@ public: void FloatConstToAccu(double val); void FloatConstToWork(double val); void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins); + void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins); void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins); void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 204f375..3907a77 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -512,6 +512,7 @@ bool Declaration::IsSimpleType(void) const Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration; Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; +Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; void InitDeclarations(void) { @@ -571,4 +572,15 @@ void InitDeclarations(void) TheFloatTypeDeclaration = new Declaration(noloc, DT_TYPE_FLOAT); TheFloatTypeDeclaration->mSize = 4; TheFloatTypeDeclaration->mFlags = DTF_DEFINED | DTF_SIGNED; + + + TheCharPointerTypeDeclaration = new Declaration(noloc, DT_TYPE_POINTER); + TheCharPointerTypeDeclaration->mBase = TheCharTypeDeclaration; + TheCharPointerTypeDeclaration->mSize = 2; + TheCharPointerTypeDeclaration->mFlags = DTF_DEFINED; + + TheConstCharPointerTypeDeclaration = new Declaration(noloc, DT_TYPE_POINTER); + TheConstCharPointerTypeDeclaration->mBase = TheConstCharTypeDeclaration; + TheConstCharPointerTypeDeclaration->mSize = 2; + TheConstCharPointerTypeDeclaration->mFlags = DTF_DEFINED; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 332d0e5..047e15e 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -190,4 +190,5 @@ void InitDeclarations(void); extern Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration; extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; +extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 62db070..f544e21 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -372,6 +372,9 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star fprintf(file, "COPY\t#%d", memory[start + i + 0]); i++; break; + case BC_STRCPY: + fprintf(file, "STRCPY"); + break; case BC_COPY_LONG: fprintf(file, "COPYL\t#%d", uint16(memory[start + i + 0] + 256 * memory[start + i + 1])); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 3c77e53..1c64103 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -623,6 +623,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr InsertValue(ins); break; case IC_COPY: + case IC_STRCPY: i = 0; while (i < mNum) { @@ -1319,7 +1320,7 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV requiredVars += mSrc[1].mVarIndex; } } - else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE) + else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY) { requiredVars.OrNot(providedVars); } @@ -1587,7 +1588,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(const GrowingVariable } } } - else if (mCode == IC_COPY) + else if (mCode == IC_COPY || mCode == IC_STRCPY) { requiredVars.Fill(); } @@ -1883,6 +1884,9 @@ void InterInstruction::Disassemble(FILE* file) case IC_COPY: fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); break; + case IC_STRCPY: + fprintf(file, "STRCPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); + break; case IC_LEA: fprintf(file, "LEA%c", memchars[mSrc[1].mMemory]); break; @@ -3814,7 +3818,7 @@ bool InterCodeBasicBlock::IsLeafProcedure(void) static bool CanBypassLoad(const InterInstruction * lins, const InterInstruction * bins) { // Check ambiguity - if (bins->mCode == IC_STORE || bins->mCode == IC_COPY) + if (bins->mCode == IC_STORE || bins->mCode == IC_COPY || bins->mCode == IC_STRCPY) return false; // Side effects @@ -3860,7 +3864,7 @@ static bool CanBypass(const InterInstruction* lins, const InterInstruction* bins static bool CanBypassStore(const InterInstruction * sins, const InterInstruction * bins) { - if (bins->mCode == IC_COPY || bins->mCode == IC_PUSH_FRAME) + if (bins->mCode == IC_COPY || bins->mCode == IC_STRCPY || bins->mCode == IC_PUSH_FRAME) return false; InterMemory sm = IM_NONE, bm = IM_NONE; @@ -4029,7 +4033,7 @@ InterCodeBasicBlock* InterCodeBasicBlock::PropagateDominator(InterCodeProcedure* bool IsMoveable(InterCode code) { - if (HasSideEffect(code) || code == IC_COPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME) + if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME) return false; if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE) return false; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index b6cd1c4..99e22da 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -22,6 +22,7 @@ enum InterCode IC_LOAD, IC_LEA, IC_COPY, + IC_STRCPY, IC_TYPECAST, IC_CONSTANT, IC_BRANCH, diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 0da14bb..ed3cdbc 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1834,12 +1834,51 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(TheFloatTypeDeclaration, ins->mDst.mTemp); } - else - mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname->mString); + else if (!strcmp(iname->mString, "strcpy")) + { + if (exp->mRight->mType == EX_LIST) + { + Expression* tex = exp->mRight->mLeft, * sex = exp->mRight->mRight; + if ((tex->mDecType->mType == DT_TYPE_ARRAY && tex->mDecType->mSize <= 256) || + (sex->mDecType->mType == DT_TYPE_ARRAY && sex->mDecType->mSize <= 256)) + { + vl = TranslateExpression(procType, proc, block, tex, breakBlock, continueBlock, inlineMapper); + if (vl.mType->mType == DT_TYPE_ARRAY) + vl = Dereference(proc, block, vl, 1); + else + vl = Dereference(proc, block, vl); - return ExValue(TheVoidTypeDeclaration); + vr = TranslateExpression(procType, proc, block, sex, breakBlock, continueBlock, inlineMapper); + if (vr.mType->mType == DT_TYPE_ARRAY) + vr = Dereference(proc, block, vr, 1); + else + vr = Dereference(proc, block, vr); + + if (!TheCharPointerTypeDeclaration->CanAssign(vl.mType)) + mErrors->Error(tex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + if (!TheConstCharPointerTypeDeclaration->CanAssign(vr.mType)) + mErrors->Error(sex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + + InterInstruction* ins = new InterInstruction(); + ins->mCode = IC_STRCPY; + ins->mSrc[0].mType = IT_POINTER; + ins->mSrc[0].mTemp = vr.mTemp; + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = vl.mTemp; + block->Append(ins); + + return vl; + } + } + } + else + { + mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname->mString); + return ExValue(TheVoidTypeDeclaration); + } } - else if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10)) + + if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10)) { Declaration* fdec = exp->mLeft->mDecValue; Expression* fexp = fdec->mValue; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 65da3a7..7ebac58 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -742,6 +742,12 @@ bool NativeCodeInstruction::ApplySimulation(const NativeRegisterDataSet& data) mAddress = data.mRegs[mAddress].mValue + 256 * data.mRegs[mAddress + 1].mValue; mLinkerObject = nullptr; } + else if (mMode == ASMIM_INDIRECT_Y && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject) + { + mMode = ASMIM_ABSOLUTE_Y; + mLinkerObject = data.mRegs[mAddress].mLinkerObject; + mAddress = data.mRegs[mAddress].mValue; + } return false; } @@ -1956,6 +1962,12 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT { mAddress = data.mRegs[mAddress].mValue; } + else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject) + { + mMode = ASMIM_ABSOLUTE_Y; + mLinkerObject = data.mRegs[mAddress].mLinkerObject; + mAddress = data.mRegs[mAddress + 1].mValue; + } if (ChangesAddress()) data.ResetIndirect(); @@ -4234,6 +4246,23 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, } } +NativeCodeBasicBlock* NativeCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) +{ + int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0xff)); + this->Close(lblock, nullptr, ASMIT_JMP); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg)); + lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg)); + lblock->Close(lblock, eblock, ASMIT_BNE); + + return eblock; +} + bool NativeCodeBasicBlock::CheckPredAccuStore(int reg) { if (mIns.Size() < 8) @@ -10680,6 +10709,9 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode case IC_COPY: block = block->CopyValue(iproc, ins, this); break; + case IC_STRCPY: + block = block->StrcpyValue(iproc, ins, this); + break; case IC_LOAD_TEMPORARY: { if (ins->mSrc[0].mTemp != ins->mDst.mTemp) diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 5fa3f65..4f1970e 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -147,6 +147,7 @@ public: void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0); void NumericConversion(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc); + NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);