diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 5665bb2..2f7700b 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -117,6 +117,9 @@ rem @echo off @call :test floatmultest.c @if %errorlevel% neq 0 goto :error +@call :test floatinttest.c +@if %errorlevel% neq 0 goto :error + @call :test staticconsttest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/floatinttest.c b/autotest/floatinttest.c new file mode 100644 index 0000000..8b23c4a --- /dev/null +++ b/autotest/floatinttest.c @@ -0,0 +1,75 @@ +#include +#include +#include + + +int main(void) +{ + float a; + int i; + long li; + unsigned u; + unsigned long lu; + + a = 1.0; + i = 1; + for(int j=0; j<15; j++) + { + assert(i == (int)a); + assert(a == (float)i); + a *= 2.0; + i <<= 1; + } + + a = -1.0; + i = -1; + for(int j=0; j<15; j++) + { + assert(i == (int)a); + assert(a == (float)i); + a *= 2.0; + i <<= 1; + } + + a = 1.0; + u = 1; + for(int j=0; j<16; j++) + { + assert(u == (unsigned)a); + assert(a == (float)u); + a *= 2.0; + u <<= 1; + } + + a = 1.0; + li = 1; + for(int j=0; j<31; j++) + { + assert(li == (long)a); + assert(a == (float)li); + a *= 2.0; + li <<= 1; + } + + a = -1.0; + li = -1; + for(int j=0; j<31; j++) + { + assert(li == (long)a); + assert(a == (float)li); + a *= 2.0; + li <<= 1; + } + + a = 1.0; + lu = 1; + for(int j=0; j<32; j++) + { + assert(lu == (unsigned long)a); + assert(a == (float)lu); + a *= 2.0; + lu <<= 1; + } + + return 0; +} diff --git a/include/crt.c b/include/crt.c index 24a5568..2f0e1e2 100644 --- a/include/crt.c +++ b/include/crt.c @@ -3518,6 +3518,102 @@ __asm inp_conv_i16_f32 #pragma bytecode(BC_CONV_I16_F32, inp_conv_i16_f32) +__asm uint32_to_float +{ + lda accu + ora accu + 1 + ora accu + 2 + ora accu + 3 + bne W1 + rts +W1: + ldx #$9e + lda accu + 3 + bmi W2 +L1: + dex + asl accu + rol accu + 1 + rol accu + 2 + rol + bpl L1 +W2: + bit accu + bpl W3 + // check rounding + inc accu + 1 + bne W3 + inc accu + 2 + bne W3 + clc + adc #1 + bcc W3 + lsr + ror accu + 2 + ror accu + 1 + inx +W3: + asl + ldy accu + 1 + sty accu + ldy accu + 2 + sty accu + 1 + sta accu + 2 + + txa + lsr + sta accu + 3 + ror accu + 2 + rts +} + +__asm sint32_to_float +{ + bit accu + 3 + bmi W1 + jmp uint32_to_float +W1: + sec + lda #0 + sbc accu + sta accu + lda #0 + sbc accu + 1 + sta accu + 1 + lda #0 + sbc accu + 2 + sta accu + 2 + lda #0 + sbc accu + 3 + sta accu + 3 + jsr uint32_to_float + lda accu + 3 + ora #$80 + sta accu + 3 + rts +} + + +__asm inp_conv_u32_f32 +{ + sty tmpy + jsr uint32_to_float + ldy tmpy + rts +} + +#pragma bytecode(BC_CONV_U32_F32, inp_conv_u32_f32) + +__asm inp_conv_i32_f32 +{ + sty tmpy + jsr sint32_to_float + ldy tmpy + rts +} + +#pragma bytecode(BC_CONV_I32_F32, inp_conv_i32_f32) + __asm f32_to_i16 { jsr freg.split_aexp @@ -3615,6 +3711,90 @@ __asm inp_conv_f32_u16 #pragma bytecode(BC_CONV_F32_U16, inp_conv_f32_u16) +__asm f32_to_u32 +{ + jsr freg.split_aexp + lda tmp + 4 + cmp #$7f + bcs W1 + lda #0 +F0: + sta accu + sta accu + 1 + sta accu + 2 + sta accu + 3 + rts +W1: + sec + sbc #$9e + beq W2 + bcc W3 + lda #$ff + bne F0 + +W3: + tax + + lda #0 +L1: + lsr accu + 2 + ror accu + 1 + ror accu + 0 + ror + inx + bne L1 + +W2: + ldx accu + 2 + stx accu + 3 + ldx accu + 1 + stx accu + 2 + ldx accu + stx accu + 1 + sta accu + + rts +} + +__asm f32_to_i32 +{ + lda accu + 3 + bmi W1 + jmp f32_to_u32 +W1: + jsr f32_to_u32 + + sec + lda #0 + sbc accu + sta accu + lda #0 + sbc accu + 1 + sta accu + 1 + lda #0 + sbc accu + 2 + sta accu + 2 + lda #0 + sbc accu + 3 + sta accu + 3 + + rts +} + +__asm inp_conv_f32_i32 +{ + jmp f32_to_i32 +} + +#pragma bytecode(BC_CONV_F32_I32, inp_conv_f32_i32) + +__asm inp_conv_f32_u32 +{ + jmp f32_to_u32 +} + +#pragma bytecode(BC_CONV_F32_U32, inp_conv_f32_u32) + __asm inp_op_abs_f32 { lda accu + 3 @@ -3809,6 +3989,10 @@ fru3: #pragma runtime(ftou, f32_to_u16) #pragma runtime(ffloor, fround.ffloor) #pragma runtime(fceil, fround.fceil) +#pragma runtime(ffromli, sint32_to_float) +#pragma runtime(ffromlu, uint32_to_float) +#pragma runtime(ftoli, f32_to_i32) +#pragma runtime(ftolu, f32_to_u32) __asm inp_op_floor_f32 { diff --git a/include/crt.h b/include/crt.h index 5d5630a..8d428ac 100644 --- a/include/crt.h +++ b/include/crt.h @@ -186,6 +186,11 @@ enum ByteCode BC_BINOP_SHR_I32, BC_BINOP_CMP_U32, BC_BINOP_CMP_S32, + + BC_CONV_U32_F32, + BC_CONV_I32_F32, + BC_CONV_F32_U32, + BC_CONV_F32_I32, }; #endif diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index b0093d7..bdc5d88 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -623,6 +623,10 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used) case BC_OP_CEIL_F32: case BC_CONV_F32_U16: case BC_CONV_F32_I16: + case BC_CONV_U32_F32: + case BC_CONV_I32_F32: + case BC_CONV_F32_U32: + case BC_CONV_F32_I32: used = 0xffffffff; break; @@ -1278,6 +1282,23 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl block->PutByte(mRegister); break; } + case BC_CONV_U32_F32: + case BC_CONV_I32_F32: + case BC_CONV_F32_U32: + case BC_CONV_F32_I32: + { + block->PutCode(generator, BC_EXTRT); + + LinkerReference rl; + rl.mOffset = block->mCode.Size(); + rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE; + rl.mRefObject = generator->mExtByteCodes[mCode - 128]; + rl.mRefOffset = 0; + block->mRelocations.Push(rl); + block->PutWord(0); + block->PutByte(mRegister); + break; + } default: assert(false); @@ -3721,6 +3742,67 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter } break; + case IA_FLOAT2LINT: + { + ByteCodeInstruction lins(BC_LOAD_REG_32); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + lins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(lins); + + ByteCodeInstruction bins(BC_CONV_F32_I32); + mIns.Push(bins); + + ByteCodeInstruction sins(BC_STORE_REG_32); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(sins); + + } break; + case IA_LINT2FLOAT: + { + ByteCodeInstruction lins(BC_LOAD_REG_32); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + lins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(lins); + + ByteCodeInstruction bins(BC_CONV_I32_F32); + mIns.Push(bins); + + ByteCodeInstruction sins(BC_STORE_REG_32); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(sins); + + } break; + case IA_FLOAT2LUINT: + { + ByteCodeInstruction lins(BC_LOAD_REG_32); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + lins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(lins); + + ByteCodeInstruction bins(BC_CONV_F32_U32); + mIns.Push(bins); + + ByteCodeInstruction sins(BC_STORE_REG_32); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(sins); + + } break; + case IA_LUINT2FLOAT: + { + ByteCodeInstruction lins(BC_LOAD_REG_32); + lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + lins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(lins); + + ByteCodeInstruction bins(BC_CONV_U32_F32); + mIns.Push(bins); + + ByteCodeInstruction sins(BC_STORE_REG_32); + sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(sins); + + } break; + case IA_EXT8TO16S: { if (ins->mSrc[0].mTemp == ins->mDst.mTemp) diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index 955c675..85f886e 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -186,7 +186,12 @@ enum ByteCode BC_BINOP_SHR_U32, BC_BINOP_SHR_I32, BC_BINOP_CMP_U32, - BC_BINOP_CMP_S32 + BC_BINOP_CMP_S32, + + BC_CONV_U32_F32, + BC_CONV_I32_F32, + BC_CONV_F32_U32, + BC_CONV_F32_I32, }; class ByteCodeProcedure; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index a5aedc7..14eede2 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -950,8 +950,12 @@ bool Compiler::GenerateCode(void) RegisterRuntime(loc, Ident::Unique("fceil")); RegisterRuntime(loc, Ident::Unique("ftoi")); RegisterRuntime(loc, Ident::Unique("ftou")); + RegisterRuntime(loc, Ident::Unique("ftoli")); + RegisterRuntime(loc, Ident::Unique("ftolu")); RegisterRuntime(loc, Ident::Unique("ffromi")); RegisterRuntime(loc, Ident::Unique("ffromu")); + RegisterRuntime(loc, Ident::Unique("ffromli")); + RegisterRuntime(loc, Ident::Unique("ffromlu")); RegisterRuntime(loc, Ident::Unique("fcmp")); RegisterRuntime(loc, Ident::Unique("bcexec")); RegisterRuntime(loc, Ident::Unique("jmpaddr")); diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index b5a8f6b..e3d0cd1 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -484,6 +484,19 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank fprintf(file, "CNVFS\tACCU"); break; + case BC_CONV_U32_F32: + fprintf(file, "CNVLUF\tACCU"); + break; + case BC_CONV_I32_F32: + fprintf(file, "CNVLSF\tACCU"); + break; + case BC_CONV_F32_U32: + fprintf(file, "CNVFLU\tACCU"); + break; + case BC_CONV_F32_I32: + fprintf(file, "CNVFLS\tACCU"); + break; + case BC_MALLOC: fprintf(file, "MALLOC\tACCU"); break; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index a3818ae..205cdc6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3074,6 +3074,8 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONVERSION_OPERATOR && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2INT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_INT2FLOAT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2UINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_UINT2FLOAT && + tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2LINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_LINT2FLOAT && + tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2LUINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_LUINT2FLOAT && tvalue[ins->mSrc[0].mTemp]->mOperator == tvalue[ins->mSrc[1].mTemp]->mOperator) { ins->mSrc[0].mType = tvalue[ins->mSrc[0].mTemp]->mSrc[0].mType; @@ -3086,7 +3088,9 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr else if (ins->mSrc[1].mTemp >= 0 && tvalue[ins->mSrc[1].mTemp] && tvalue[ins->mSrc[1].mTemp]->mCode == IC_CONVERSION_OPERATOR && ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2INT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_INT2FLOAT && - tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2UINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_UINT2FLOAT) + tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2UINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_UINT2FLOAT && + tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2LINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_LINT2FLOAT && + tvalue[ins->mSrc[1].mTemp]->mOperator != IA_FLOAT2LUINT && tvalue[ins->mSrc[1].mTemp]->mOperator != IA_LUINT2FLOAT) { bool toconst = false; int cvalue = 0; @@ -3287,8 +3291,10 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr else if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONVERSION_OPERATOR && ins->mSrc[1].mTemp >= 0 && tvalue[ins->mSrc[1].mTemp] && tvalue[ins->mSrc[1].mTemp]->mCode == IC_CONSTANT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_FLOAT2INT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_INT2FLOAT && - tvalue[ins->mSrc[0].mTemp]->mOperator != IA_FLOAT2UINT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_UINT2FLOAT) - { + tvalue[ins->mSrc[0].mTemp]->mOperator != IA_FLOAT2UINT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_UINT2FLOAT && + tvalue[ins->mSrc[0].mTemp]->mOperator != IA_FLOAT2LINT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_LINT2FLOAT && + tvalue[ins->mSrc[0].mTemp]->mOperator != IA_FLOAT2LUINT && tvalue[ins->mSrc[0].mTemp]->mOperator != IA_LUINT2FLOAT) + { bool toconst = false; int cvalue = 0; @@ -20393,7 +20399,7 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati for (int i = 1; i < mInstructions.Size(); i++) { InterInstruction* ins(mInstructions[i]); - if (ins->mCode == IC_CONVERSION_OPERATOR && (ins->mOperator == IA_FLOAT2INT || ins->mOperator == IA_FLOAT2UINT) && ins->mSrc[0].mFinal) + if (ins->mCode == IC_CONVERSION_OPERATOR && (ins->mOperator == IA_FLOAT2INT || ins->mOperator == IA_FLOAT2UINT || ins->mOperator == IA_FLOAT2LINT || ins->mOperator == IA_FLOAT2LUINT) && ins->mSrc[0].mFinal) { int j = i - 1; while (j > 0 && CanSwapInstructions(ins, mInstructions[j])) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 2c8214d..5b8c8a1 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -105,10 +105,15 @@ enum InterOperator IA_CMPLEU, IA_CMPGU, IA_CMPLU, + IA_FLOAT2INT, IA_INT2FLOAT, IA_FLOAT2UINT, IA_UINT2FLOAT, + IA_FLOAT2LINT, + IA_LINT2FLOAT, + IA_FLOAT2LUINT, + IA_LUINT2FLOAT, IA_EXT8TO16U, IA_EXT8TO32U, diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 7552ede..4c68800 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -349,8 +349,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); - cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; - cins->mSrc[0].mType = IT_INT16; + if (v.mType->mSize <= 2) + { + cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; + cins->mSrc[0].mType = IT_INT16; + } + else + { + cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_LINT2FLOAT : IA_LUINT2FLOAT; + cins->mSrc[0].mType = IT_INT32; + } cins->mSrc[0].mTemp = stemp; cins->mDst.mType = IT_FLOAT; cins->mDst.mTemp = proc->AddTemporary(IT_FLOAT); @@ -364,11 +372,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p mErrors->Error(exp->mLocation, EWARN_FLOAT_TO_INT, "Float to int conversion, potential loss of precision"); InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); - cins->mOperator = IA_FLOAT2INT; + + if (type->mSize <= 2) + { + cins->mDst.mType = IT_INT16; + if (type->mFlags & DTF_SIGNED) + cins->mOperator = IA_FLOAT2INT; + else + cins->mOperator = IA_FLOAT2UINT; + } + else + { + cins->mDst.mType = IT_INT32; + if (type->mFlags & DTF_SIGNED) + cins->mOperator = IA_FLOAT2LINT; + else + cins->mOperator = IA_FLOAT2LUINT; + } + cins->mSrc[0].mType = IT_FLOAT; cins->mSrc[0].mTemp = v.mTemp; - cins->mDst.mType = IT_INT16; - cins->mDst.mTemp = proc->AddTemporary(IT_INT16); + + cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); v.mTemp = cins->mDst.mTemp; v.mType = type; @@ -4845,8 +4870,17 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } } - ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; - ins->mSrc[0].mType = IT_INT16; + if (vr.mType->mSize <= 2) + { + ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; + ins->mSrc[0].mType = IT_INT16; + } + else + { + ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_LINT2FLOAT : IA_LUINT2FLOAT; + ins->mSrc[0].mType = IT_INT32; + } + ins->mSrc[0].mTemp = stemp; ins->mDst.mType = InterTypeOf(exp->mDecType); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); @@ -4855,11 +4889,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (exp->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) { vr = Dereference(proc, exp, block, inlineMapper, vr); - ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; + if (exp->mDecType->mSize <= 2) + { + ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; + ins->mDst.mType = IT_INT16; + } + else + { + ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2LINT : IA_FLOAT2LUINT; + ins->mDst.mType = IT_INT32; + } + ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; - ins->mDst.mType = IT_INT16; - ins->mDst.mTemp = proc->AddTemporary(IT_INT16); + ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); block->Append(ins); if (exp->mDecType->mSize == 1) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index bd23b25..a7f73bb 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12201,6 +12201,102 @@ void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, NativeCod mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3)); + } break; + case IA_FLOAT2LINT: + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ftoli"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3)); + + } break; + case IA_LINT2FLOAT: + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ffromli"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3)); + + } break; + case IA_FLOAT2LUINT: + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ftolu"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3)); + + } break; + case IA_LUINT2FLOAT: + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ffromlu"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3)); + } break; case IA_EXT8TO16S: mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));