]> git.proxmox.com Git - qemu.git/commitdiff
target-mips: fix incorrect behaviour for INSV
authorPetar Jovanovic <petar.jovanovic@imgtec.com>
Wed, 8 May 2013 11:17:40 +0000 (13:17 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Wed, 8 May 2013 16:46:38 +0000 (18:46 +0200)
Corner case for INSV instruction when size=32 has not been correctly
implemented. The mask for size should be one bit wider, and preparing the
filter variable should be aware of this case too.

The test for INSV has been extended to include the case that triggers the
bug.

Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
target-mips/dsp_helper.c
tests/tcg/mips/mips32-dsp/insv.c

index 805247d2529c0645dee58e648f9303c92ca26c77..9212789b4e27fd2af6e8f99c3886f11b3667885b 100644 (file)
@@ -2921,7 +2921,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
         return rt;                                              \
     }                                                           \
                                                                 \
-    filter = ((int32_t)0x01 << size) - 1;                       \
+    filter = ((int64_t)0x01 << size) - 1;                       \
     filter = filter << pos;                                     \
     temprs = (rs << pos) & filter;                              \
     temprt = rt & ~filter;                                      \
@@ -2930,7 +2930,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
     return (target_long)(ret_type)temp;                         \
 }
 
-BIT_INSV(insv, 0x1F, 0x1F, int32_t);
+BIT_INSV(insv, 0x1F, 0x3F, int32_t);
 #ifdef TARGET_MIPS64
 BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
 #endif
index 243b00733d4f6886674c92c78ba87102c0643859..9d674697ccaa9f5001b39ed511ef1f1c5cad1c5b 100644 (file)
@@ -19,5 +19,18 @@ int main()
         );
     assert(rt == result);
 
+    dsp    = 0x1000;
+    rt     = 0xF0F0F0F0;
+    rs     = 0xA5A5A5A5;
+    result = 0xA5A5A5A5;
+
+    __asm
+        ("wrdsp %2\n\t"
+         "insv  %0, %1\n\t"
+         : "+r"(rt)
+         : "r"(rs), "r"(dsp)
+        );
+    assert(rt == result);
+
     return 0;
 }