aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorPetar Jovanovic <petarj@mips.com>2012-12-10 16:28:17 +0100
committerAurelien Jarno <aurelien@aurel32.net>2013-01-01 11:11:38 +0100
commitb8abbbe8df5e04085f4b85fc4f7cf85efbcd492c (patch)
tree597fbe25eec8e83317cf933f93106d938858aeab /target-mips
parenteec8972a5bc744eda695a86a984d746c240dff90 (diff)
target-mips: Fix for helpers for EXTR_* instructions
The change removes some unnecessary and incorrect code for EXTR_S.H. Further, it corrects the mask for shift value in the EXTR_ instructions. It also extends the existing tests so they trigger the issues corrected with the change. Signed-off-by: Petar Jovanovic <petarj@mips.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/dsp_helper.c45
1 files changed, 10 insertions, 35 deletions
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index acf7ceb1d1..ee0c8724c7 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -484,35 +484,6 @@ static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
return (temp >> 1) & 0x00FF;
}
-static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
- int32_t shift,
- CPUMIPSState *env)
-{
- int32_t sign, temp31;
- int64_t temp, acc;
-
- sign = (env->active_tc.HI[ac] >> 31) & 0x01;
- acc = ((int64_t)env->active_tc.HI[ac] << 32) |
- ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
- if (shift == 0) {
- temp = acc;
- } else {
- if (sign == 0) {
- temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
- } else {
- temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) |
- (acc >> shift);
- }
- }
-
- temp31 = (temp >> 31) & 0x01;
- if (sign != temp31) {
- set_DSPControl_overflow_flag(1, 23, env);
- }
-
- return temp;
-}
-
/* 128 bits long. p[0] is LO, p[1] is HI. */
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
int32_t ac,
@@ -3407,7 +3378,7 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
int32_t tempI;
int64_t tempDL[2];
- shift = shift & 0x0F;
+ shift = shift & 0x1F;
mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
@@ -3435,7 +3406,7 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
{
int64_t tempDL[2];
- shift = shift & 0x0F;
+ shift = shift & 0x1F;
mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
@@ -3462,7 +3433,7 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
int32_t tempI, temp64;
int64_t tempDL[2];
- shift = shift & 0x0F;
+ shift = shift & 0x1F;
mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
@@ -3645,11 +3616,15 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
CPUMIPSState *env)
{
- int64_t temp;
+ int64_t temp, acc;
+
+ shift = shift & 0x1F;
+
+ acc = ((int64_t)env->active_tc.HI[ac] << 32) |
+ ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
- shift = shift & 0x0F;
+ temp = acc >> shift;
- temp = mipsdsp_rashift_short_acc(ac, shift, env);
if (temp > (int64_t)0x7FFF) {
temp = 0x00007FFF;
set_DSPControl_overflow_flag(1, 23, env);