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