aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetar Jovanovic <petar.jovanovic@imgtec.com>2013-03-15 18:56:19 +0100
committerMichael Roth <mdroth@linux.vnet.ibm.com>2013-04-04 16:58:41 -0500
commitd019dd928c68038c539fa0a5ba92f046fed12a6c (patch)
tree3cad6e3b184a3ee257bb594a2d48178f1b9aef44
parentdac077f0e6f02791d4206aa05e034b6ebbce0ba7 (diff)
target-mips: fix rndrashift_short_acc and code for EXTR_ instructions
Fix for rndrashift_short_acc to set correct value to higher 64 bits. This change also corrects conditions when bit 23 of the DSPControl register is set. The existing test files have been extended with several examples that trigger the issues. One bug/example in the test file for EXTR_RS_W has been found and reported by Klaus Peichl. Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> (cherry picked from commit 8b758d0568a986d58c254b3c209691c82e0f82a1) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--target-mips/dsp_helper.c23
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_r_w.c23
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_rs_w.c46
-rw-r--r--tests/tcg/mips/mips32-dsp/extr_w.c23
4 files changed, 101 insertions, 14 deletions
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index ffa9396c4b..550f4a1e8e 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -517,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
acc = ((int64_t)env->active_tc.HI[ac] << 32) |
((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
- if (shift == 0) {
- p[0] = acc << 1;
- p[1] = (acc >> 63) & 0x01;
- } else {
- p[0] = acc >> (shift - 1);
- p[1] = 0;
- }
+ p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
+ p[1] = (acc >> 63) & 0x01;
}
/* 128 bits long. p[0] is LO, p[1] is HI */
@@ -3161,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
- (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3187,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3214,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
}
tempI = tempDL[0] >> 1;
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
- temp64 = tempDL[1];
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ temp64 = tempDL[1] & 0x01;
if (temp64 == 0) {
tempI = 0x7FFFFFFF;
} else {
diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c
index 02e022427a..489c1931b4 100644
--- a/tests/tcg/mips/mips32-dsp/extr_r_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -67,5 +67,28 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}
diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
index c3a22ee704..f9d2ed646f 100644
--- a/tests/tcg/mips/mips32-dsp/extr_rs_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -67,5 +67,51 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x80000000;
+ acl = 0x00000000;
+ result = 0x80000000;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}
diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c
index bd6b0b95c2..cf926146d5 100644
--- a/tests/tcg/mips/mips32-dsp/extr_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -67,5 +67,28 @@ int main()
assert(dsp == 0);
assert(result == rt);
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0xFFFFFFFF;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
return 0;
}