Author: leo
Date: Thu Apr 14 02:52:06 2005
New Revision: 7828

Modified:
   trunk/jit/i386/jit_emit.h
   trunk/t/op/jit.t
Log:
fix i386 JIT bug

* this one came up on IRC yesterday



Modified: trunk/jit/i386/jit_emit.h
==============================================================================
--- trunk/jit/i386/jit_emit.h   (original)
+++ trunk/jit/i386/jit_emit.h   Thu Apr 14 02:52:06 2005
@@ -578,6 +578,11 @@
 {
     char *pc = jit_info->native_ptr;
     int saved = 0;
+    int div_ecx = 0;
+    Parrot_jit_register_usage_t *ru;
+
+    assert(src != emit_EAX);
+
     if (dest != emit_EAX) {
         jit_emit_mov_rr_i(pc, emit_EAX, dest);
     }
@@ -585,55 +590,73 @@
         /* all ok, we can globber it */
     }
     else {
-        /* if ECX is mapped, push EDX on stack */
-        if (jit_info->optimizer->cur_section->ru[0].registers_used ==
-                INT_REGISTERS_TO_MAP) {
-            emitm_pushl_r(pc, emit_EDX);
-            saved = 2;
-        }
-        /* if EDX is mapped, save it in ECX */
-        else if (jit_info->optimizer->cur_section->ru[0].registers_used ==
-                INT_REGISTERS_TO_MAP - 1) {
-            saved = 1;
+        ru = jit_info->optimizer->cur_section->ru + 0;
+        /* if ECX is not mapped use it */
+        if (ru->registers_used < INT_REGISTERS_TO_MAP && src == emit_EDX) {
             jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+            div_ecx = 1;
         }
+        else
+            /* if EDX is mapped, preserve EDX on stack */
+            if (ru->registers_used >= INT_REGISTERS_TO_MAP - 1) {
+                emitm_pushl_r(pc, emit_EDX);
+                saved = 1;
+                /* if EDX is the src, we need another temp register: ECX */
+                if (src == emit_EDX) {
+                    /* if ECX is mapped save it, but not if it's dest */
+                    if (ru->registers_used == INT_REGISTERS_TO_MAP &&
+                            dest != emit_ECX) {
+                        emitm_pushl_r(pc, emit_ECX);
+                        saved = 2;
+                    }
+                    /* else just use it */
+                    jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+                    div_ecx = 1;
+                }
+            }
     }
 #  if 0
     jit_emit_cdq(pc);
 #  else
     /* this sequence allows 2 other instructions to run parallel */
-    jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+    if (dest != emit_EDX) {
+        jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+    }
     pc = emit_shift_i_r(pc, emit_b111, 31, emit_EDX); /* SAR 31 */
 #  endif
-    if (src == emit_EDX) {
-        assert(saved == 1);
+    if (div_ecx) {
         emitm_sdivl_r(pc, emit_ECX);
     }
     else {
         emitm_sdivl_r(pc, src);
     }
+    if (saved == 2) {
+        emitm_popl_r(pc, emit_ECX);
+    }
     if (is_div) {
         /* result = quotient in EAX */
-        if (saved == 1) {
-            jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+        if (saved) {
+            emitm_popl_r(pc, emit_EDX);
         }
         if (dest != emit_EAX) {
             jit_emit_mov_rr_i(pc, dest, emit_EAX);
         }
-        if (saved == 2) {
-            emitm_popl_r(pc, emit_EDX);
-        }
     }
     else {
         /* result = remainder in EDX */
-        if (dest != emit_EDX) {
+        if (saved) {
+            emitm_popl_r(pc, emit_EAX);
             jit_emit_mov_rr_i(pc, dest, emit_EDX);
-            if (saved == 1) {
-                jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
-            }
-            else if (saved == 2)
-                emitm_popl_r(pc, emit_EDX);
+            jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
         }
+        else {
+            if (dest != emit_EDX)
+                jit_emit_mov_rr_i(pc, dest, emit_EDX);
+        }
+    }
+    if (!saved && div_ecx) {
+        /* restore EDX */
+        jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
     }
     return pc;
 }

Modified: trunk/t/op/jit.t
==============================================================================
--- trunk/t/op/jit.t    (original)
+++ trunk/t/op/jit.t    Thu Apr 14 02:52:06 2005
@@ -23,7 +23,7 @@
 =cut
 
 # test WRT JIT register allocation
-use Parrot::Test tests => 59;
+use Parrot::Test tests => 60;
 
 output_is(<<'CODE', <<'OUTPUT', "add_i_i_i 1,2,3 mapped");
 set I0,0
@@ -1184,4 +1184,16 @@
 154
 OUTPUT
 
-1;
+output_is(<<'CODE', <<'OUTPUT', "div bug");
+    set I1, 1
+    set I2, 2
+    set I3, 4
+    set I4, 4
+    mul I3, I1
+    div I3, I2
+    print I3
+    print "\n"
+    end
+CODE
+2
+OUTPUT

Reply via email to