diff --git a/ChangeLog b/ChangeLog index e53376a..06e206f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-08-08 Klaus Treichel + + * jit/jit-rules-x86.ins (JIT_OP_FLOAT32_TO_INT, + JIT_OP_FLOAT64_TO_INT, JIT_OP_FLOAT32_TO_LONG, + JIT_OP_FLOAT64_TO_LONG, JIT_OP_INT_TO_FLOAT32, + JIT_OP_INT_TO_FLOAT64, JIT_OP_UINT_TO_FLOAT32, + JIT_OP_UINT_TO_FLOAT64, JIT_OP_LONG_TO_FLOAT32, + JIT_OP_LONG_TO_FLOAT64, JIT_OP_ULONG_TO_FLOAT32, + JIT_OP_ULONG_TO_FLOAT64, JIT_OP_FLOAT64_TO_FLOAT32, + JIT_OP_FLOAT32_TO_FLOAT64: Add support for these new opcodes. + + * tests/math.pas: Add tests for integer/float conversions. + 2010-08-07 Klaus Treichel * config/jit-opcodes.ops: Add opcodes for direct conversions from diff --git a/jit/jit-rules-x86.ins b/jit/jit-rules-x86.ins index bc5a1a8..7196198 100644 --- a/jit/jit-rules-x86.ins +++ b/jit/jit-rules-x86.ins @@ -143,7 +143,7 @@ JIT_OP_EXPAND_UINT: x86_clear_reg(inst, %1); } -JIT_OP_NFLOAT_TO_INT: stack +JIT_OP_FLOAT32_TO_INT, JIT_OP_FLOAT64_TO_INT, JIT_OP_NFLOAT_TO_INT: stack [=reg, freg] -> { /* allocate space on the stack for 2 shorts and 1 int */ x86_alu_reg_imm(inst, X86_SUB, X86_ESP, 8); @@ -164,7 +164,7 @@ JIT_OP_NFLOAT_TO_INT: stack x86_alu_reg_imm(inst, X86_ADD, X86_ESP, 8); } -JIT_OP_NFLOAT_TO_LONG: stack +JIT_OP_FLOAT32_TO_LONG, JIT_OP_FLOAT64_TO_LONG, JIT_OP_NFLOAT_TO_LONG: stack [=lreg, freg] -> { /* allocate space on the stack for 2 shorts and 1 long */ x86_alu_reg_imm(inst, X86_SUB, X86_ESP, 12); @@ -186,7 +186,23 @@ JIT_OP_NFLOAT_TO_LONG: stack x86_alu_reg_imm(inst, X86_ADD, X86_ESP, 12); } -JIT_OP_INT_TO_NFLOAT: +JIT_OP_INT_TO_FLOAT32: + [=freg, local] -> { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(void *)); + x86_fild_membase(inst, X86_EBP, $2, 0); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(void *)); + } + [=freg, reg] -> { + x86_push_reg(inst, $2); + x86_fild_membase(inst, X86_ESP, 0, 0); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_nint)); + } + +JIT_OP_INT_TO_FLOAT64, JIT_OP_INT_TO_NFLOAT: [=freg, local] -> { x86_fild_membase(inst, X86_EBP, $2, 0); } @@ -196,7 +212,18 @@ JIT_OP_INT_TO_NFLOAT: x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_nint)); } -JIT_OP_UINT_TO_NFLOAT: +JIT_OP_UINT_TO_FLOAT32: + [=freg, reg, scratch reg] -> { + x86_clear_reg(inst, $3); + x86_push_reg(inst, $3); + x86_push_reg(inst, $2); + x86_fild_membase(inst, X86_ESP, 0, 1); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); + } + +JIT_OP_UINT_TO_FLOAT64, JIT_OP_UINT_TO_NFLOAT: [=freg, reg, scratch reg] -> { x86_clear_reg(inst, $3); x86_push_reg(inst, $3); @@ -205,6 +232,40 @@ JIT_OP_UINT_TO_NFLOAT: x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); } +JIT_OP_LONG_TO_FLOAT32: + [=freg, local] -> { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float32)); + x86_fild_membase(inst, X86_EBP, $2, 1); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_float32)); + } + [=freg, lreg] -> { + x86_push_reg(inst, %2); + x86_push_reg(inst, $2); + x86_fild_membase(inst, X86_ESP, 0, 1); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); + } + +JIT_OP_LONG_TO_FLOAT64: + [=freg, local] -> { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float64)); + x86_fild_membase(inst, X86_EBP, $2, 1); + x86_fst_membase(inst, X86_ESP, 0, 1, 1); + x86_fld_membase(inst, X86_ESP, 0, 1); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_float64)); + } + [=freg, lreg] -> { + x86_push_reg(inst, %2); + x86_push_reg(inst, $2); + x86_fild_membase(inst, X86_ESP, 0, 1); + x86_fst_membase(inst, X86_ESP, 0, 1, 1); + x86_fld_membase(inst, X86_ESP, 0, 1); + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); + } + JIT_OP_LONG_TO_NFLOAT: [=freg, local] -> { x86_fild_membase(inst, X86_EBP, $2, 1); @@ -216,7 +277,7 @@ JIT_OP_LONG_TO_NFLOAT: x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); } -JIT_OP_ULONG_TO_NFLOAT: more_space +JIT_OP_ULONG_TO_FLOAT32, JIT_OP_ULONG_TO_FLOAT64, JIT_OP_ULONG_TO_NFLOAT: more_space [=freg, lreg] -> { /* TODO: review wrt relocation for elf pre-compilation */ static float f2pow64; @@ -230,15 +291,25 @@ JIT_OP_ULONG_TO_NFLOAT: more_space x86_push_reg(inst, %2); x86_push_reg(inst, $2); x86_fild_membase(inst, X86_ESP, 0, 1); - x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); x86_test_reg_reg(inst, %2, %2); patch = inst; x86_branch8(inst, X86_CC_NS, 0, 1); x86_fp_op_mem(inst, X86_FADD, &f2pow64, 0); x86_patch(patch, inst); + if(insn->opcode == JIT_OP_ULONG_TO_FLOAT32) + { + x86_fst_membase(inst, X86_ESP, 0, 0, 1); + x86_fld_membase(inst, X86_ESP, 0, 0); + } + else if(insn->opcode == JIT_OP_ULONG_TO_FLOAT64) + { + x86_fst_membase(inst, X86_ESP, 0, 1, 1); + x86_fld_membase(inst, X86_ESP, 0, 1); + } + x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_long)); } -JIT_OP_NFLOAT_TO_FLOAT32: stack +JIT_OP_FLOAT64_TO_FLOAT32, JIT_OP_NFLOAT_TO_FLOAT32: stack [freg] -> { x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(void *)); x86_fst_membase(inst, X86_ESP, 0, 0, 1); @@ -254,7 +325,7 @@ JIT_OP_NFLOAT_TO_FLOAT64: stack x86_alu_reg_imm(inst, X86_ADD, X86_ESP, sizeof(jit_float64)); } -JIT_OP_FLOAT32_TO_NFLOAT, JIT_OP_FLOAT64_TO_NFLOAT: copy, stack +JIT_OP_FLOAT32_TO_NFLOAT, JIT_OP_FLOAT32_TO_FLOAT64, JIT_OP_FLOAT64_TO_NFLOAT: copy, stack [freg] -> { /* Nothing to do: loading the value onto the FP stack is sufficient */ } diff --git a/tests/math.pas b/tests/math.pas index 8f4fcee..09f70f2 100644 --- a/tests/math.pas +++ b/tests/math.pas @@ -90,6 +90,131 @@ begin nfneg := -f; end; +procedure run_conversion_tests; +var + f: ShortReal; + d: Real; + nf: LongReal; + i: Integer; + u: Cardinal; + l: LongInt; + ul: LongCard; +begin + + { Tests for conversions from ShortReal to other types } + f:= 1.5; + run("math_conv_float32_int 1.5", Integer(f) = 1); + f:= ShortReal(-1.5); + run("math_conv_float32_int -1.5", Integer(f) = -1); + f:= 1.5; + run("math_conv_float32_uint 1.5", Cardinal(f) = Cardinal(1)); + { The float mantissa is less than 32 bit so precision might get lost } + f:= ShortReal(81234500H); + run("math_conv_float32_uint 81234500H", Cardinal(f) = Cardinal(81234500H)); + f:= 1.5; + run("math_conv_float32_long 1.5", LongInt(f) = LongInt(1)); + f:= ShortReal(-1.5); + run("math_conv_float32_long -1.5", LongInt(f) = LongInt(-1)); + f:= 1.5; + run("math_conv_float32_ulong 1.5", LongCard(f) = LongCard(1)); + { The 32-bit float fraction is less than 32 bit so precision might get lost } + f:= ShortReal(81234500H); + run("math_conv_float32_ulong 81234500H", LongCard(f) = LongCard(81234500H)); + + { Tests for conversions from Real to other types } + d := 1.5; + run("math_conv_float64_int 1.5", Integer(d) = 1); + d := Real(-1.5); + run("math_conv_float64_int -1.5", Integer(d) = -1); + d := 1.5; + run("math_conv_float64_uint 1.5", Cardinal(d) = Cardinal(1)); + d := Real(81234567H); + run("math_conv_float64_uint 81234567H", Cardinal(d) = Cardinal(81234567H)); + d := 1.5; + run("math_conv_float64_long 1.5", LongInt(d) = LongInt(1)); + d := Real(-1.5); + run("math_conv_float64_long -1.5", LongInt(d) = LongInt(-1)); + d := 1.5; + run("math_conv_float64_ulong 1.5", LongCard(d) = LongCard(1)); + { The 64-bit float fraction is less than 64 bit so precision might get lost } + d := Real(8123456789ABC000H); + run("math_conv_float64_ulong 8123456789ABC000H", LongCard(d) = LongCard(8123456789ABC000H)); + + { Tests for conversions from LongReal to other types } + nf := 1.5; + run("math_conv_nfloat_int 1.5", Integer(nf) = 1); + nf := LongReal(-1.5); + run("math_conv_nfloat_int -1.5", Integer(nf) = -1); + nf := 1.5; + run("math_conv_nfloat_uint 1.5", Cardinal(nf) = Cardinal(1)); + nf := LongReal(81234567H); + run("math_conv_nfloat_uint 81234567H", Cardinal(nf) = Cardinal(81234567H)); + nf := 1.5; + run("math_conv_nfloat_long 1.5", LongInt(nf) = LongInt(1)); + nf := LongReal(-1.5); + run("math_conv_nfloat_long -1.5", LongInt(nf) = LongInt(-1)); + nf := 1.5; + run("math_conv_nfloat_ulong 1.5", LongCard(nf) = LongCard(1)); + { The native float fraction might less than 64 bit so precision might get lost } + nf:= LongReal(8123456789ABC000H); + run("math_conv_nfloat_ulong 8123456789ABC000H", LongCard(nf) = LongCard(8123456789ABC000H)); + + { Tests for conversions from integer types to ShortReal } + i := 1; + runf("math_conv_int_float32 1", ShortReal(i), ShortReal(1.0), 0.00001); + i := -1; + runf("math_conv_int_float32 -1", ShortReal(i), ShortReal(-1.0), 0.00001); + u := 1; + runf("math_conv_uint_float32 1", ShortReal(u), ShortReal(1.0), 0.00001); + u := 81234500H; + runf("math_conv_uint_float32 81234500H", ShortReal(u), ShortReal(81234500H), 0.00001); + l := 1; + runf("math_conv_long_float32 1", ShortReal(l), ShortReal(1.0), 0.00001); + l := -1; + runf("math_conv_long_float32 -1", ShortReal(l), ShortReal(-1.0), 0.00001); + ul := 1; + runf("math_conv_ulong_float32 1", ShortReal(ul), ShortReal(1.0), 0.00001); + ul := 8123450000000000H; + runf("math_conv_ulong_float32 8123450000000000H", ShortReal(ul), ShortReal(8123450000000000H), 0.00001); + + { Tests for conversions from integer types to Real } + i := 1; + rund("math_conv_int_float64 1", Real(i), Real(1.0), 0.00001); + i := -1; + rund("math_conv_int_float64 -1", Real(i), Real(-1.0), 0.00001); + u := 1; + rund("math_conv_uint_float64 1", Real(u), Real(1.0), 0.00001); + u := 81234567H; + rund("math_conv_uint_float64 81234567H", Real(u), Real(81234567H), 0.00001); + l := 1; + rund("math_conv_long_float64 1", Real(l), Real(1.0), 0.00001); + l := -1; + rund("math_conv_long_float64 -1", Real(l), Real(-1.0), 0.00001); + ul := 1; + rund("math_conv_ulong_float64 1", Real(ul), Real(1.0), 0.00001); + ul := 8123456789ABC000H; + rund("math_conv_ulong_float64 8123456789ABC000H", Real(ul), Real(8123456789ABC000H), 0.00001); + + { Tests for conversions from integer types to LomgReal } + i := 1; + runn("math_conv_int_nfloat 1", LongReal(i), LongReal(1.0), 0.00001); + i := -1; + runn("math_conv_int_nfloat -1", LongReal(i), LongReal(-1.0), 0.00001); + u := 1; + runn("math_conv_uint_nfloat 1", LongReal(u), LongReal(1.0), 0.00001); + u := 81234567H; + runn("math_conv_uint_nfloat 81234567H", LongReal(u), LongReal(81234567H), 0.00001); + l := 1; + runn("math_conv_long_nfloat 1", LongReal(l), LongReal(1.0), 0.00001); + l := -1; + runn("math_conv_long_nfloat -1", LongReal(l), LongReal(-1.0), 0.00001); + ul := 1; + runn("math_conv_ulong_nfloat 1", LongReal(ul), LongReal(1.0), 0.00001); + ul := 8123456789ABC000H; + runn("math_conv_ulong_nfloat 8123456789ABC000H", LongReal(ul), LongReal(8123456789ABC000H), 0.00001); + +end; + procedure run_tests; var b: Byte; @@ -348,18 +473,19 @@ begin runn("math_n_sqrt_2", Sqrt(LongReal(2.0)), LongReal(1.4142), 0.0001); n := Sqrt(LongReal(-1.0)); run("math_n_sqrt_m1", IsNaN(n)); - runn("math_n_ceil_1.5", Ceil(LongReal(1.5)), LongReal(2.0), 0.00001); - runn("math_n_ceil_m1.5", Ceil(LongReal(-1.5)), LongReal(-1.0), 0.00001); - runn("math_n_floor_1.5", Floor(LongReal(1.5)), LongReal(1.0), 0.00001); - runn("math_n_floor_m1.5", Floor(LongReal(-1.5)), LongReal(-2.0), 0.00001); - runn("math_n_rint_1.5", Rint(LongReal(1.5)), LongReal(2.0), 0.00001); - runn("math_n_rint_2.5", Rint(LongReal(2.5)), LongReal(2.0), 0.00001); - runn("math_n_round_1.5", Round(LongReal(1.5)), LongReal(2.0), 0.00001); - runn("math_n_round_2.5", Round(LongReal(2.5)), LongReal(3.0), 0.00001); - runn("math_n_trunc_1.5", Trunc(LongReal(1.5)), LongReal(1.0), 0.00001); - runn("math_n_trunc_2.5", Trunc(LongReal(2.5)), LongReal(2.0), 0.00001); - runn("math_n_trunc_m1.5", Trunc(LongReal(-1.5)), LongReal(-1.0), 0.00001); + runn("math_n_ceil 1.5", Ceil(LongReal(1.5)), LongReal(2.0), 0.00001); + runn("math_n_ceil -1.5", Ceil(LongReal(-1.5)), LongReal(-1.0), 0.00001); + runn("math_n_floor 1.5", Floor(LongReal(1.5)), LongReal(1.0), 0.00001); + runn("math_n_floor -1.5", Floor(LongReal(-1.5)), LongReal(-2.0), 0.00001); + runn("math_n_rint 1.5", Rint(LongReal(1.5)), LongReal(2.0), 0.00001); + runn("math_n_rint 2.5", Rint(LongReal(2.5)), LongReal(2.0), 0.00001); + runn("math_n_round 1.5", Round(LongReal(1.5)), LongReal(2.0), 0.00001); + runn("math_n_round 2.5", Round(LongReal(2.5)), LongReal(3.0), 0.00001); + runn("math_n_trunc 1.5", Trunc(LongReal(1.5)), LongReal(1.0), 0.00001); + runn("math_n_trunc 2.5", Trunc(LongReal(2.5)), LongReal(2.0), 0.00001); + runn("math_n_trunc -1.5", Trunc(LongReal(-1.5)), LongReal(-1.0), 0.00001); + run_conversion_tests; end; begin