Patchwork tcg: fix deposit_i64 op on 32-bit targets

login
register
mail settings
Submitter Aurelien Jarno
Date April 20, 2013, 10:48 p.m.
Message ID <1366498123-21182-1-git-send-email-aurelien@aurel32.net>
Download mbox | patch
Permalink /patch/238190/
State New
Headers show

Comments

Aurelien Jarno - April 20, 2013, 10:48 p.m.
On 32-bit TCG targets, when emulating deposit_i64 with a mov_i32 +
deposit_i32, care should be taken to not overwrite the low part of
the second argument before the deposit when it is the same the
destination.

This fixes the shld instruction in qemu-system-x86_64, which in turns
fixes booting "system rescue CD version 2.8.0" on this target.

Reported-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
 tcg/tcg-op.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Richard Henderson - April 21, 2013, 7:31 a.m.
On 2013-04-21 00:48, Aurelien Jarno wrote:
> On 32-bit TCG targets, when emulating deposit_i64 with a mov_i32 +
> deposit_i32, care should be taken to not overwrite the low part of
> the second argument before the deposit when it is the same the
> destination.
>
> This fixes the shld instruction in qemu-system-x86_64, which in turns
> fixes booting "system rescue CD version 2.8.0" on this target.
>
> Reported-by: Michael S. Tsirkin<mst@redhat.com>
> Cc: Richard Henderson<rth@twiddle.net>
> Cc: Paolo Bonzini<pbonzini@redhat.com>
> Signed-off-by: Aurelien Jarno<aurelien@aurel32.net>

Nice catch.

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

Patch

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index d70b2eb..94f6043 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2188,9 +2188,9 @@  static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
 
 #if TCG_TARGET_REG_BITS == 32
     if (ofs >= 32) {
-        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
         tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
                             TCGV_LOW(arg2), ofs - 32, len);
+        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
         return;
     }
     if (ofs + len <= 32) {