]> git.proxmox.com Git - qemu.git/commitdiff
target-mips: fix calculation of overflow for SHLL.PH and SHLL.QB
authorPetar Jovanovic <petar.jovanovic@imgtec.com>
Sun, 28 Apr 2013 01:18:36 +0000 (03:18 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Fri, 3 May 2013 09:50:49 +0000 (11:50 +0200)
This change corrects and simplifies how discard is calculated for shift
left logical vector instructions. It is used to detect overflow and set bit
22 in the DSPControl register.

The existing tests (shll_ph.c, shll_qb.c) are extended with the corner cases
that expose incorrectness in the previous implementation.

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/shll_ph.c
tests/tcg/mips/mips32-dsp/shll_qb.c

index f975da08c4717afa53ff2ebd8d9b7d2d0f028d01..805247d2529c0645dee58e648f9303c92ca26c77 100644 (file)
@@ -682,49 +682,31 @@ static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
 
 static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
 {
-    uint8_t sign;
     uint8_t discard;
 
-    if (s == 0) {
-        return a;
-    } else {
-        sign = (a >> 7) & 0x01;
-        if (sign != 0) {
-            discard = (((0x01 << (8 - s)) - 1) << s) |
-                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
-        } else {
-            discard = a >> (6 - (s - 1));
-        }
+    if (s != 0) {
+        discard = a >> (8 - s);
 
         if (discard != 0x00) {
             set_DSPControl_overflow_flag(1, 22, env);
         }
-        return a << s;
     }
+    return a << s;
 }
 
 static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
                                         CPUMIPSState *env)
 {
-    uint8_t  sign;
     uint16_t discard;
 
-    if (s == 0) {
-        return a;
-    } else {
-        sign = (a >> 15) & 0x01;
-        if (sign != 0) {
-            discard = (((0x01 << (16 - s)) - 1) << s) |
-                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
-        } else {
-            discard = a >> (14 - (s - 1));
-        }
+    if (s != 0) {
+        discard = (int16_t)a >> (15 - s);
 
         if ((discard != 0x0000) && (discard != 0xFFFF)) {
             set_DSPControl_overflow_flag(1, 22, env);
         }
-        return a << s;
     }
+    return a << s;
 }
 
 
index b8f1ff528503cff624c80a8e56b9e9dae109c46d..5fa58ccf63744bae1dd25da618980bae21b99e09 100644 (file)
@@ -11,7 +11,38 @@ int main()
     resultdsp = 1;
 
     __asm
-        ("shll.ph %0, %2, 0x0B\n\t"
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rt        = 0x7fff8000;
+    result    = 0xfffe0000;
+    resultdsp = 1;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x01\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rt        = 0x00000001;
+    result    = 0x00008000;
+    resultdsp = 1;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x0F\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
index 8c1b91c635d22e36885974333d3670d4fca94211..729716d626184caece39598ce67365766c46d1d9 100644 (file)
@@ -11,12 +11,14 @@ int main()
     resultdsp = 0x00;
 
     __asm
-        ("shll.qb %0, %2, 0x00\n\t"
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x00\n\t"
          "rddsp   %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
         );
     dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
     assert(rd == result);
 
     rt     = 0x87654321;
@@ -24,12 +26,29 @@ int main()
     resultdsp = 0x01;
 
     __asm
-        ("shll.qb %0, %2, 0x03\n\t"
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x03\n\t"
          "rddsp   %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
         );
     dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd == result);
+
+    rt     = 0x00000001;
+    result = 0x00000080;
+    resultdsp = 0x00;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x07\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
     assert(rd == result);
 
     return 0;