Add float long conversion

This commit is contained in:
drmortalwombat 2024-09-19 09:49:16 +02:00
parent ce0ac30280
commit ce710fca5d
12 changed files with 536 additions and 15 deletions

View File

@ -117,6 +117,9 @@ rem @echo off
@call :test floatmultest.c @call :test floatmultest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test floatinttest.c
@if %errorlevel% neq 0 goto :error
@call :test staticconsttest.c @call :test staticconsttest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

75
autotest/floatinttest.c Normal file
View File

@ -0,0 +1,75 @@
#include <assert.h>
#include <stdio.h>
#include <math.h>
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;
}

View File

@ -3518,6 +3518,102 @@ __asm inp_conv_i16_f32
#pragma bytecode(BC_CONV_I16_F32, 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 __asm f32_to_i16
{ {
jsr freg.split_aexp jsr freg.split_aexp
@ -3615,6 +3711,90 @@ __asm inp_conv_f32_u16
#pragma bytecode(BC_CONV_F32_U16, 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 __asm inp_op_abs_f32
{ {
lda accu + 3 lda accu + 3
@ -3809,6 +3989,10 @@ fru3:
#pragma runtime(ftou, f32_to_u16) #pragma runtime(ftou, f32_to_u16)
#pragma runtime(ffloor, fround.ffloor) #pragma runtime(ffloor, fround.ffloor)
#pragma runtime(fceil, fround.fceil) #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 __asm inp_op_floor_f32
{ {

View File

@ -186,6 +186,11 @@ enum ByteCode
BC_BINOP_SHR_I32, BC_BINOP_SHR_I32,
BC_BINOP_CMP_U32, 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,
}; };
#endif #endif

View File

@ -623,6 +623,10 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
case BC_OP_CEIL_F32: case BC_OP_CEIL_F32:
case BC_CONV_F32_U16: case BC_CONV_F32_U16:
case BC_CONV_F32_I16: 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; used = 0xffffffff;
break; break;
@ -1278,6 +1282,23 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
block->PutByte(mRegister); block->PutByte(mRegister);
break; 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: default:
assert(false); assert(false);
@ -3721,6 +3742,67 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter
} break; } 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: case IA_EXT8TO16S:
{ {
if (ins->mSrc[0].mTemp == ins->mDst.mTemp) if (ins->mSrc[0].mTemp == ins->mDst.mTemp)

View File

@ -186,7 +186,12 @@ enum ByteCode
BC_BINOP_SHR_U32, BC_BINOP_SHR_U32,
BC_BINOP_SHR_I32, BC_BINOP_SHR_I32,
BC_BINOP_CMP_U32, 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; class ByteCodeProcedure;

View File

@ -950,8 +950,12 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("fceil")); RegisterRuntime(loc, Ident::Unique("fceil"));
RegisterRuntime(loc, Ident::Unique("ftoi")); RegisterRuntime(loc, Ident::Unique("ftoi"));
RegisterRuntime(loc, Ident::Unique("ftou")); RegisterRuntime(loc, Ident::Unique("ftou"));
RegisterRuntime(loc, Ident::Unique("ftoli"));
RegisterRuntime(loc, Ident::Unique("ftolu"));
RegisterRuntime(loc, Ident::Unique("ffromi")); RegisterRuntime(loc, Ident::Unique("ffromi"));
RegisterRuntime(loc, Ident::Unique("ffromu")); RegisterRuntime(loc, Ident::Unique("ffromu"));
RegisterRuntime(loc, Ident::Unique("ffromli"));
RegisterRuntime(loc, Ident::Unique("ffromlu"));
RegisterRuntime(loc, Ident::Unique("fcmp")); RegisterRuntime(loc, Ident::Unique("fcmp"));
RegisterRuntime(loc, Ident::Unique("bcexec")); RegisterRuntime(loc, Ident::Unique("bcexec"));
RegisterRuntime(loc, Ident::Unique("jmpaddr")); RegisterRuntime(loc, Ident::Unique("jmpaddr"));

View File

@ -484,6 +484,19 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
fprintf(file, "CNVFS\tACCU"); fprintf(file, "CNVFS\tACCU");
break; 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: case BC_MALLOC:
fprintf(file, "MALLOC\tACCU"); fprintf(file, "MALLOC\tACCU");
break; break;

View File

@ -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 && 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_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 &&
tvalue[ins->mSrc[0].mTemp]->mOperator == tvalue[ins->mSrc[1].mTemp]->mOperator) tvalue[ins->mSrc[0].mTemp]->mOperator == tvalue[ins->mSrc[1].mTemp]->mOperator)
{ {
ins->mSrc[0].mType = tvalue[ins->mSrc[0].mTemp]->mSrc[0].mType; 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 && 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 && 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_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; bool toconst = false;
int cvalue = 0; int cvalue = 0;
@ -3287,7 +3291,9 @@ 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 && 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 && 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_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; bool toconst = false;
int cvalue = 0; int cvalue = 0;
@ -20393,7 +20399,7 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
for (int i = 1; i < mInstructions.Size(); i++) for (int i = 1; i < mInstructions.Size(); i++)
{ {
InterInstruction* ins(mInstructions[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; int j = i - 1;
while (j > 0 && CanSwapInstructions(ins, mInstructions[j])) while (j > 0 && CanSwapInstructions(ins, mInstructions[j]))

View File

@ -105,10 +105,15 @@ enum InterOperator
IA_CMPLEU, IA_CMPLEU,
IA_CMPGU, IA_CMPGU,
IA_CMPLU, IA_CMPLU,
IA_FLOAT2INT, IA_FLOAT2INT,
IA_INT2FLOAT, IA_INT2FLOAT,
IA_FLOAT2UINT, IA_FLOAT2UINT,
IA_UINT2FLOAT, IA_UINT2FLOAT,
IA_FLOAT2LINT,
IA_LINT2FLOAT,
IA_FLOAT2LUINT,
IA_LUINT2FLOAT,
IA_EXT8TO16U, IA_EXT8TO16U,
IA_EXT8TO32U, IA_EXT8TO32U,

View File

@ -349,8 +349,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
} }
InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR);
if (v.mType->mSize <= 2)
{
cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT;
cins->mSrc[0].mType = IT_INT16; 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->mSrc[0].mTemp = stemp;
cins->mDst.mType = IT_FLOAT; cins->mDst.mType = IT_FLOAT;
cins->mDst.mTemp = proc->AddTemporary(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"); 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); InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR);
if (type->mSize <= 2)
{
cins->mDst.mType = IT_INT16;
if (type->mFlags & DTF_SIGNED)
cins->mOperator = IA_FLOAT2INT; 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].mType = IT_FLOAT;
cins->mSrc[0].mTemp = v.mTemp; 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); block->Append(cins);
v.mTemp = cins->mDst.mTemp; v.mTemp = cins->mDst.mTemp;
v.mType = type; v.mType = type;
@ -4845,8 +4870,17 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
} }
if (vr.mType->mSize <= 2)
{
ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT;
ins->mSrc[0].mType = IT_INT16; 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->mSrc[0].mTemp = stemp;
ins->mDst.mType = InterTypeOf(exp->mDecType); ins->mDst.mType = InterTypeOf(exp->mDecType);
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); 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) else if (exp->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT)
{ {
vr = Dereference(proc, exp, block, inlineMapper, vr); vr = Dereference(proc, exp, block, inlineMapper, vr);
if (exp->mDecType->mSize <= 2)
{
ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; 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].mType = InterTypeOf(vr.mType);
ins->mSrc[0].mTemp = vr.mTemp; ins->mSrc[0].mTemp = vr.mTemp;
ins->mDst.mType = IT_INT16; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
ins->mDst.mTemp = proc->AddTemporary(IT_INT16);
block->Append(ins); block->Append(ins);
if (exp->mDecType->mSize == 1) if (exp->mDecType->mSize == 1)

View File

@ -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_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)); 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; } break;
case IA_EXT8TO16S: case IA_EXT8TO16S:
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));