From e2e20581a6eaaaa0062b55e273492124b083f920 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 14 Sep 2021 16:34:48 +0200 Subject: [PATCH] Prepare byte level optimisations --- autotest/arraytestfloat.c | 2 + include/crt.c | 80 ++---- include/crt.h | 2 + oscar64/ByteCodeGenerator.cpp | 114 +++++++-- oscar64/ByteCodeGenerator.h | 2 + oscar64/Declaration.cpp | 9 +- oscar64/Declaration.h | 2 +- oscar64/Emulator.cpp | 2 +- oscar64/InterCode.cpp | 106 ++++---- oscar64/InterCode.h | 18 +- oscar64/InterCodeGenerator.cpp | 420 ++++++++++++++++++-------------- oscar64/NativeCodeGenerator.cpp | 320 ++++++++++++++++++++---- oscar64/NativeCodeGenerator.h | 5 +- oscar64/Parser.cpp | 55 ++++- oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + 16 files changed, 762 insertions(+), 379 deletions(-) diff --git a/autotest/arraytestfloat.c b/autotest/arraytestfloat.c index 398a43b..f2e70fb 100644 --- a/autotest/arraytestfloat.c +++ b/autotest/arraytestfloat.c @@ -8,6 +8,7 @@ float sum(float * a, int s) { sum += a[i]; } + return sum; } @@ -18,6 +19,7 @@ int main(void) { a[i] = i % 10; } + assert(sum(a, 100) == 450); return 0; } diff --git a/include/crt.c b/include/crt.c index 07aad59..772c12b 100644 --- a/include/crt.c +++ b/include/crt.c @@ -223,71 +223,6 @@ L2: jsr divmod #pragma runtime(divs16, divs16); #pragma runtime(mods16, mods16); -/* -!align 255, 0 -inptable - !word inp_nop - !word inp_exit - - !word inp_const_p8, inp_const_n8, inp_const_16, inp_const_32 - - !word inp_load_reg_16, inp_store_reg_16, inp_addr_reg, inp_load_reg_32, inp_store_reg_32 - - !word inp_load_abs_u8, inp_load_abs_s8, inp_load_abs_16, inp_load_abs_32 - !word inp_store_abs_8, inp_store_abs_16, inp_store_abs_32 - !word inp_lea_abs - - !word inp_load_local_u8, inp_load_local_s8, inp_load_local_16, inp_load_local_32 - !word inp_store_local_8, inp_store_local_16, inp_store_local_32 - !word inp_lea_local - - !word inp_store_frame_8, inp_store_frame_16, inp_store_frame_32 - - !word inp_load_addr_u8, inp_load_addr_s8, inp_load_addr_16, inp_load_addr_32 - !word inp_store_addr_8, inp_store_addr_16, inp_store_addr_32 - - !word inp_binop_addr_16, inp_binop_subr_16 - !word inp_binop_andr_16, inp_binop_orr_16, inp_binop_xorr_16 - !word inp_binop_mulr_16, inp_binop_divr_u16, inp_binop_modr_u16, inp_binop_divr_s16, inp_binop_modr_s16 - !word inp_binop_shlr_16, inp_binop_shrr_u16, inp_binop_shrr_s16 - - !word inp_binop_addi_16, inp_binop_subi_16, inp_binop_andi_16, inp_binop_ori_16, inp_binop_muli8_16 - !word inp_binop_shli_16, inp_binop_shri_u16, inp_binop_shri_s16 - - !word inp_binop_cmpr_u16, inp_binop_cmpr_s16 - !word inp_binop_cmpi_u16, inp_binop_cmpi_s16 - - !word inp_op_negate_16, inp_op_invert_16 - - !word inp_binop_add_f32, inp_binop_sub_f32, inp_binop_mul_f32, inp_binop_div_f32 - !word inp_binop_cmp_f32 - !word inp_op_negate_f32, inp_op_abs_f32, inp_op_floor_f32, inp_op_ceil_f32 - - !word inp_conv_u16_f32, inp_conv_i16_f32, inp_conv_f32_u16, inp_conv_f32_i16 - - !word inp_jumps - !word inp_branchs_eq, inp_branchs_ne - !word inp_branchs_gt, inp_branchs_ge - !word inp_branchs_lt, inp_branchs_le - - !word inp_jumpf - !word inp_branchf_eq, inp_branchf_ne - !word inp_branchf_gt, inp_branchf_ge - !word inp_branchf_lt, inp_branchf_le - - !word inp_set_eq, inp_set_ne - !word inp_set_gt, inp_set_ge - !word inp_set_lt, inp_set_le - - !word inp_enter - !word inp_return - !word inp_call - !word inp_push_frame, inp_pop_frame - - !word inp_jsr - - !word inp_copy, inp_copyl -*/ __asm inp_nop { @@ -481,6 +416,21 @@ __asm inp_store_reg_32 #pragma bytecode(BC_STORE_REG_32, inp_store_reg_32) +__asm inp_conv_s8_s16 +{ + lda (ip), y + tax + iny + lda #$80 + and $00, x + bpl W1 + lda #$ff +W1: sta $01, x + jmp startup.exec +} + +#pragma bytecode(BC_CONV_I8_I16, inp_conv_s8_s16) + __asm inp_addr_reg { lda (ip), y diff --git a/include/crt.h b/include/crt.h index c173e41..f86df3c 100644 --- a/include/crt.h +++ b/include/crt.h @@ -113,6 +113,8 @@ enum ByteCode BC_CONV_F32_U16, BC_CONV_F32_I16, + BC_CONV_I8_I16, + BC_JUMPS, BC_BRANCHS_EQ, BC_BRANCHS_NE, diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 8a3b806..46e5ef2 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -364,6 +364,11 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl block->PutCode(generator, mCode); break; + case BC_CONV_I8_I16: + block->PutCode(generator, mCode); + block->PutByte(mRegister); + break; + case BC_JUMPS: case BC_BRANCHS_EQ: case BC_BRANCHS_NE: @@ -1371,7 +1376,7 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn { if (ins.mMemory == IM_GLOBAL) { - ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_ABS_I8 : BC_LOAD_ABS_U8); + ByteCodeInstruction bins(BC_LOAD_ABS_U8); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[0]; @@ -1380,7 +1385,7 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn } else if (ins.mMemory == IM_ABSOLUTE) { - ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_ABS_I8 : BC_LOAD_ABS_U8); + ByteCodeInstruction bins(BC_LOAD_ABS_U8); bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); @@ -1395,7 +1400,7 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn if (index <= 255) { - ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_LOCAL_I8 : BC_LOAD_LOCAL_U8); + ByteCodeInstruction bins(BC_LOAD_LOCAL_U8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = index; mIns.Push(bins); @@ -1406,7 +1411,7 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn lins.mRegister = BC_REG_ADDR; lins.mValue = index; mIns.Push(lins); - ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_ADDR_I8 : BC_LOAD_ADDR_U8); + ByteCodeInstruction bins(BC_LOAD_ADDR_U8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = 0; mIns.Push(bins); @@ -1471,20 +1476,10 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn if (ins.mOperandSize == 1) { - if (ins.mTType == IT_SIGNED) - { - ByteCodeInstruction bins(BC_LOAD_ADDR_I8); - bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; - bins.mValue = ins.mSIntConst[0]; - mIns.Push(bins); - } - else - { - ByteCodeInstruction bins(BC_LOAD_ADDR_U8); - bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; - bins.mValue = ins.mSIntConst[0]; - mIns.Push(bins); - } + ByteCodeInstruction bins(BC_LOAD_ADDR_U8); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + bins.mValue = ins.mSIntConst[0]; + mIns.Push(bins); } else if (ins.mOperandSize == 2) { @@ -1820,7 +1815,8 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); - ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_CONV_F32_I16 : BC_CONV_F32_U16); + ByteCodeInstruction bins(BC_CONV_F32_I16); +// ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_CONV_F32_I16 : BC_CONV_F32_U16); mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_16); @@ -1835,7 +1831,8 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); - ByteCodeInstruction bins(ins.mSType[0] == IT_SIGNED ? BC_CONV_I16_F32 : BC_CONV_U16_F32); + ByteCodeInstruction bins(BC_CONV_I16_F32); +// ByteCodeInstruction bins(ins.mSType[0] == IT_SIGNED ? BC_CONV_I16_F32 : BC_CONV_U16_F32); mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_32); @@ -1843,6 +1840,59 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter mIns.Push(sins); } break; + case IA_EXT8TO16S: + { + if (ins.mSTemp[0] == ins.mTTemp) + { + ByteCodeInstruction cins(BC_CONV_I8_I16); + cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + cins.mRegisterFinal = ins.mSFinal[0]; + mIns.Push(cins); + } + else + { + ByteCodeInstruction lins(BC_LOAD_REG_16); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; + lins.mRegisterFinal = ins.mSFinal[0]; + mIns.Push(lins); + + ByteCodeInstruction cins(BC_CONV_I8_I16); + cins.mRegister = BC_REG_ACCU; + mIns.Push(cins); + + ByteCodeInstruction sins(BC_STORE_REG_16); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + mIns.Push(sins); + } + } break; + case IA_EXT8TO16U: + { + if (ins.mSTemp[0] == ins.mTTemp) + { + ByteCodeInstruction cins(BC_BINOP_ANDI_16); + cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + cins.mRegisterFinal = ins.mSFinal[0]; + cins.mValue = 0x00ff; + mIns.Push(cins); + } + else + { + ByteCodeInstruction lins(BC_LOAD_REG_16); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; + lins.mRegisterFinal = ins.mSFinal[0]; + mIns.Push(lins); + + ByteCodeInstruction cins(BC_BINOP_ANDI_16); + cins.mRegister = BC_REG_ACCU; + cins.mValue = 0x00ff; + mIns.Push(cins); + + ByteCodeInstruction sins(BC_STORE_REG_16); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; + mIns.Push(sins); + } + } break; + } } @@ -2622,7 +2672,24 @@ void ByteCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mCode = BC_NOP; progress = true; } - + else if (mIns[i].mCode == BC_LOAD_ABS_U8 && mIns[i + 1].mCode == BC_CONV_I8_I16 && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal) + { + mIns[i].mCode = BC_LOAD_ABS_I8; + mIns[i + 1].mCode = BC_NOP; + progress = true; + } + else if (mIns[i].mCode == BC_LOAD_LOCAL_U8 && mIns[i + 1].mCode == BC_CONV_I8_I16 && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal) + { + mIns[i].mCode = BC_LOAD_LOCAL_I8; + mIns[i + 1].mCode = BC_NOP; + progress = true; + } + else if (mIns[i].mCode == BC_LOAD_ADDR_U8 && mIns[i + 1].mCode == BC_CONV_I8_I16 && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal) + { + mIns[i].mCode = BC_LOAD_ADDR_I8; + mIns[i + 1].mCode = BC_NOP; + progress = true; + } } if ((mIns[i].mCode == BC_LOAD_REG_16 || mIns[i].mCode == BC_STORE_REG_16 || mIns[i].mCode == BC_LOAD_REG_32 || mIns[i].mCode == BC_STORE_REG_32) && accuTemp == mIns[i].mRegister) @@ -3206,6 +3273,11 @@ void ByteCodeProcedure::Disassemble(FILE * file, ByteCodeGenerator * generator, i += 2; break; + case BC_CONV_I8_I16: + fprintf(file, "SEXT8\t%s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); + i ++; + break; + case BC_BINOP_SHLI_16: fprintf(file, "SHL\tACCU, #%d", uint8(generator->mMemory[mProgStart + i + 0])); i += 1; diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index c9a6a10..0bd4ff7 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -102,6 +102,8 @@ enum ByteCode BC_CONV_F32_U16, BC_CONV_F32_I16, + BC_CONV_I8_I16, + BC_JUMPS, BC_BRANCHS_EQ, BC_BRANCHS_NE, diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 271296b..ae22900 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -470,7 +470,7 @@ bool Declaration::IsNumericType(void) const return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM; } -Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstSignedCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration, * TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration; +Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration, * TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration; void InitDeclarations(void) { @@ -495,13 +495,14 @@ void InitDeclarations(void) TheSignedCharTypeDeclaration->mSize = 1; TheSignedCharTypeDeclaration->mFlags = DTF_DEFINED | DTF_SIGNED; - TheConstSignedCharTypeDeclaration = new Declaration(noloc, DT_TYPE_INTEGER); - TheConstSignedCharTypeDeclaration->mSize = 1; - TheConstSignedCharTypeDeclaration->mFlags = DTF_DEFINED | DTF_SIGNED | DTF_CONST; + TheConstCharTypeDeclaration = new Declaration(noloc, DT_TYPE_INTEGER); + TheConstCharTypeDeclaration->mSize = 1; + TheConstCharTypeDeclaration->mFlags = DTF_DEFINED | DTF_CONST; TheUnsignedCharTypeDeclaration = new Declaration(noloc, DT_TYPE_INTEGER); TheUnsignedCharTypeDeclaration->mSize = 1; TheUnsignedCharTypeDeclaration->mFlags = DTF_DEFINED; + TheCharTypeDeclaration = TheUnsignedCharTypeDeclaration; TheBoolTypeDeclaration = new Declaration(noloc, DT_TYPE_BOOL); TheBoolTypeDeclaration->mSize = 1; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d4ddf42..c1ce332 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -166,4 +166,4 @@ public: void InitDeclarations(void); -extern Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstSignedCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration, * TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration; +extern Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration, * TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration; diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index c1cce7e..447a91b 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -65,7 +65,7 @@ void Emulator::DumpCycles(void) } printf("Total Cycles %d\n", totalCycles); -// return; + return; for (int i = 0; i < numTops; i++) { diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index b3a761c..3c623db 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -226,6 +226,33 @@ static double ConstantFolding(InterOperator oper, double val1, double val2 = 0.0 } } +static void ConversionConstantFold(InterInstruction& ins, InterInstruction * cins) +{ + switch (ins.mOperator) + { + case IA_INT2FLOAT: + ins.mCode = IC_CONSTANT; + ins.mFloatValue = (double)(cins->mIntValue); + ins.mSTemp[0] = -1; + break; + case IA_FLOAT2INT: + ins.mCode = IC_CONSTANT; + ins.mIntValue = (int)(cins->mFloatValue); + ins.mSTemp[0] = -1; + break; + case IA_EXT8TO16S: + ins.mCode = IC_CONSTANT; + ins.mIntValue = (char)(cins->mIntValue); + ins.mSTemp[0] = -1; + break; + case IA_EXT8TO16U: + ins.mCode = IC_CONSTANT; + ins.mIntValue = (unsigned char)(cins->mIntValue); + ins.mSTemp[0] = -1; + break; + } +} + void ValueSet::InsertValue(InterInstruction& ins) { InterInstructionPtr* nins; @@ -717,14 +744,11 @@ void ValueSet::UpdateValue(InterInstruction& ins, const GrowingInstructionPtrArr break; case IC_CONVERSION_OPERATOR: - if (ins.mOperator == IA_INT2FLOAT) + if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT) { - if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT) + ConversionConstantFold(ins, tvalue[ins.mSTemp[0]]); + if (ins.mTType == IT_FLOAT) { - ins.mCode = IC_CONSTANT; - ins.mFloatValue = (double)(tvalue[ins.mSTemp[0]]->mIntValue); - ins.mSTemp[0] = -1; - i = 0; while (i < mNum && (mInstructions[i]->mCode != IC_CONSTANT || @@ -748,31 +772,32 @@ void ValueSet::UpdateValue(InterInstruction& ins, const GrowingInstructionPtrArr } else { - i = 0; - while (i < mNum && - (mInstructions[i]->mCode != IC_CONVERSION_OPERATOR || - mInstructions[i]->mOperator != ins.mOperator || - mInstructions[i]->mSTemp[0] != ins.mSTemp[0])) - { - i++; - } - - if (i < mNum) - { - ins.mCode = IC_LOAD_TEMPORARY; - ins.mSTemp[0] = mInstructions[i]->mTTemp; - ins.mSType[0] = mInstructions[i]->mTType; - ins.mSTemp[1] = -1; - assert(ins.mSTemp[0] >= 0); - } - else - { - InsertValue(ins); - } + InsertValue(ins); } } - else if (ins.mOperator == IA_FLOAT2INT) + else { + i = 0; + while (i < mNum && + (mInstructions[i]->mCode != IC_CONVERSION_OPERATOR || + mInstructions[i]->mOperator != ins.mOperator || + mInstructions[i]->mSTemp[0] != ins.mSTemp[0])) + { + i++; + } + + if (i < mNum) + { + ins.mCode = IC_LOAD_TEMPORARY; + ins.mSTemp[0] = mInstructions[i]->mTTemp; + ins.mSType[0] = mInstructions[i]->mTType; + ins.mSTemp[1] = -1; + assert(ins.mSTemp[0] >= 0); + } + else + { + InsertValue(ins); + } } break; @@ -992,7 +1017,7 @@ void InterInstruction::SetCode(const Location& loc, InterCode code) static bool TypeInteger(InterType t) { - return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL || t == IT_POINTER; + return t == IT_INT8 || t == IT_INT16 || t == IT_INT32 || t == IT_BOOL || t == IT_POINTER; } static bool TypeCompatible(InterType t1, InterType t2) @@ -1002,7 +1027,7 @@ static bool TypeCompatible(InterType t1, InterType t2) static bool TypeArithmetic(InterType t) { - return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL || t == IT_FLOAT; + return t == IT_INT8 || t == IT_INT16 || t == IT_INT32 || t == IT_BOOL || t == IT_FLOAT; } static InterType TypeCheckArithmecitResult(InterType t1, InterType t2) @@ -1010,7 +1035,7 @@ static InterType TypeCheckArithmecitResult(InterType t1, InterType t2) if (t1 == IT_FLOAT && t2 == IT_FLOAT) return IT_FLOAT; else if (TypeInteger(t1) && TypeInteger(t2)) - return IT_SIGNED; + return t1 > t2 ? t1 : t2; else throw InterCodeTypeMismatchException(); } @@ -1068,7 +1093,7 @@ void InterInstruction::CollectLocalAddressTemps(GrowingIntArray& localTable, Gro void InterInstruction::MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals, const GrowingIntArray& paramTable, NumberSet& aliasedParams) { - if (mCode == IC_STORE) + if (mCode == IC_STORE && mSTemp[0] >= 0) { int l = localTable[mSTemp[0]]; if (l >= 0) @@ -1578,7 +1603,7 @@ void InterInstruction::Disassemble(FILE* file) fprintf(file, "RET"); break; } - static char typechars[] = "NUSFPB"; + static char typechars[] = "NBCILFP"; fprintf(file, "\t"); if (mTTemp >= 0) fprintf(file, "R%d(%c)", mTTemp, typechars[mTType]); @@ -1803,10 +1828,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn case IT_POINTER: break; default: - if (ins.mSType[0] == IT_UNSIGNED) - ins.mSIntConst[0] = unsigned short (tvalue[ins.mSTemp[0]]->mIntValue); - else - ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue; + ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue; ins.mSTemp[0] = -1; break; } @@ -1823,6 +1845,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn ins.mMemory = tvalue[ins.mSTemp[1]]->mMemory; ins.mVarIndex = tvalue[ins.mSTemp[1]]->mVarIndex; ins.mIntValue = tvalue[ins.mSTemp[1]]->mIntValue + tvalue[ins.mSTemp[0]]->mIntValue; + ins.mOperandSize = tvalue[ins.mSTemp[1]]->mOperandSize; ins.mSTemp[0] = -1; ins.mSTemp[1] = -1; } @@ -1847,7 +1870,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn ins.mCode = IC_LOAD_TEMPORARY; assert(ins.mSTemp[0] >= 0); } - else if ((ins.mSType[0] == IT_SIGNED || ins.mSType[0] == IT_UNSIGNED) && ins.mTType == IT_POINTER) + else if (TypeInteger(ins.mSType[0]) && ins.mTType == IT_POINTER) { if (ins.mSTemp[0] >= 0 && tvalue[ins.mSTemp[0]] && tvalue[ins.mSTemp[0]]->mCode == IC_CONSTANT) { @@ -1870,10 +1893,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn case IT_POINTER: break; default: - if (ins.mSType[0] == IT_UNSIGNED) - ins.mSIntConst[0] = unsigned short(tvalue[ins.mSTemp[0]]->mIntValue); - else - ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue; + ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue; ins.mSTemp[0] = -1; break; } @@ -2129,7 +2149,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn { ins.mCode = IC_CONSTANT; ins.mIntValue = ConstantRelationalFolding(ins.mOperator, tvalue[ins.mSTemp[1]]->mFloatValue, tvalue[ins.mSTemp[0]]->mFloatValue); - ins.mTType = IT_SIGNED; + ins.mTType = IT_BOOL; ins.mSTemp[0] = -1; ins.mSTemp[1] = -1; } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 9af7895..5474ce0 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -37,11 +37,12 @@ enum InterCode enum InterType { IT_NONE, - IT_UNSIGNED, - IT_SIGNED, + IT_BOOL, + IT_INT8, + IT_INT16, + IT_INT32, IT_FLOAT, - IT_POINTER, - IT_BOOL + IT_POINTER }; enum InterMemory @@ -89,7 +90,14 @@ enum InterOperator IA_CMPGU, IA_CMPLU, IA_FLOAT2INT, - IA_INT2FLOAT + IA_INT2FLOAT, + + IA_EXT8TO16U, + IA_EXT8TO32U, + IA_EXT16TO32U, + IA_EXT8TO16S, + IA_EXT8TO32S, + IA_EXT16TO32S }; class InterInstruction; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 37d47e5..33e96e0 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -20,8 +20,14 @@ static inline InterType InterTypeOf(const Declaration* dec) case DT_TYPE_VOID: return IT_NONE; case DT_TYPE_INTEGER: + if (dec->mSize == 1) + return IT_INT8; + else if (dec->mSize == 2) + return IT_INT16; + else + return IT_INT32; case DT_TYPE_ENUM: - return (dec->mFlags & DTF_SIGNED) ? IT_SIGNED : IT_UNSIGNED; + return IT_INT8; case DT_TYPE_BOOL: return IT_BOOL; case DT_TYPE_FLOAT: @@ -55,31 +61,101 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, InterCodeBasicBlock*& block, ExValue v, Declaration* type) { + int stemp = v.mTemp; + if (v.mType->IsIntegerType() && type->mType == DT_TYPE_FLOAT) { + if (v.mType->mSize == 1) + { + if (v.mType->mFlags & DTF_SIGNED) + { + InterInstruction xins; + xins.mCode = IC_CONVERSION_OPERATOR; + xins.mOperator = IA_EXT8TO16S; + xins.mSType[0] = IT_INT8; + xins.mSTemp[0] = stemp; + xins.mTType = IT_INT16; + xins.mTTemp = proc->AddTemporary(IT_INT16); + block->Append(xins); + stemp = xins.mTTemp; + } + else + { + InterInstruction xins; + xins.mCode = IC_CONVERSION_OPERATOR; + xins.mOperator = IA_EXT8TO16U; + xins.mSType[0] = IT_INT8; + xins.mSTemp[0] = stemp; + xins.mTType = IT_INT16; + xins.mTTemp = proc->AddTemporary(IT_INT16); + block->Append(xins); + stemp = xins.mTTemp; + } + } + InterInstruction cins; cins.mCode = IC_CONVERSION_OPERATOR; cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(v.mType); - cins.mSTemp[0] = v.mTemp; + cins.mSType[0] = IT_INT16; + cins.mSTemp[0] = stemp; cins.mTType = IT_FLOAT; - cins.mTTemp = proc->AddTemporary(cins.mTType); + cins.mTTemp = proc->AddTemporary(IT_FLOAT); + block->Append(cins); + v.mTemp = cins.mTTemp; v.mType = type; - block->Append(cins); } else if (v.mType->mType == DT_TYPE_FLOAT && type->IsIntegerType()) { InterInstruction cins; cins.mCode = IC_CONVERSION_OPERATOR; cins.mOperator = IA_FLOAT2INT; - cins.mSType[0] = InterTypeOf(v.mType); + cins.mSType[0] = IT_FLOAT; cins.mSTemp[0] = v.mTemp; - cins.mTType = InterTypeOf(type); - cins.mTTemp = proc->AddTemporary(cins.mTType); + cins.mTType = IT_INT16; + cins.mTTemp = proc->AddTemporary(IT_INT16); + block->Append(cins); v.mTemp = cins.mTTemp; v.mType = type; - block->Append(cins); + } + else if (v.mType->mSize < type->mSize) + { + if (v.mType->mSize == 1 && type->mSize == 2) + { + if (v.mType->mFlags & DTF_SIGNED) + { + InterInstruction xins; + xins.mCode = IC_CONVERSION_OPERATOR; + xins.mOperator = IA_EXT8TO16S; + xins.mSType[0] = IT_INT8; + xins.mSTemp[0] = stemp; + xins.mTType = IT_INT16; + xins.mTTemp = proc->AddTemporary(IT_INT16); + block->Append(xins); + stemp = xins.mTTemp; + } + else + { + InterInstruction xins; + xins.mCode = IC_CONVERSION_OPERATOR; + xins.mOperator = IA_EXT8TO16U; + xins.mSType[0] = IT_INT8; + xins.mSTemp[0] = stemp; + xins.mTType = IT_INT16; + xins.mTTemp = proc->AddTemporary(IT_INT16); + block->Append(xins); + stemp = xins.mTTemp; + } + } + + v.mTemp = stemp; + v.mType = type; + } + else + { + // ignore size reduction + + v.mType = type; } return v; @@ -87,21 +163,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p static inline bool InterTypeTypeInteger(InterType t) { - return t == IT_UNSIGNED || t == IT_SIGNED || t == IT_BOOL; + return t == IT_INT8 || t == IT_INT16 || t == IT_INT32 || t == IT_BOOL; } static inline InterType InterTypeOfArithmetic(InterType t1, InterType t2) { if (t1 == IT_FLOAT || t2 == IT_FLOAT) return IT_FLOAT; - else if (t1 == IT_SIGNED && t2 == IT_SIGNED) - return IT_SIGNED; + else if (InterTypeTypeInteger(t1) && InterTypeTypeInteger(t2)) + return t1 > t2 ? t1 : t2; else if (t1 == IT_POINTER && t2 == IT_POINTER) - return IT_SIGNED; + return IT_INT16; else if (t1 == IT_POINTER || t2 == IT_POINTER) return IT_POINTER; else - return IT_UNSIGNED; + return IT_INT16; } void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* dec) @@ -360,17 +436,37 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins.mCode = IC_CONSTANT; ins.mTType = InterTypeOf(dec->mBase); ins.mTTemp = proc->AddTemporary(ins.mTType); - if (ins.mTType == IT_SIGNED) + if (ins.mTType == IT_INT8) { - if (dec->mInteger < -32768 || dec->mInteger > 32767) - mErrors->Warning(dec->mLocation, "Integer constant truncated"); + if (dec->mFlags & DTF_SIGNED) + { + if (dec->mInteger < -128 || dec->mInteger > 127) + mErrors->Warning(dec->mLocation, "Integer constant truncated"); + } + else + { + if (dec->mInteger < 0 || dec->mInteger > 255) + mErrors->Warning(dec->mLocation, "Unsigned integer constant truncated"); + } + ins.mIntValue = char(dec->mInteger); + } + else if (ins.mTType == IT_INT8) + { + if (dec->mFlags & DTF_SIGNED) + { + if (dec->mInteger < -32768 || dec->mInteger > 32767) + mErrors->Warning(dec->mLocation, "Integer constant truncated"); + } + else + { + if (dec->mInteger < 0 || dec->mInteger > 65535) + mErrors->Warning(dec->mLocation, "Unsigned integer constant truncated"); + } ins.mIntValue = short(dec->mInteger); } else { - if (dec->mInteger < 0 || dec->mInteger > 65535) - mErrors->Warning(dec->mLocation, "Unsigned integer constant truncated"); - ins.mIntValue = unsigned short(dec->mInteger); + ins.mIntValue = dec->mInteger; } block->Append(ins); return ExValue(dec->mBase, ins.mTTemp); @@ -533,8 +629,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock); vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock); - if (!vl.mType->CanAssign(vr.mType)) - mErrors->Error(exp->mLocation, "Cannot assign incompatible types"); + if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == IT_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) + { + if (!vl.mType->CanAssign(vr.mType)) + mErrors->Error(exp->mLocation, "Cannot assign incompatible types"); + } if (vl.mType->mFlags & DTF_CONST) mErrors->Error(exp->mLocation, "Cannot assign to const type"); @@ -597,31 +696,34 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!vr.mType->IsIntegerType()) mErrors->Error(exp->mLocation, "Invalid argument for pointer inc/dec"); - cins.mTType = IT_SIGNED; + cins.mTType = IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); block->Append(cins); InterInstruction mins; mins.mCode = IC_BINARY_OPERATOR; mins.mOperator = IA_MUL; - mins.mSType[0] = IT_SIGNED; + mins.mSType[0] = IT_INT16; mins.mSTemp[0] = vr.mTemp; - mins.mSType[1] = IT_SIGNED; + mins.mSType[1] = IT_INT16; mins.mSTemp[1] = cins.mTTemp; - mins.mTType = IT_SIGNED; + mins.mTType = IT_INT16; mins.mTTemp = proc->AddTemporary(mins.mTType); block->Append(mins); InterInstruction ains; ains.mCode = IC_LEA; ains.mMemory = IM_INDIRECT; - ains.mSType[0] = IT_SIGNED; + ains.mSType[0] = IT_INT16; ains.mSTemp[0] = mins.mTTemp; ains.mSType[1] = IT_POINTER; - ains.mSTemp[1] = vl.mTemp; + ains.mSTemp[1] = vll.mTemp; ains.mTType = IT_POINTER; ains.mTTemp = proc->AddTemporary(ains.mTType); block->Append(ains); + + vr.mTemp = ains.mTTemp; + vr.mType = vll.mType; } else { @@ -692,32 +794,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_FLOAT2INT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = InterTypeOf(vl.mType); - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheSignedIntTypeDeclaration; - block->Append(cins); - } - else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = InterTypeOf(vl.mType);; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheFloatTypeDeclaration; - block->Append(cins); - } + vr = CoerceType(proc, block, vr, vl.mType); } ins.mCode = IC_STORE; @@ -750,25 +827,25 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction cins; cins.mCode = IC_CONSTANT; cins.mIntValue = vl.mType->mBase->mSize; - cins.mTType = IT_SIGNED; + cins.mTType = IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); block->Append(cins); InterInstruction mins; mins.mCode = IC_BINARY_OPERATOR; mins.mOperator = IA_MUL; - mins.mSType[0] = IT_SIGNED; + mins.mSType[0] = IT_INT16; mins.mSTemp[0] = vr.mTemp; - mins.mSType[1] = IT_SIGNED; + mins.mSType[1] = IT_INT16; mins.mSTemp[1] = cins.mTTemp; - mins.mTType = IT_SIGNED; + mins.mTType = IT_INT16; mins.mTTemp = proc->AddTemporary(mins.mTType); block->Append(mins); InterInstruction ains; ains.mCode = IC_LEA; ains.mMemory = IM_INDIRECT; - ains.mSType[0] = IT_SIGNED; + ains.mSType[0] = IT_INT16; ains.mSTemp[0] = mins.mTTemp; ains.mSType[1] = IT_POINTER; ains.mSTemp[1] = vl.mTemp; @@ -790,14 +867,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction cins; cins.mCode = IC_CONSTANT; cins.mIntValue = exp->mDecValue->mOffset; - cins.mTType = IT_SIGNED; + cins.mTType = IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); block->Append(cins); InterInstruction ains; ains.mCode = IC_LEA; ains.mMemory = IM_INDIRECT; - ains.mSType[0] = IT_SIGNED; + ains.mSType[0] = IT_INT16; ains.mSTemp[0] = cins.mTTemp; ains.mSType[1] = IT_POINTER; ains.mSTemp[1] = vl.mTemp; @@ -846,24 +923,24 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else mErrors->Error(exp->mLocation, "Invalid pointer operation"); - cins.mTType = IT_SIGNED; + cins.mTType = IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); block->Append(cins); InterInstruction mins; mins.mCode = IC_BINARY_OPERATOR; mins.mOperator = IA_MUL; - mins.mSType[0] = IT_SIGNED; + mins.mSType[0] = IT_INT16; mins.mSTemp[0] = vr.mTemp; - mins.mSType[1] = IT_SIGNED; + mins.mSType[1] = IT_INT16; mins.mSTemp[1] = cins.mTTemp; - mins.mTType = IT_SIGNED; + mins.mTType = IT_INT16; mins.mTTemp = proc->AddTemporary(mins.mTType); block->Append(mins); ins.mCode = IC_LEA; ins.mMemory = IM_INDIRECT; - ins.mSType[0] = IT_SIGNED; + ins.mSType[0] = IT_INT16; ins.mSTemp[0] = mins.mTTemp; ins.mSType[1] = IT_POINTER; ins.mSTemp[1] = vl.mTemp; @@ -879,42 +956,42 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* clins.mCode = IC_TYPECAST; clins.mSTemp[0] = vl.mTemp; clins.mSType[0] = IT_POINTER; - clins.mTType = IT_SIGNED; + clins.mTType = IT_INT16; clins.mTTemp = proc->AddTemporary(clins.mTType); block->Append(clins); crins.mCode = IC_TYPECAST; crins.mSTemp[0] = vr.mTemp; crins.mSType[0] = IT_POINTER; - crins.mTType = IT_SIGNED; + crins.mTType = IT_INT16; crins.mTTemp = proc->AddTemporary(crins.mTType); block->Append(crins); InterInstruction cins; cins.mCode = IC_CONSTANT; cins.mIntValue = vl.mType->mBase->mSize; - cins.mTType = IT_SIGNED; + cins.mTType = IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); block->Append(cins); InterInstruction sins, dins; sins.mCode = IC_BINARY_OPERATOR; sins.mOperator = IA_SUB; - sins.mSType[0] = IT_SIGNED; + sins.mSType[0] = IT_INT16; sins.mSTemp[0] = crins.mTTemp; - sins.mSType[1] = IT_SIGNED; + sins.mSType[1] = IT_INT16; sins.mSTemp[1] = clins.mTTemp; - sins.mTType = IT_SIGNED; + sins.mTType = IT_INT16; sins.mTTemp = proc->AddTemporary(sins.mTType); block->Append(sins); dins.mCode = IC_BINARY_OPERATOR; dins.mOperator = IA_DIVS; - dins.mSType[0] = IT_SIGNED; + dins.mSType[0] = IT_INT16; dins.mSTemp[0] = cins.mTTemp; - dins.mSType[1] = IT_SIGNED; + dins.mSType[1] = IT_INT16; dins.mSTemp[1] = sins.mTTemp; - dins.mTType = IT_SIGNED; + dins.mTType = IT_INT16; dins.mTTemp = proc->AddTemporary(dins.mTType); block->Append(dins); @@ -933,34 +1010,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!vr.mType->IsNumericType()) mErrors->Error(exp->mLocation, "Right hand operand type is not numeric"); - if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vl.mType); - cins.mSTemp[0] = vl.mTemp; - cins.mTType = IT_FLOAT; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vl.mTemp = cins.mTTemp; - vl.mType = TheFloatTypeDeclaration; - block->Append(cins); - } - else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = IT_FLOAT; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheFloatTypeDeclaration; - block->Append(cins); - } + Declaration* dtype; + if (vr.mType->mType == DT_TYPE_FLOAT || vl.mType->mType == DT_TYPE_FLOAT) + dtype = TheFloatTypeDeclaration; + else if (vr.mType->mSize < vl.mType->mSize && (vl.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else if (vl.mType->mSize < vr.mType->mSize && (vr.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else if ((vr.mType->mFlags & DTF_SIGNED) && (vl.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else + dtype = TheUnsignedIntTypeDeclaration; - bool signedOP = (vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED); + vl = CoerceType(proc, block, vl, dtype); + vr = CoerceType(proc, block, vr, dtype); + + bool signedOP = dtype->mFlags & DTF_SIGNED; ins.mCode = IC_BINARY_OPERATOR; switch (exp->mToken) @@ -1028,7 +1093,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* bool ftype = vl.mType->mType == DT_TYPE_FLOAT; cins.mCode = IC_CONSTANT; - cins.mTType = ftype ? IT_FLOAT : IT_SIGNED; + cins.mTType = ftype ? IT_FLOAT : IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); if (vdl.mType->mType == DT_TYPE_POINTER) cins.mIntValue = exp->mToken == TK_INC ? vdl.mType->mBase->mSize : -(vdl.mType->mBase->mSize); @@ -1080,7 +1145,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* bool ftype = vl.mType->mType == DT_TYPE_FLOAT; cins.mCode = IC_CONSTANT; - cins.mTType = ftype ? IT_FLOAT : IT_SIGNED; + cins.mTType = ftype ? IT_FLOAT : IT_INT16; cins.mTTemp = proc->AddTemporary(cins.mTType); if (vdl.mType->mType == DT_TYPE_POINTER) cins.mIntValue = exp->mToken == TK_INC ? vdl.mType->mBase->mSize : -(vdl.mType->mBase->mSize); @@ -1175,37 +1240,31 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction ins; - bool signedCompare = (vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED); + Declaration* dtype = TheSignedIntTypeDeclaration; - if (!(vl.mType->mType == DT_TYPE_POINTER || vl.mType->IsNumericType())) + if (vl.mType->mType == DT_TYPE_POINTER || vr.mType->mType == DT_TYPE_POINTER) + { + dtype = vl.mType; + if (!vl.mType->IsSame(vr.mType)) + mErrors->Error(exp->mLocation, "Incompatible pointer types"); + } + else if (!vl.mType->IsNumericType() || !vr.mType->IsNumericType()) mErrors->Error(exp->mLocation, "Not a numeric or pointer type"); + else if (vr.mType->mType == DT_TYPE_FLOAT || vl.mType->mType == DT_TYPE_FLOAT) + dtype = TheFloatTypeDeclaration; + else if (vr.mType->mSize < vl.mType->mSize && (vl.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else if (vl.mType->mSize < vr.mType->mSize && (vr.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else if ((vr.mType->mFlags & DTF_SIGNED) && (vl.mType->mFlags & DTF_SIGNED)) + dtype = TheSignedIntTypeDeclaration; + else + dtype = TheUnsignedIntTypeDeclaration; - if (vl.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vl.mType); - cins.mSTemp[0] = vl.mTemp; - cins.mTType = IT_FLOAT; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vl.mTemp = cins.mTTemp; - vl.mType = TheFloatTypeDeclaration; - block->Append(cins); - } - else if (vl.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = IT_FLOAT; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheFloatTypeDeclaration; - block->Append(cins); - } + vl = CoerceType(proc, block, vl, dtype); + vr = CoerceType(proc, block, vr, dtype); + + bool signedCompare = dtype->mFlags & DTF_SIGNED; ins.mCode = IC_RELATIONAL_OPERATOR; switch (exp->mToken) @@ -1737,74 +1796,57 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = Dereference(proc, fblock, vr); int ttemp; - InterType ttype; + InterType ttype, stypel, styper; + + stypel = InterTypeOf(vl.mType); + styper = InterTypeOf(vr.mType); + Declaration* dtype; - if (vl.mType->mType == DT_TYPE_FLOAT || vr.mType->mType == DT_TYPE_FLOAT) - { - ttype = IT_FLOAT; - dtype = TheFloatTypeDeclaration; - } - else if (vl.mType->IsIntegerType() && vr.mType->IsIntegerType()) - { - ttype = ((vl.mType->mFlags & DTF_SIGNED) && (vr.mType->mFlags & DTF_SIGNED)) ? IT_SIGNED : IT_UNSIGNED; - dtype = vl.mType; - } - else if (vl.mType->mType == DT_TYPE_POINTER && vl.mType->IsSame(vr.mType)) + if (stypel == IT_POINTER || styper == IT_POINTER) { + if (!vl.mType->IsSame(vr.mType)) + mErrors->Error(exp->mLocation, "Incompatible conditional types"); + ttype = IT_POINTER; dtype = vl.mType; } + else if (stypel == styper) + { + ttype = stypel; + dtype = vl.mType; + } + else if (stypel > styper) + { + ttype = stypel; + dtype = vl.mType; + + vr = CoerceType(proc, fblock, vr, dtype); + } else { - mErrors->Error(exp->mLocation, "Incompatible conditional types"); - ttype = IT_SIGNED; - dtype = TheVoidTypeDeclaration; + ttype = styper; + dtype = vr.mType; + + vl = CoerceType(proc, tblock, vl, dtype); } + ttemp = proc->AddTemporary(ttype); - if (ttype == IT_FLOAT && vr.mType->IsIntegerType()) - { - InterInstruction ins; - ins.mCode = IC_CONVERSION_OPERATOR; - ins.mOperator = IA_INT2FLOAT; - ins.mSType[0] = InterTypeOf(vr.mType); - ins.mSTemp[0] = vr.mTemp; - ins.mTType = ttype; - ins.mTTemp = ttemp; - fblock->Append(ins); - } - else - { - InterInstruction ins; - ins.mCode = IC_LOAD_TEMPORARY; - ins.mSType[0] = InterTypeOf(vr.mType); - ins.mSTemp[0] = vr.mTemp; - ins.mTType = ttype; - ins.mTTemp = ttemp; - fblock->Append(ins); - } + InterInstruction rins; + rins.mCode = IC_LOAD_TEMPORARY; + rins.mSType[0] = InterTypeOf(vr.mType); + rins.mSTemp[0] = vr.mTemp; + rins.mTType = ttype; + rins.mTTemp = ttemp; + fblock->Append(rins); - if (ttype == IT_FLOAT && vl.mType->IsIntegerType()) - { - InterInstruction ins; - ins.mCode = IC_CONVERSION_OPERATOR; - ins.mOperator = IA_INT2FLOAT; - ins.mSType[0] = InterTypeOf(vl.mType); - ins.mSTemp[0] = vl.mTemp; - ins.mTType = ttype; - ins.mTTemp = ttemp; - tblock->Append(ins); - } - else - { - InterInstruction ins; - ins.mCode = IC_LOAD_TEMPORARY; - ins.mSType[0] = InterTypeOf(vl.mType); - ins.mSTemp[0] = vl.mTemp; - ins.mTType = ttype; - ins.mTTemp = ttemp; - tblock->Append(ins); - } + InterInstruction lins; + lins.mCode = IC_LOAD_TEMPORARY; + lins.mSType[0] = InterTypeOf(vl.mType); + lins.mSTemp[0] = vl.mTemp; + lins.mTType = ttype; + lins.mTTemp = ttemp; + tblock->Append(lins); tblock->Append(jins); tblock->Close(eblock, nullptr); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index b610acd..e6cd7bd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -331,6 +331,8 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) case ASMIT_CPY: case ASMIT_ASL: case ASMIT_LSR: + case ASMIT_INC: + case ASMIT_DEC: case ASMIT_ORA: case ASMIT_EOR: case ASMIT_AND: @@ -497,12 +499,19 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) case ASMIT_LSR: if (mMode == ASMIM_IMPLIED) data.mRegs[CPU_REG_A].Reset(); + data.mRegs[CPU_REG_C].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + break; + + case ASMIT_INC: + case ASMIT_DEC: + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_LDA: if (mMode == ASMIM_IMMEDIATE) { - if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress) + if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; changed = true; @@ -513,22 +522,93 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) data.mRegs[CPU_REG_A].mZeroPage = false; data.mRegs[CPU_REG_A].mValue = mAddress; } + + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; + } + else + { + if (mMode != ASMIM_ZERO_PAGE) + data.mRegs[CPU_REG_A].Reset(); + data.mRegs[CPU_REG_Z].Reset(); } - else if (mMode != ASMIM_ZERO_PAGE) - data.mRegs[CPU_REG_A].Reset(); break; case ASMIT_ADC: case ASMIT_SBC: + data.mRegs[CPU_REG_A].Reset(); + data.mRegs[CPU_REG_C].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + break; + case ASMIT_CMP: + if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mImmediate - mAddress; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_A].mImmediate >= mAddress; + } + else + { + data.mRegs[CPU_REG_C].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } + break; + case ASMIT_CPX: + if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_X].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mImmediate - mAddress; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_X].mImmediate >= mAddress; + } + else + { + data.mRegs[CPU_REG_C].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } + break; + case ASMIT_CPY: + if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_Y].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mImmediate - mAddress; + data.mRegs[CPU_REG_C].mImmediate = true; + data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_Y].mImmediate >= mAddress; + } + else + { + data.mRegs[CPU_REG_C].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } + break; + case ASMIT_ORA: case ASMIT_EOR: case ASMIT_AND: - data.mRegs[CPU_REG_A].Reset(); + if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_A].mImmediate) + { + if (mType == ASMIT_ORA) + mAddress |= data.mRegs[CPU_REG_A].mValue; + else if (mType == ASMIT_AND) + mAddress &= data.mRegs[CPU_REG_A].mValue; + else if (mType == ASMIT_EOR) + mAddress ^= data.mRegs[CPU_REG_A].mValue; + mType = ASMIT_LDA; + data.mRegs[CPU_REG_A].mValue = mAddress; + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; + } + else + { + data.mRegs[CPU_REG_A].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } break; case ASMIT_LDX: if (mMode == ASMIM_IMMEDIATE) { - if (data.mRegs[CPU_REG_X].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress) + if (data.mRegs[CPU_REG_X].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; changed = true; @@ -538,19 +618,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) data.mRegs[CPU_REG_X].mImmediate = true; data.mRegs[CPU_REG_X].mZeroPage = false; data.mRegs[CPU_REG_X].mValue = mAddress; + + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; } } - else if (mMode != ASMIM_ZERO_PAGE) - data.mRegs[CPU_REG_X].Reset(); + else + { + if (mMode != ASMIM_ZERO_PAGE) + data.mRegs[CPU_REG_X].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } break; case ASMIT_INX: case ASMIT_DEX: data.mRegs[CPU_REG_X].Reset(); + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_LDY: if (mMode == ASMIM_IMMEDIATE) { - if (data.mRegs[CPU_REG_Y].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress) + if (data.mRegs[CPU_REG_Y].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; changed = true; @@ -560,27 +648,63 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) data.mRegs[CPU_REG_Y].mImmediate = true; data.mRegs[CPU_REG_Y].mZeroPage = false; data.mRegs[CPU_REG_Y].mValue = mAddress; + + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = mAddress; } } - else if (mMode != ASMIM_ZERO_PAGE) - data.mRegs[CPU_REG_Y].Reset(); + else + { + if (mMode != ASMIM_ZERO_PAGE) + data.mRegs[CPU_REG_Y].Reset(); + data.mRegs[CPU_REG_Z].Reset(); + } break; case ASMIT_INY: case ASMIT_DEY: data.mRegs[CPU_REG_Y].Reset(); + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_TXA: data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X]; + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_TYA: data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y]; + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_TAX: data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A]; + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); break; case ASMIT_TAY: data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A]; + if (data.mRegs[CPU_REG_A].mImmediate) + { + data.mRegs[CPU_REG_Z].mImmediate = true; + data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue; + } + else + data.mRegs[CPU_REG_Z].Reset(); break; } @@ -589,7 +713,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) switch (mType) { case ASMIT_LDA: - if (data.mRegs[CPU_REG_A].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress) + if (data.mRegs[CPU_REG_A].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z)) { mType = ASMIT_NOP; changed = true; @@ -2059,9 +2183,6 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI { if (ins.mOperandSize == 1) { - if (ins.mTType == IT_SIGNED) - mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, 0)); - if (ins.mMemory == IM_GLOBAL) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex)); @@ -2093,16 +2214,7 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI mIns.Push(*ainsl); } mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - if (ins.mTType == IT_SIGNED) - { - mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1)); - mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED)); - } - else - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - } + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (ainsh) mIns.Push(*ainsh); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } @@ -2174,8 +2286,6 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI { if (ins.mOperandSize == 1) { - if (ins.mTType == IT_SIGNED) - mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins.mSIntConst[0])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); if (ainsl) @@ -2187,16 +2297,7 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI mIns.Push(*ainsl); } mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - if (ins.mTType == IT_SIGNED) - { - mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1)); - mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED)); - } - else - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - } + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (ainsh) mIns.Push(*ainsh); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } @@ -3192,10 +3293,7 @@ void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Int mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 3)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); - if (ins.mTType == IT_SIGNED) - mIns.Push(NativeCodeInstruction("ftoi")); - else - mIns.Push(NativeCodeInstruction("ftou")); + mIns.Push(NativeCodeInstruction("ftoi")); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 0)); @@ -3210,10 +3308,7 @@ void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Int mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - if (ins.mSType[0] == IT_SIGNED) - mIns.Push(NativeCodeInstruction("ffromi")); - else - mIns.Push(NativeCodeInstruction("fromu")); + mIns.Push(NativeCodeInstruction("ffromi")); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 0)); @@ -3225,6 +3320,24 @@ void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Int mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 3)); } break; + case IA_EXT8TO16S: + mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + if (ins.mSTemp[0] != ins.mTTemp) + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + break; + case IA_EXT8TO16U: + if (ins.mSTemp[0] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + } + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + break; } } @@ -3688,6 +3801,47 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void) return changed; } +void NativeCodeBasicBlock::CountEntries(void) +{ + mNumEntries++; + + if (!mVisited) + { + mVisited = true; + + if (mTrueJump) + mTrueJump->CountEntries(); + if (mFalseJump) + mFalseJump->CountEntries(); + } +} + +bool NativeCodeBasicBlock::MergeBasicBlocks(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this) + { + for (int i = 0; i < mTrueJump->mIns.Size(); i++) + mIns.Push(mTrueJump->mIns[i]); + mBranch = mTrueJump->mBranch; + mFalseJump = mTrueJump->mFalseJump; + mTrueJump = mTrueJump->mTrueJump; + changed = true; + } + + if (mTrueJump) + mTrueJump->MergeBasicBlocks(); + if (mFalseJump) + mFalseJump->MergeBasicBlocks(); + } + return changed; +} + bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) { int j = at; @@ -3734,6 +3888,73 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i].ValueForwarding(data); } + if (mFalseJump) + { + switch (mBranch) + { + case ASMIT_BCS: + if (data.mRegs[CPU_REG_C].mImmediate) + { + mBranch = ASMIT_JMP; + if (!data.mRegs[CPU_REG_C].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BCC: + if (data.mRegs[CPU_REG_C].mImmediate) + { + mBranch = ASMIT_JMP; + if (data.mRegs[CPU_REG_C].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BNE: + if (data.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (data.mRegs[CPU_REG_Z].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BEQ: + if (data.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (!data.mRegs[CPU_REG_Z].mValue) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BPL: + if (data.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (!(data.mRegs[CPU_REG_Z].mValue & 0x80)) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + case ASMIT_BMI: + if (data.mRegs[CPU_REG_Z].mImmediate) + { + mBranch = ASMIT_JMP; + if (data.mRegs[CPU_REG_Z].mValue & 0x80) + mTrueJump = mFalseJump; + mFalseJump = nullptr; + changed = true; + } + break; + } + } + // move load store pairs up to initial store for (int i = 2; i + 2 < mIns.Size(); i++) @@ -4292,10 +4513,17 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu if (entryBlock->PeepHoleOptimizer()) changed = true; + ResetVisited(); + for (int i = 0; i < mBlocks.Size(); i++) + mBlocks[i]->mNumEntries = 0; + entryBlock->CountEntries(); + + ResetVisited(); + if (entryBlock->MergeBasicBlocks()) + changed = true; + } while (changed); - ResetVisited(); - entryBlock->PeepHoleOptimizer(); #endif entryBlock->Assemble(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 79a6062..c40ef32 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -64,7 +64,7 @@ public: GrowingArray mIns; GrowingArray mRelocations; - int mOffset, mSize; + int mOffset, mSize, mNumEntries; bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited; int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset); @@ -114,6 +114,9 @@ public: bool BuildGlobalRequiredRegSet(NumberSet& fromRequiredTemps); bool RemoveUnusedResultInstructions(void); + void CountEntries(void); + bool MergeBasicBlocks(void); + bool MoveLoadStoreUp(int at); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5128cdf..e2155f3 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -131,6 +131,29 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint32 flags) break; + case TK_SIGNED: + dec = new Declaration(mScanner->mLocation, DT_TYPE_INTEGER); + dec->mFlags = flags | DTF_DEFINED | DTF_SIGNED; + mScanner->NextToken(); + if (mScanner->mToken == TK_INT || mScanner->mToken == TK_SHORT) + { + dec->mSize = 2; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_LONG) + { + dec->mSize = 4; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_CHAR) + { + dec->mSize = 1; + mScanner->NextToken(); + } + else + dec->mSize = 2; + break; + case TK_CONST: mScanner->NextToken(); return ParseBaseTypeDeclaration(flags | DTF_CONST); @@ -157,14 +180,14 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint32 flags) case TK_CHAR: dec = new Declaration(mScanner->mLocation, DT_TYPE_INTEGER); dec->mSize = 1; - dec->mFlags = flags | DTF_DEFINED | DTF_SIGNED; + dec->mFlags = flags | DTF_DEFINED; mScanner->NextToken(); break; case TK_BOOL: dec = new Declaration(mScanner->mLocation, DT_TYPE_BOOL); dec->mSize = 1; - dec->mFlags = flags | DTF_DEFINED | DTF_SIGNED; + dec->mFlags = flags | DTF_DEFINED; mScanner->NextToken(); break; @@ -840,6 +863,7 @@ Expression* Parser::ParseSimpleExpression(void) case TK_BOOL: case TK_VOID: case TK_UNSIGNED: + case TK_SIGNED: case TK_CONST: case TK_VOLATILE: case TK_STRUCT: @@ -878,7 +902,7 @@ Expression* Parser::ParseSimpleExpression(void) dec->mVarIndex = -1; dec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_ARRAY); dec->mBase->mSize = dec->mSize; - dec->mBase->mBase = TheConstSignedCharTypeDeclaration; + dec->mBase->mBase = TheConstCharTypeDeclaration; dec->mBase->mFlags |= DTF_DEFINED; uint8* d = new uint8[dec->mSize]; dec->mData = d; @@ -1206,6 +1230,12 @@ Expression* Parser::ParseMulExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParsePrefixExpression(); + + if (nexp->mLeft->mDecType->mType == DT_TYPE_FLOAT || nexp->mRight->mDecType->mType == DT_TYPE_FLOAT) + nexp->mDecType = TheFloatTypeDeclaration; + else + nexp->mDecType = exp->mDecType; + exp = nexp->ConstantFold(); } @@ -1223,6 +1253,15 @@ Expression* Parser::ParseAddExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseMulExpression(); + if (nexp->mLeft->mDecType->mType == DT_TYPE_POINTER && nexp->mRight->mDecType->IsIntegerType()) + nexp->mDecType = nexp->mLeft->mDecType; + else if (nexp->mRight->mDecType->mType == DT_TYPE_POINTER && nexp->mLeft->mDecType->IsIntegerType()) + nexp->mDecType = nexp->mRight->mDecType; + else if (nexp->mLeft->mDecType->mType == DT_TYPE_FLOAT || nexp->mRight->mDecType->mType == DT_TYPE_FLOAT) + nexp->mDecType = TheFloatTypeDeclaration; + else + nexp->mDecType = exp->mDecType; + exp = nexp->ConstantFold(); } @@ -1240,6 +1279,8 @@ Expression* Parser::ParseShiftExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAddExpression(); + nexp->mDecType = exp->mDecType; + exp = nexp->ConstantFold(); } @@ -1257,6 +1298,8 @@ Expression* Parser::ParseRelationalExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseShiftExpression(); + nexp->mDecType = TheBoolTypeDeclaration; + exp = nexp->ConstantFold(); } @@ -1274,6 +1317,8 @@ Expression* Parser::ParseBinaryAndExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseRelationalExpression(); + nexp->mDecType = exp->mDecType; + exp = nexp->ConstantFold(); } @@ -1291,6 +1336,7 @@ Expression* Parser::ParseBinaryXorExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseBinaryAndExpression(); + nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(); } @@ -1308,6 +1354,7 @@ Expression* Parser::ParseBinaryOrExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseBinaryXorExpression(); + nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(); } @@ -1325,6 +1372,7 @@ Expression* Parser::ParseLogicAndExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseBinaryOrExpression(); + nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(); } @@ -1342,6 +1390,7 @@ Expression* Parser::ParseLogicOrExpression(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseLogicAndExpression(); + nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(); } diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 3d3e076..ab05c26 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -21,6 +21,7 @@ const char* TokenNames[] = { "'char'", "'float'", "'unsigned'", + "'signed'", "'switch'", "'case'", "'default'", @@ -922,6 +923,8 @@ void Scanner::NextRawToken(void) mToken = TK_LONG; else if (!strcmp(tkident, "unsigned")) mToken = TK_UNSIGNED; + else if (!strcmp(tkident, "signed")) + mToken = TK_SIGNED; else if (!strcmp(tkident, "const")) mToken = TK_CONST; else if (!strcmp(tkident, "volatile")) diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index dacb53b..e865a2d 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -21,6 +21,7 @@ enum Token TK_CHAR, TK_FLOAT, TK_UNSIGNED, + TK_SIGNED, TK_SWITCH, TK_CASE, TK_DEFAULT,