Strcpy as intrinsic

This commit is contained in:
drmortalwombat 2021-10-31 19:14:07 +01:00
parent 7e340cc816
commit 135d357dbc
14 changed files with 167 additions and 28 deletions

View File

@ -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

View File

@ -144,6 +144,7 @@ enum ByteCode
BC_COPY,
BC_COPY_LONG,
BC_STRCPY,
BC_EXTRT,

View File

@ -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
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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]));

View File

@ -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;

View File

@ -22,6 +22,7 @@ enum InterCode
IC_LOAD,
IC_LEA,
IC_COPY,
IC_STRCPY,
IC_TYPECAST,
IC_CONSTANT,
IC_BRANCH,

View File

@ -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;

View File

@ -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)

View File

@ -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);