Patchwork [v6,10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions

login
register
mail settings
Submitter Jia Liu
Date Aug. 21, 2012, 6:53 a.m.
Message ID <1345531999-17872-11-git-send-email-proljc@gmail.com>
Download mbox | patch
Permalink /patch/178985/
State New
Headers show

Comments

Jia Liu - Aug. 21, 2012, 6:53 a.m.
Add MIPS ASE DSP Accumulator and DSPControl Access instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c | 1044 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   52 +++
 target-mips/translate.c  |  461 ++++++++++++++++++++
 3 files changed, 1557 insertions(+)

Patch

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index f41808e..332e7c2 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -7207,6 +7207,1050 @@  target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
 }
 #endif
 
+/** DSP Accumulator and DSPControl Access Sub-class insns **/
+target_ulong helper_extr_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
+        (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extr_r_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempI = tempDL[0] >> 1;
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extr_rs_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI, temp64;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    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 (temp64 == 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_r_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_rs_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[0] = 0x0FFFFFFFF;
+        } else {
+            temp[0] = 0x0100000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_r_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_rs_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
+            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
+        } else {
+            temp[1] |= 0x01;
+            temp[0] &= 0x01;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extr_s_h(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int64_t temp;
+    uint32_t tempI;
+
+    temp = mipsdsp_rashift_short_acc(env, ac, shift);
+    if (temp > 0x0000000000007FFFull) {
+        temp = 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if (temp < 0xFFFFFFFFFFFF8000ull) {
+        temp = 0xFFFF8000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = temp & 0xFFFFFFFF;
+    return (target_long)(int32_t)tempI;
+}
+
+target_ulong helper_extrv_s_h(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    uint32_t rd;
+    int32_t shift, tempI;
+    int64_t tempL;
+
+    shift = rs & 0x0F;
+    tempL = mipsdsp_rashift_short_acc(env, ac, shift);
+    if (tempL > 0x000000000007FFFull) {
+        tempI = 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if (tempL < 0xFFFFFFFFFFF8000ull) {
+        tempI = 0xFFFF8000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    rd = tempI;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_s_h(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int64_t temp[2];
+    uint32_t temp127;
+    uint64_t result;
+
+    mipsdsp_rashift_acc(env, (uint64_t *)temp, ac, shift);
+
+    temp127 = (temp[1] >> 63) & 0x01;
+
+    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if ((temp127 == 1) &&
+            (temp[1] < 0xFFFFFFFFFFFFFFFFll
+             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00008000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
+
+    return result;
+}
+
+target_ulong helper_dextrv_s_h(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    int64_t temp[2];
+    uint32_t temp127;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+    mipsdsp_rashift_acc(env, (uint64_t *)temp, ac, shift);
+
+    temp127 = (temp[1] >> 63) & 0x01;
+
+    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if ((temp127 == 1) &&
+            (temp[1] < 0xFFFFFFFFFFFFFFFFull
+             || temp[0] < 0xFFFFFFFFFFFF1000ull)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00008000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extrv_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = tempDL[0] >> 1;
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extrv_r_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempI = tempDL[0] >> 1;
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extrv_rs_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    tempI = tempDL[0] >> 1;
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        if (tempDL[1] == 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextrv_w(CPUMIPSState *env, uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_r_w(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_rs_w(CPUMIPSState *env,
+                                uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[0] |= 0x0FFFFFFFF;
+        } else {
+            temp[0] = 0x0100000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_l(CPUMIPSState *env, uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_r_l(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_rs_l(CPUMIPSState *env,
+                                uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
+            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
+        } else {
+            temp[1] |= 0x01;
+            temp[0] &= 0x01;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    sub = start_pos - (size + 1);
+    if (sub >= -1) {
+        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpv(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t start_pos, size;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = rs & 0x1F;
+
+    if (start_pos - (size + 1) >= -1) {
+        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpdp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    sub = start_pos - (size + 1);
+    if (sub >= -1) {
+        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+
+        set_DSPControl_pos(env, start_pos - (size + 1));
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpdpv(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t start_pos, size;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = rs & 0x1F;
+
+    if (start_pos - (size + 1) >= -1) {
+        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) & (((int)0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, start_pos - (size + 1));
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+
+    size = size & 0x3F;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpv(CPUMIPSState *env, uint32_t ac, target_ulong size)
+{
+    uint8_t start_pos;
+    uint8_t len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+
+    size = size & 0x3F;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpdp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, sub);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpdpv(CPUMIPSState *env, uint32_t ac, target_ulong size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = size & 0x3F;
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, sub);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+#endif
+
+void helper_shilo(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint8_t  sign;
+    uint64_t temp, acc;
+
+    shift = (int32_t)((int32_t)shift << 26) >> 26;
+    sign  = (shift >>  5) & 0x01;
+    shift = (sign == 0) ? shift : -shift;
+    acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+
+    if (shift == 0) {
+        temp = acc;
+    } else {
+        if (sign == 0) {
+            temp = acc >> shift;
+        } else {
+            temp = acc << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+void helper_shilov(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    uint8_t sign;
+    int8_t  rs5_0;
+    uint64_t temp, acc;
+
+    rs5_0 = rs & 0x3F;
+    rs    = (int8_t)(rs5_0 << 2) >> 2;
+    sign  = (rs5_0 >> 5) & 0x01;
+    rs5_0 = (sign == 0) ? rs : -rs;
+    acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
+            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    if (rs5_0 == 0) {
+        temp = acc;
+    } else {
+        if (sign == 0) {
+            temp = acc >> rs5_0;
+        } else {
+            temp = acc << rs5_0;
+        }
+    }
+
+    env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dshilo(CPUMIPSState *env, uint32_t shift, uint32_t ac)
+{
+    uint8_t shift6;
+    int8_t shift_t;
+    uint64_t tempB, tempA;
+
+    shift6 = (shift >> 6) & 0x01;
+    shift_t = (shift6 << 7) | (uint8_t)shift;
+    shift_t = shift6 == 0 ? shift_t : -shift_t;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    if (shift_t != 0) {
+        if (shift6 == 0) {
+            tempA = (tempB << (64 - shift)) | (tempA >> shift);
+            tempB = tempB >> shift;
+        } else {
+            tempB = (tempB << shift) | (tempA >> (64 - shift));
+            tempA = tempA << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = tempB;
+    env->active_tc.LO[ac] = tempA;
+}
+
+void helper_dshilov(CPUMIPSState *env, target_ulong shift, uint32_t ac)
+{
+    uint8_t shift6;
+    int8_t shift_t;
+    uint64_t tempB, tempA;
+
+    shift6 = (shift >> 6) & 0x01;
+    shift_t = (shift6 << 7) | ((uint8_t)shift & 0x7F);
+    shift_t = shift6 == 0 ? shift_t : -shift_t;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    if (shift_t != 0) {
+        if (shift6 == 0) {
+            tempA = (tempB << (64 - shift)) | (tempA >> shift);
+            tempB = tempB >> shift;
+        } else {
+            tempB = (tempB << shift) | (tempA >> (64 - shift));
+            tempA = tempA << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = tempB;
+    env->active_tc.LO[ac] = tempA;
+}
+#endif
+void helper_mthlip(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t tempA, tempB, pos;
+
+    tempA = rs;
+    tempB = env->active_tc.LO[ac];
+    env->active_tc.HI[ac] = (target_long)tempB;
+    env->active_tc.LO[ac] = (target_long)tempA;
+    pos = get_DSPControl_pos(env);
+
+    if (pos > 32) {
+        return;
+    } else {
+        set_DSPControl_pos(env, pos + 32);
+    }
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dmthlip(CPUMIPSState *env, target_ulong rs, uint32_t ac)
+{
+    uint8_t ac_t;
+    uint8_t pos;
+    uint64_t tempB, tempA;
+
+    ac_t = ac & 0x3;
+
+    tempA = rs;
+    tempB = env->active_tc.LO[ac_t];
+
+    env->active_tc.HI[ac_t] = tempB;
+    env->active_tc.LO[ac_t] = tempA;
+
+    pos = get_DSPControl_pos(env);
+
+    if (pos <= 64) {
+        pos = pos + 64;
+        set_DSPControl_pos(env, pos);
+    }
+}
+#endif
+
+void helper_wrdsp(CPUMIPSState *env, target_ulong rs, uint32_t mask_num)
+{
+    uint8_t  mask[6];
+    uint8_t  i;
+    uint32_t newbits, overwrite;
+    target_ulong dsp;
+
+    newbits   = 0x00;
+    overwrite = 0xFFFFFFFF;
+    dsp = env->active_tc.DSPControl;
+
+    for (i = 0; i < 6; i++) {
+        mask[i] = (mask_num >> i) & 0x01;
+    }
+
+    if (mask[0] == 1) {
+#if defined(TARGET_MIPS64)
+        overwrite &= 0xFFFFFF80;
+        newbits   &= 0xFFFFFF80;
+        newbits   |= 0x0000007F & rs;
+#else
+        overwrite &= 0xFFFFFFC0;
+        newbits   &= 0xFFFFFFC0;
+        newbits   |= 0x0000003F & rs;
+#endif
+    }
+
+    if (mask[1] == 1) {
+        overwrite &= 0xFFFFE07F;
+        newbits   &= 0xFFFFE07F;
+        newbits   |= 0x00001F80 & rs;
+    }
+
+    if (mask[2] == 1) {
+        overwrite &= 0xFFFFDFFF;
+        newbits   &= 0xFFFFDFFF;
+        newbits   |= 0x00002000 & rs;
+    }
+
+    if (mask[3] == 1) {
+        overwrite &= 0xFF00FFFF;
+        newbits   &= 0xFF00FFFF;
+        newbits   |= 0x00FF0000 & rs;
+    }
+
+    if (mask[4] == 1) {
+        overwrite &= 0x00FFFFFF;
+        newbits   &= 0x00FFFFFF;
+        newbits   |= 0xFF000000 & rs;
+    }
+
+    if (mask[5] == 1) {
+        overwrite &= 0xFFFFBFFF;
+        newbits   &= 0xFFFFBFFF;
+        newbits   |= 0x00004000 & rs;
+    }
+
+    dsp = dsp & overwrite;
+    dsp = dsp | newbits;
+    env->active_tc.DSPControl = dsp;
+}
+
+target_ulong helper_rddsp(CPUMIPSState *env, uint32_t masknum)
+{
+    uint8_t  mask[6];
+    uint32_t ruler, i;
+    target_ulong temp;
+    target_ulong dsp;
+
+    ruler = 0x01;
+    for (i = 0; i < 6; i++) {
+        mask[i] = (masknum & ruler) >> i ;
+        ruler = ruler << 1;
+    }
+
+    temp  = 0x00;
+    dsp = env->active_tc.DSPControl;
+
+    if (mask[0] == 1) {
+#if defined(TARGET_MIPS64)
+        temp |= dsp & 0x7F;
+#else
+        temp |= dsp & 0x3F;
+#endif
+    }
+
+    if (mask[1] == 1) {
+        temp |= dsp & 0x1F80;
+    }
+
+    if (mask[2] == 1) {
+        temp |= dsp & 0x2000;
+    }
+
+    if (mask[3] == 1) {
+        temp |= dsp & 0x00FF0000;
+    }
+
+    if (mask[4] == 1) {
+        temp |= dsp & 0xFF000000;
+    }
+
+    if (mask[5] == 1) {
+        temp |= dsp & 0x4000;
+    }
+
+    return temp;
+}
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 273501c..754fad5 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -641,4 +641,56 @@  DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 #endif
 
+/* DSP Accumulator and DSPControl Access Sub-class insns */
+DEF_HELPER_FLAGS_3(extr_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, env, i32, i32)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_l, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, env, i32, i32)
+#endif
+DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extrv_s_h, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextrv_s_h, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(extrv_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extrv_r_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extrv_rs_w, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextrv_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_r_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_rs_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_l, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_r_l, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_rs_l, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(extp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extpv, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extpdp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extpdpv, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextpv, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextpdp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextpdpv, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(shilo, 0, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(shilov, 0, void, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dshilo, 0, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(dshilov, 0, void, env, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(mthlip, 0, void, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dmthlip, 0, void, env, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(wrdsp, 0, void, env, tl, i32)
+DEF_HELPER_FLAGS_2(rddsp, 0, tl, env, i32)
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index b493582..577944e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -353,6 +353,11 @@  enum {
 #if defined(TARGET_MIPS64)
     OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
 #endif
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_EXTR_W_DSP     = 0x38 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DEXTR_W_DSP    = 0x3C | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -564,6 +569,28 @@  enum {
     OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
 };
 
+#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_EXTR_W     = (0x00 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_R_W   = (0x04 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_RS_W  = (0x06 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_S_H   = (0x0E << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_S_H  = (0x0F << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_W    = (0x01 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_R_W  = (0x05 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTP       = (0x02 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPV      = (0x03 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPDP     = (0x0A << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPDPV    = (0x0B << 6) | OPC_EXTR_W_DSP,
+    OPC_SHILO      = (0x1A << 6) | OPC_EXTR_W_DSP,
+    OPC_SHILOV     = (0x1B << 6) | OPC_EXTR_W_DSP,
+    OPC_MTHLIP     = (0x1F << 6) | OPC_EXTR_W_DSP,
+    OPC_WRDSP      = (0x13 << 6) | OPC_EXTR_W_DSP,
+    OPC_RDDSP      = (0x12 << 6) | OPC_EXTR_W_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -676,6 +703,34 @@  enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_DMTHLIP     = (0x1F << 6) | OPC_DEXTR_W_DSP,
+    OPC_DSHILO      = (0x1A << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTP       = (0x02 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPDP     = (0x0A << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPDPV    = (0x0B << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPV      = (0x03 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_L     = (0x10 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_R_L   = (0x14 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_RS_L  = (0x16 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_W     = (0x00 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_R_W   = (0x04 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_RS_W  = (0x06 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_S_H   = (0x0E << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_L    = (0x11 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_R_L  = (0x15 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_S_H  = (0x0F << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_W    = (0x01 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_R_W  = (0x05 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DSHILOV     = (0x1B << 6) | OPC_DEXTR_W_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* DSP Bit/Manipulation Sub-class */
@@ -13482,6 +13537,178 @@  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_EXTR_W_DSP:
+            op2 = MASK_EXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_EXTR_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_w(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_r_w(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_rs_w(cpu_gpr[rt], cpu_env,
+                                         temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_s_h(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTRV_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_s_h(cpu_gpr[rt], cpu_env,
+                                         temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_w(cpu_gpr[rt], cpu_env,
+                                       temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_r_w(cpu_gpr[rt], cpu_env,
+                                         temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_rs_w(cpu_gpr[rt], cpu_env,
+                                          temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extp(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extpv(cpu_gpr[rt], cpu_env,
+                                     temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTPDP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extpdp(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTPDPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extpdpv(cpu_gpr[rt], cpu_env,
+                                       temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_SHILO:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    imm = (ctx->opcode >> 20) & 0x3F;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_shilo(cpu_env, temp_rd, temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_SHILOV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_shilov(cpu_env, temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MTHLIP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_mthlip(cpu_env, temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_WRDSP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    imm = (ctx->opcode >> 11) & 0x3FF;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_wrdsp(cpu_env, cpu_gpr[rs], temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    break;
+                }
+            case OPC_RDDSP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    imm = (ctx->opcode >> 16) & 0x03FF;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_rddsp(cpu_gpr[rd], cpu_env, temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK EXTR.W");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -14022,6 +14249,240 @@  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DEXTR_W_DSP:
+            op2 = MASK_DEXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_DMTHLIP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 ac_v = tcg_const_i32(rd);
+                    gen_helper_dmthlip(cpu_env, cpu_gpr[rs], ac_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DSHILO:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int shift = (ctx->opcode >> 19) & 0x7F;
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 shift_v = tcg_const_i32(shift);
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+
+                    gen_helper_dshilo(cpu_env, shift_v, ac_v);
+
+                    tcg_temp_free_i32(shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DSHILOV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dshilov(cpu_env, cpu_gpr[rs], ac_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 size_v = tcg_const_i32(rs);
+                    gen_helper_dextp(cpu_gpr[rt], cpu_env, ac_v, size_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(size_v);
+                    break;
+                }
+            case OPC_DEXTPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dextpv(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTPDP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 size_v = tcg_const_i32(rs);
+                    gen_helper_dextpdp(cpu_gpr[rt], cpu_env, ac_v, size_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(size_v);
+                    break;
+                }
+            case OPC_DEXTPDPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dextpdpv(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTR_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_l(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_R_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_r_l(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_RS_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_rs_l(cpu_gpr[rt], cpu_env,
+                                          ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_r_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_rs_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_s_h(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTRV_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextrv_s_h(cpu_gpr[rt], cpu_env,
+                                          ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTRV_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_l(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_R_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_r_l(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_RS_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_rs_l(cpu_gpr[rt], cpu_env,
+                                         ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_w(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_r_w(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_rs_w(cpu_gpr[rt], cpu_env,
+                                         ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK EXTR.W");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_DPAQ_W_QH_DSP:
             {
                 int ac = rd & 0x03;