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

Reply via email to