Author: leo
Date: Wed Oct 19 11:36:09 2005
New Revision: 9514
Modified:
trunk/jit/i386/jit_emit.h
trunk/t/op/jitn.t
Log:
Fix a nasty x86/JIT bug related to precision
* examples/pir/mandel.pir produced slightly different 'pixels',
when run with x86/JIT
* reduced the bug to t/op/jitn_14.pasm
* which is just a precision problem: storing intermediate results
into FLOATVAL regs rounds to 64 bit, while keeping in the
x86 FP reg stack doesn't round - bumm.
Solution: reduce precision to 64 bit by emitting fldcw
Modified: trunk/jit/i386/jit_emit.h
==============================================================================
--- trunk/jit/i386/jit_emit.h (original)
+++ trunk/jit/i386/jit_emit.h Wed Oct 19 11:36:09 2005
@@ -1350,6 +1350,9 @@ static unsigned char *lastpc;
# define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; }
# define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; }
+# define emitm_fldcw(pc, mem) \
+ emitm_fl_2(pc, emit_b00, 1, emit_b101, 0, 0, 0, mem)
+
# if defined(NEG_MINUS_ZERO)
# define jit_emit_neg_r_n(pc, r) { \
if (r) { \
@@ -2738,6 +2741,8 @@ Parrot_jit_dofixup(Parrot_jit_info_t *ji
jit_info->arena.fixups = NULL;
}
+static int control_word = 0x27f;
+
# ifndef JIT_CGP
void
Parrot_jit_begin(Parrot_jit_info_t *jit_info,
@@ -2750,6 +2755,7 @@ Parrot_jit_begin(Parrot_jit_info_t *jit_
/* Maintain the stack frame pointer for the sake of gdb */
jit_emit_stack_frame_enter(jit_info->native_ptr);
+ emitm_fldcw(jit_info->native_ptr, &control_word);
/* stack:
* 12 pc
* 8 interpreter
@@ -2865,6 +2871,7 @@ Parrot_jit_begin(Parrot_jit_info_t *jit_
Interp * interpreter)
{
jit_emit_stack_frame_enter(jit_info->native_ptr);
+ emitm_fldcw(jit_info->native_ptr, &control_word);
emitm_pushl_r(jit_info->native_ptr, emit_EBX);
/* get the pc from stack: mov 12(%ebp), %ebx */
emitm_movl_m_r(jit_info->native_ptr, emit_EBX, emit_EBP, emit_None, 1, 12);
@@ -3382,6 +3389,16 @@ preg:
#if JIT_EMIT == 0
# define REQUIRES_CONSTANT_POOL 0
/* # define INT_REGISTERS_TO_MAP 4 definition at top */
+/*
+ * examples/pir/mandel.pir and t/op/jitn_14 show rounding problems
+ * due to keeping intermediate results in FP registers
+ * When intermediates are written back to parrot regs, rounding to
+ * 64 bit is performed, which changes results slightly
+ *
+ * One method is to just turn off mapped floats. The other one is
+ * setting a different control word (with precision control = double)
+ * see emitm_fldcw above
+ */
# define FLOAT_REGISTERS_TO_MAP 4
# ifndef JIT_IMCC
Modified: trunk/t/op/jitn.t
==============================================================================
--- trunk/t/op/jitn.t (original)
+++ trunk/t/op/jitn.t Wed Oct 19 11:36:09 2005
@@ -18,7 +18,7 @@ registers.
=cut
-use Parrot::Test tests => 13;
+use Parrot::Test tests => 14;
output_is(<<'CODE', <<'OUTPUT', "sub_n_n_n 1,2,3 mapped");
set N0,0
@@ -315,3 +315,15 @@ CODE
123
OUT
+output_is(<<'CODE', <<'OUTPUT', "rounding due to mapped");
+ set N0, 15
+ mul N0, N0, 0.1
+ sub N0, 1.5
+ unless N0, z
+ print "not "
+z:
+ print "zero\n"
+ end
+CODE
+zero
+OUTPUT