Strcpy as intrinsic
This commit is contained in:
parent
7e340cc816
commit
135d357dbc
|
@ -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
|
||||
|
|
|
@ -144,6 +144,7 @@ enum ByteCode
|
|||
|
||||
BC_COPY,
|
||||
BC_COPY_LONG,
|
||||
BC_STRCPY,
|
||||
|
||||
BC_EXTRT,
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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]));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,6 +22,7 @@ enum InterCode
|
|||
IC_LOAD,
|
||||
IC_LEA,
|
||||
IC_COPY,
|
||||
IC_STRCPY,
|
||||
IC_TYPECAST,
|
||||
IC_CONSTANT,
|
||||
IC_BRANCH,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue