All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jia Liu <proljc@gmail.com>
To: qemu-devel@nongnu.org
Cc: aurelien@aurel32.net
Subject: [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions
Date: Tue, 21 Aug 2012 14:53:11 +0800	[thread overview]
Message-ID: <1345531999-17872-6-git-send-email-proljc@gmail.com> (raw)
In-Reply-To: <1345531999-17872-1-git-send-email-proljc@gmail.com>

Add MIPS ASE DSP Arithmetic instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c | 1929 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |  132 ++++
 target-mips/translate.c  |  675 ++++++++++++++++
 3 files changed, 2736 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index a7d6c7e..486b22f 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1275,3 +1275,1932 @@ static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
     return result;
 }
 /*** MIPS DSP internal functions end ***/
+
+#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
+#define MIPSDSP_LLO 0x00000000FFFFFFFFull
+#define MIPSDSP_HI  0xFFFF0000
+#define MIPSDSP_LO  0x0000FFFF
+#define MIPSDSP_Q3  0xFF000000
+#define MIPSDSP_Q2  0x00FF0000
+#define MIPSDSP_Q1  0x0000FF00
+#define MIPSDSP_Q0  0x000000FF
+
+/** DSP Arithmetic Sub-class insns **/
+target_ulong helper_addq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t  rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_add_i16(env, rsh, rth);
+    templ = mipsdsp_add_i16(env, rsl, rtl);
+    rd = ((unsigned int)temph << 16) | ((unsigned int)templ & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addq_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_sat_add_i16(env, rsh, rth);
+    templ = mipsdsp_sat_add_i16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_add_i16(env, rs3, rt3);
+    tempC = mipsdsp_add_i16(env, rs2, rt2);
+    tempB = mipsdsp_add_i16(env, rs1, rt1);
+    tempA = mipsdsp_add_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addq_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_add_i16(env, rs3, rt3);
+    tempC = mipsdsp_sat_add_i16(env, rs2, rt2);
+    tempB = mipsdsp_sat_add_i16(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_addq_s_w(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    rd = mipsdsp_sat_add_i32(env, rs, rt);
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_add_i32(env, rs1, rt1);
+    tempA = mipsdsp_add_i32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addq_s_pw(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat_add_i32(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_i32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_addu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_add_u8(env, rs0, rt0);
+    temp1 = mipsdsp_add_u8(env, rs1, rt1);
+    temp2 = mipsdsp_add_u8(env, rs2, rt2);
+    temp3 = mipsdsp_add_u8(env, rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_s_qb(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t rs0, rs1, rs2, rs3;
+    uint8_t rt0, rt1, rt2, rt3;
+    uint8_t temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_sat_add_u8(env, rs0, rt0);
+    temp1 = mipsdsp_sat_add_u8(env, rs1, rt1);
+    temp2 = mipsdsp_sat_add_u8(env, rs2, rt2);
+    temp3 = mipsdsp_sat_add_u8(env, rs3, rt3);
+
+    rd = (((uint8_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint8_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint8_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint8_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_adduh_qb(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_rshift1_add_u8(rs0, rt0);
+    temp1 = mipsdsp_rshift1_add_u8(rs1, rt1);
+    temp2 = mipsdsp_rshift1_add_u8(rs2, rt2);
+    temp3 = mipsdsp_rshift1_add_u8(rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_adduh_r_qb(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_rrshift1_add_u8(rs0, rt0);
+    temp1 = mipsdsp_rrshift1_add_u8(rs1, rt1);
+    temp2 = mipsdsp_rrshift1_add_u8(rs2, rt2);
+    temp3 = mipsdsp_rrshift1_add_u8(rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    temph = mipsdsp_add_u16(env, rsh, rth);
+    templ = mipsdsp_add_u16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    temph = mipsdsp_sat_add_u16(env, rsh, rth);
+    templ = mipsdsp_sat_add_u16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_ph(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_rshift1_add_q16(rsh, rth);
+    templ = mipsdsp_rshift1_add_q16(rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_r_ph(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_rrshift1_add_q16(rsh, rth);
+    templ = mipsdsp_rrshift1_add_q16(rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rshift1_add_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_r_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rrshift1_add_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_add_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_addu_s_ob(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_sat_add_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_adduh_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rshift1_add_u8(rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_adduh_r_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rrshift1_add_u8(rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_addu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_add_u16(env, rs3, rt3);
+    tempC = mipsdsp_add_u16(env, rs2, rt2);
+    tempB = mipsdsp_add_u16(env, rs1, rt1);
+    tempA = mipsdsp_add_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addu_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_add_u16(env, rs3, rt3);
+    tempC = mipsdsp_sat_add_u16(env, rs2, rt2);
+    tempB = mipsdsp_sat_add_u16(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_subq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sub_i16(env, rsh, rth);
+    tempA = mipsdsp_sub_i16(env, rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subq_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sat16_sub(env, rsh, rth);
+    tempA = mipsdsp_sat16_sub(env, rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sub_i16(env, rs3, rt3);
+    tempC = mipsdsp_sub_i16(env, rs2, rt2);
+    tempB = mipsdsp_sub_i16(env, rs1, rt1);
+    tempA = mipsdsp_sub_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+
+target_ulong helper_subq_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat16_sub(env, rs3, rt3);
+    tempC = mipsdsp_sat16_sub(env, rs2, rt2);
+    tempB = mipsdsp_sat16_sub(env, rs1, rt1);
+    tempA = mipsdsp_sat16_sub(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_subq_s_w(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_sat32_sub(env, rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sub32(env, rs1, rt1);
+    tempA = mipsdsp_sub32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+    return temp;
+}
+
+target_ulong helper_subq_s_pw(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat32_sub(env, rs1, rt1);
+    tempA = mipsdsp_sat32_sub(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_subu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_sub_u8(env, rs3, rt3);
+    tempC = mipsdsp_sub_u8(env, rs2, rt2);
+    tempB = mipsdsp_sub_u8(env, rs1, rt1);
+    tempA = mipsdsp_sub_u8(env, rs0, rt0);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subu_s_qb(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_satu8_sub(env, rs3, rt3);
+    tempC = mipsdsp_satu8_sub(env, rs2, rt2);
+    tempB = mipsdsp_satu8_sub(env, rs1, rt1);
+    tempA = mipsdsp_satu8_sub(env, rs0, rt0);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subuh_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = ((uint16_t)rs3 - (uint16_t)rt3) >> 1;
+    tempC = ((uint16_t)rs2 - (uint16_t)rt2) >> 1;
+    tempB = ((uint16_t)rs1 - (uint16_t)rt1) >> 1;
+    tempA = ((uint16_t)rs0 - (uint16_t)rt0) >> 1;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_subuh_r_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + 1) >> 1;
+    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + 1) >> 1;
+    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + 1) >> 1;
+    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + 1) >> 1;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_subu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sub_u16_u16(env, rth, rsh);
+    tempA = mipsdsp_sub_u16_u16(env, rtl, rsl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subu_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_satu16_sub_u16_u16(env, rth, rsh);
+    tempA = mipsdsp_satu16_sub_u16_u16(env, rtl, rsl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rshift1_sub_q16(rsh, rth);
+    tempA = mipsdsp_rshift1_sub_q16(rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_r_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rrshift1_sub_q16(rsh, rth);
+    tempA = mipsdsp_rrshift1_sub_q16(rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rshift1_sub_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_r_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rrshift1_sub_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_sub_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result += (uint64_t)temp[i] << (i * 8);
+    }
+
+    return result;
+}
+
+target_ulong helper_subu_s_ob(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_satu8_sub(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result += (uint64_t)temp[i] << (i * 8);
+    }
+
+    return result;
+}
+
+target_ulong helper_subuh_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i]) >> 1;
+      }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_subuh_r_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i] + 1) >> 1;
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_subu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sub_u16_u16(env, rs3, rt3);
+    tempC = mipsdsp_sub_u16_u16(env, rs2, rt2);
+    tempB = mipsdsp_sub_u16_u16(env, rs1, rt1);
+    tempA = mipsdsp_sub_u16_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+
+
+target_ulong helper_subu_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_satu16_sub_u16_u16(env, rs3, rt3);
+    tempC = mipsdsp_satu16_sub_u16_u16(env, rs2, rt2);
+    tempB = mipsdsp_satu16_sub_u16_u16(env, rs1, rt1);
+    tempA = mipsdsp_satu16_sub_u16_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_addsc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint64_t temp, tempRs, tempRt;
+    int32_t flag;
+
+    tempRs = (uint64_t)rs & MIPSDSP_LLO;
+    tempRt = (uint64_t)rt & MIPSDSP_LLO;
+
+    temp = tempRs + tempRt;
+    flag = (temp & 0x0100000000ull) >> 32;
+    set_DSPControl_carryflag(env, flag);
+    rd = temp & MIPSDSP_LLO;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addwc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int32_t temp32, temp31;
+    int64_t rsL, rtL, tempL;
+
+    rsL = (int32_t)rs;
+    rtL = (int32_t)rt;
+    tempL = rsL + rtL + get_DSPControl_carryflag(env);
+    temp31 = (tempL >> 31) & 0x01;
+    temp32 = (tempL >> 32) & 0x01;
+
+    if (temp31 != temp32) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    rd = tempL & MIPSDSP_LLO;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_modsub(target_ulong rs, target_ulong rt)
+{
+    int32_t decr;
+    uint16_t lastindex;
+    target_ulong rd;
+
+    decr = rt & MIPSDSP_Q0;
+    lastindex = (rt >> 8) & MIPSDSP_LO;
+
+    if ((rs & MIPSDSP_LLO) == 0x00000000) {
+        rd = (target_ulong)lastindex;
+    } else {
+        rd = rs - decr;
+    }
+
+    return rd;
+}
+
+target_ulong helper_raddu_w_qb(target_ulong rs)
+{
+    uint8_t  rs3, rs2, rs1, rs0;
+    uint16_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_raddu_l_ob(target_ulong rs)
+{
+    int i;
+    uint16_t rs_t[8];
+    uint64_t temp;
+
+    temp = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        temp += (uint64_t)rs_t[i];
+    }
+
+    return temp;
+}
+#endif
+
+target_ulong helper_absq_s_qb(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int8_t tempD, tempC, tempB, tempA;
+
+    tempD = (rt & MIPSDSP_Q3) >> 24;
+    tempC = (rt & MIPSDSP_Q2) >> 16;
+    tempB = (rt & MIPSDSP_Q1) >>  8;
+    tempA =  rt & MIPSDSP_Q0;
+
+    rd = (((uint32_t)mipsdsp_sat_abs_u8 (env, tempD) << 24) & MIPSDSP_Q3) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempC) << 16) & MIPSDSP_Q2) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempB) <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)mipsdsp_sat_abs_u8 (env, tempA) & MIPSDSP_Q0);
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_absq_s_ph(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t tempA, tempB;
+
+    tempA = (rt & MIPSDSP_HI) >> 16;
+    tempB =  rt & MIPSDSP_LO;
+
+    rd = ((uint32_t)mipsdsp_sat_abs_u16 (env, tempA) << 16) |
+         ((uint32_t)(mipsdsp_sat_abs_u16 (env, tempB)) & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_absq_s_w(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int32_t temp;
+
+    temp = rt;
+    rd = mipsdsp_sat_abs_u32(env, temp);
+
+    return (target_ulong)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_absq_s_ob(CPUMIPSState *env, target_ulong rt)
+{
+    uint8_t tempH, tempG, tempF, tempE;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempH = (rt >> 56) & MIPSDSP_Q0;
+    tempG = (rt >> 48) & MIPSDSP_Q0;
+    tempF = (rt >> 40) & MIPSDSP_Q0;
+    tempE = (rt >> 32) & MIPSDSP_Q0;
+    tempD = (rt >> 24) & MIPSDSP_Q0;
+    tempC = (rt >> 16) & MIPSDSP_Q0;
+    tempB = (rt >> 8) & MIPSDSP_Q0;
+    tempA = rt & MIPSDSP_Q0;
+
+    tempH = mipsdsp_sat_abs_u8(env, tempH);
+    tempG = mipsdsp_sat_abs_u8(env, tempG);
+    tempF = mipsdsp_sat_abs_u8(env, tempF);
+    tempE = mipsdsp_sat_abs_u8(env, tempE);
+    tempD = mipsdsp_sat_abs_u8(env, tempD);
+    tempC = mipsdsp_sat_abs_u8(env, tempC);
+    tempB = mipsdsp_sat_abs_u8(env, tempB);
+    tempA = mipsdsp_sat_abs_u8(env, tempA);
+
+    temp = ((uint64_t)tempH << 56) | ((uint64_t)tempG << 48) |
+           ((uint64_t)tempF << 40) | ((uint64_t)tempE << 32) |
+           ((uint64_t)tempD << 24) | ((uint64_t)tempC << 16) |
+           ((uint64_t)tempB << 8) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_absq_s_qh(CPUMIPSState *env, target_ulong rt)
+{
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempD = (rt >> 48) & MIPSDSP_LO;
+    tempC = (rt >> 32) & MIPSDSP_LO;
+    tempB = (rt >> 16) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_abs_u16(env, tempD);
+    tempC = mipsdsp_sat_abs_u16(env, tempC);
+    tempB = mipsdsp_sat_abs_u16(env, tempB);
+    tempA = mipsdsp_sat_abs_u16(env, tempA);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_absq_s_pw(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    tempB = (rt >> 32) & MIPSDSP_LLO;
+    tempA = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat_abs_u32(env, tempB);
+    tempA = mipsdsp_sat_abs_u32(env, tempA);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_precr_qb_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs2, rs0, rt2, rt0;
+    uint32_t rd;
+
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs0 =  rs & MIPSDSP_Q0;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    rd = ((uint32_t)rs2 << 24) | ((uint32_t)rs0 << 16) |
+         ((uint32_t)rt2 <<  8) | (uint32_t)rt0;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precrq_qb_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    tempD = (rs & MIPSDSP_Q3) >> 24;
+    tempC = (rs & MIPSDSP_Q1) >>  8;
+    tempB = (rt & MIPSDSP_Q3) >> 24;
+    tempA = (rt & MIPSDSP_Q1) >>  8;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
+                                   target_ulong rt)
+{
+    uint16_t tempB, tempA;
+
+    if (sa == 0) {
+        tempB = rt & MIPSDSP_LO;
+        tempA = rs & MIPSDSP_LO;
+    } else {
+        tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
+        tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
+    }
+    rt = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rt;
+}
+
+target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
+                                     target_ulong rs, target_ulong rt)
+{
+    uint64_t tempB, tempA;
+
+    if (sa == 0) {
+        tempB = (rt & MIPSDSP_LO) << 1;
+        tempA = (rs & MIPSDSP_LO) << 1;
+    } else {
+        tempB = ((int32_t)rt >> (sa - 1)) + 1;
+        tempA = ((int32_t)rs >> (sa - 1)) + 1;
+    }
+    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rt;
+}
+
+target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    tempB = (rs & MIPSDSP_HI) >> 16;
+    tempA = (rt & MIPSDSP_HI) >> 16;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precrq_rs_ph_w(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    tempB = mipsdsp_trunc16_sat16_round(env, rs);
+    tempA = mipsdsp_trunc16_sat16_round(env, rt);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs6, rs4, rs2, rs0;
+    uint8_t rt6, rt4, rt2, rt0;
+    uint64_t temp;
+
+    rs6 = (rs >> 48) & MIPSDSP_Q0;
+    rs4 = (rs >> 32) & MIPSDSP_Q0;
+    rs2 = (rs >> 16) & MIPSDSP_Q0;
+    rs0 = rs & MIPSDSP_Q0;
+    rt6 = (rt >> 48) & MIPSDSP_Q0;
+    rt4 = (rt >> 32) & MIPSDSP_Q0;
+    rt2 = (rt >> 16) & MIPSDSP_Q0;
+    rt0 = rt & MIPSDSP_Q0;
+
+    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
+           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
+           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
+           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
+
+    return temp;
+}
+
+target_ulong helper_precr_sra_qh_pw(target_ulong rs, target_ulong rt,
+                                    uint32_t sa)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (sa == 0) {
+        tempD = rt2;
+        tempC = rt0;
+        tempB = rs2;
+        tempA = rs0;
+    } else {
+        tempD = (int16_t)rt3 >> sa;
+        tempC = (int16_t)rt1 >> sa;
+        tempB = (int16_t)rs3 >> sa;
+        tempA = (int16_t)rs1 >> sa;
+    }
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+
+target_ulong helper_precr_sra_r_qh_pw(target_ulong rs, target_ulong rt,
+                                      uint32_t sa)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (sa == 0) {
+        tempD = rt2 << 1;
+        tempC = rt0 << 1;
+        tempB = rs2 << 1;
+        tempA = rs0 << 1;
+    } else {
+        tempD = (((int16_t)rt3 >> sa) + 1) >> 1;
+        tempC = (((int16_t)rt1 >> sa) + 1) >> 1;
+        tempB = (((int16_t)rs3 >> sa) + 1) >> 1;
+        tempA = (((int16_t)rs1 >> sa) + 1) >> 1;
+    }
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs6, rs4, rs2, rs0;
+    uint8_t rt6, rt4, rt2, rt0;
+    uint64_t temp;
+
+    rs6 = (rs >> 56) & MIPSDSP_Q0;
+    rs4 = (rs >> 40) & MIPSDSP_Q0;
+    rs2 = (rs >> 24) & MIPSDSP_Q0;
+    rs0 = (rs >> 8) & MIPSDSP_Q0;
+    rt6 = (rt >> 56) & MIPSDSP_Q0;
+    rt4 = (rt >> 40) & MIPSDSP_Q0;
+    rt2 = (rt >> 24) & MIPSDSP_Q0;
+    rt0 = (rt >> 8) & MIPSDSP_Q0;
+
+    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
+           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
+           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
+           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
+
+    return temp;
+}
+
+target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
+{
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempD = (rs >> 48) & MIPSDSP_LO;
+    tempC = (rs >> 16) & MIPSDSP_LO;
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 16) & MIPSDSP_LO;
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_precrq_rs_qh_pw(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    uint32_t rs2, rs0;
+    uint32_t rt2, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs2 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt2 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempD = mipsdsp_trunc16_sat16_round(env, rs2);
+    tempC = mipsdsp_trunc16_sat16_round(env, rs0);
+    tempB = mipsdsp_trunc16_sat16_round(env, rt2);
+    tempA = mipsdsp_trunc16_sat16_round(env, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
+{
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    tempB = (rs >> 32) & MIPSDSP_LLO;
+    tempA = (rt >> 32) & MIPSDSP_LLO;
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_precrqu_s_qb_ph(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint16_t rsh, rsl, rth, rtl;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat8_reduce_precision(env, rsh);
+    tempC = mipsdsp_sat8_reduce_precision(env, rsl);
+    tempB = mipsdsp_sat8_reduce_precision(env, rth);
+    tempA = mipsdsp_sat8_reduce_precision(env, rtl);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precrqu_s_ob_qh(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    temp[7] = mipsdsp_sat8_reduce_precision(env, rs3);
+    temp[6] = mipsdsp_sat8_reduce_precision(env, rs2);
+    temp[5] = mipsdsp_sat8_reduce_precision(env, rs1);
+    temp[4] = mipsdsp_sat8_reduce_precision(env, rs0);
+    temp[3] = mipsdsp_sat8_reduce_precision(env, rt3);
+    temp[2] = mipsdsp_sat8_reduce_precision(env, rt2);
+    temp[1] = mipsdsp_sat8_reduce_precision(env, rt1);
+    temp[0] = mipsdsp_sat8_reduce_precision(env, rt0);
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+#endif
+
+target_ulong helper_preceq_w_phl(target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = rt & MIPSDSP_HI;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceq_w_phr(target_ulong rt)
+{
+    uint16_t rtl;
+    uint32_t rd;
+
+    rtl = rt & MIPSDSP_LO;
+    rd  = rtl << 16;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_preceq_pw_qhl(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 32) & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhr(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 16) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhla(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 16) & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhra(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 32) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_l_pwl(target_ulong rt)
+{
+    uint64_t temp;
+    temp = rt & MIPSDSP_LHI;
+    return temp;
+}
+
+target_ulong helper_preceq_l_pwr(target_ulong rt)
+{
+    uint64_t temp;
+    temp = rt << 32;
+    return temp;
+}
+#endif
+
+target_ulong helper_precequ_ph_qbl(target_ulong rt)
+{
+    uint8_t  rt3, rt2;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+
+    tempB = (uint16_t)rt3 << 7;
+    tempA = (uint16_t)rt2 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbr(target_ulong rt)
+{
+    uint8_t  rt1, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt1 << 7;
+    tempA = (uint16_t)rt0 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbla(target_ulong rt)
+{
+    uint8_t  rt3, rt1;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+
+    tempB = (uint16_t)rt3 << 7;
+    tempA = (uint16_t)rt1 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbra(target_ulong rt)
+{
+    uint8_t  rt2, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt2 << 7;
+    tempA = (uint16_t)rt0 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precequ_qh_obl(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 48) & MIPSDSP_Q0;
+    tempBC = (rt >> 40) & MIPSDSP_Q0;
+    tempAC = (rt >> 32) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obr(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 24) & MIPSDSP_Q0;
+    tempCC = (rt >> 16) & MIPSDSP_Q0;
+    tempBC = (rt >> 8) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obla(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 40) & MIPSDSP_Q0;
+    tempBC = (rt >> 24) & MIPSDSP_Q0;
+    tempAC = (rt >> 8) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obra(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 48) & MIPSDSP_Q0;
+    tempCC = (rt >> 32) & MIPSDSP_Q0;
+    tempBC = (rt >> 16) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+#endif
+
+target_ulong helper_preceu_ph_qbl(target_ulong rt)
+{
+    uint8_t  rt3, rt2;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    tempB = (uint16_t) rt3;
+    tempA = (uint16_t) rt2;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbr(target_ulong rt)
+{
+    uint8_t  rt1, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t) rt1;
+    tempA = (uint16_t) rt0;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbla(target_ulong rt)
+{
+    uint8_t  rt3, rt1;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    tempB = (uint16_t) rt3;
+    tempA = (uint16_t) rt1;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbra(target_ulong rt)
+{
+    uint8_t  rt2, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt2;
+    tempA = (uint16_t)rt0;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_preceu_qh_obl(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 48) & MIPSDSP_Q0;
+    tempBC = (rt >> 40) & MIPSDSP_Q0;
+    tempAC = (rt >> 32) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obr(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 24) & MIPSDSP_Q0;
+    tempCC = (rt >> 16) & MIPSDSP_Q0;
+    tempBC = (rt >> 8) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obla(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 40) & MIPSDSP_Q0;
+    tempBC = (rt >> 24) & MIPSDSP_Q0;
+    tempAC = (rt >> 8) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obra(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 48) & MIPSDSP_Q0;
+    tempCC = (rt >> 32) & MIPSDSP_Q0;
+    tempBC = (rt >> 16) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+#endif
+
+#undef MIPSDSP_LHI
+#undef MIPSDSP_LLO
+#undef MIPSDSP_HI
+#undef MIPSDSP_LO
+#undef MIPSDSP_Q3
+#undef MIPSDSP_Q2
+#undef MIPSDSP_Q1
+#undef MIPSDSP_Q0
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 76fb451..0607105 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -297,4 +297,136 @@ DEF_HELPER_0(rdhwr_ccres, tl)
 DEF_HELPER_1(pmon, void, int)
 DEF_HELPER_0(wait, void)
 
+/*** MIPS DSP ***/
+/* DSP Arithmetic Sub-class insns */
+DEF_HELPER_FLAGS_3(addq_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_pw, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addu_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(addu_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addu_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(addu_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subq_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_pw, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subu_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(subu_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subu_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(subu_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addsc, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addwc, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(modsub, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, env, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, env, tl)
+#endif
+DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
+                   tl, i32, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
+                   tl, i32, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precrq_rs_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
+
+#endif
+DEF_HELPER_FLAGS_1(preceq_w_phl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_w_phr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_l_pwl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_l_pwr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index f154f09..0ea9131 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -316,6 +316,21 @@ enum {
 
     /* MIPS DSP Load */
     OPC_LX_DSP         = 0x0A | OPC_SPECIAL3,
+    /* MIPS DSP Arithmetic */
+    OPC_ADDU_QB_DSP    = 0x10 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_ADDU_OB_DSP    = 0x14 | OPC_SPECIAL3,
+#endif
+    OPC_ABSQ_S_PH_DSP  = 0x12 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_ABSQ_S_QH_DSP  = 0x16 | OPC_SPECIAL3,
+#endif
+    /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E.  */
+    /* OPC_ADDUH_QB_DSP   = 0x18 | OPC_SPECIAL3,  */
+    OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -354,6 +369,144 @@ enum {
 #endif
 };
 
+#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ADDQ_PH        = (0x0A << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDQ_S_PH      = (0x0E << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDQ_S_W       = (0x16 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_QB        = (0x00 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_S_QB      = (0x04 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_PH        = (0x08 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_S_PH      = (0x0C << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_PH        = (0x0B << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_S_PH      = (0x0F << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_S_W       = (0x17 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_QB        = (0x01 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_S_QB      = (0x05 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_PH        = (0x09 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_S_PH      = (0x0D << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDSC          = (0x10 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDWC          = (0x11 << 6) | OPC_ADDU_QB_DSP,
+    OPC_MODSUB         = (0x12 << 6) | OPC_ADDU_QB_DSP,
+    OPC_RADDU_W_QB     = (0x14 << 6) | OPC_ADDU_QB_DSP,
+};
+
+#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
+#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ADDUH_QB   = (0x00 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_PH   = (0x08 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_W    = (0x10 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_R_W  = (0x12 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBUH_QB   = (0x01 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_PH   = (0x09 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_W    = (0x11 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_R_W  = (0x13 << 6) | OPC_ADDUH_QB_DSP,
+};
+
+#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ABSQ_S_QB       = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_ABSQ_S_PH       = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_ABSQ_S_W        = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQ_W_PHL    = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQ_W_PHR    = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBL  = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBR  = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBL   = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBR   = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBLA  = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBRA  = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECR_QB_PH      = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_QB_PH     = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECR_SRA_PH_W   = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_PH_W      = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+#if defined(TARGET_MIPS64)
+#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECEQ_L_PWL    = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_L_PWR    = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHL   = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHR   = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHLA  = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHRA  = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBL  = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBR  = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBL   = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBR   = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBLA  = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBRA  = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_OB       = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_PW       = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_QH       = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
+#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_RADDU_L_OB     = (0x14 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_PW        = (0x13 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_S_PW      = (0x17 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_QH        = (0x0B << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_S_QH      = (0x0F << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_OB        = (0x01 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_S_OB      = (0x05 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_QH        = (0x09 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_S_QH      = (0x0D << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBUH_OB       = (0x19 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBUH_R_OB     = (0x1B << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_PW        = (0x12 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_S_PW      = (0x16 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_QH        = (0x0A << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_S_QH      = (0x0E << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_OB        = (0x00 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_S_OB      = (0x04 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_QH        = (0x08 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_S_QH      = (0x0C << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDUH_OB       = (0x18 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDUH_R_OB     = (0x1A << 6) | OPC_ADDU_OB_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
+#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECR_OB_QH       = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECR_SRA_QH_PW   = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_OB_QH      = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_PW_L       = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_QH_PW      = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_RS_QH_PW   = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQU_S_OB_QH   = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
+};
+#endif
+
 /* Coprocessor 0 (rs field) */
 #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
@@ -12134,6 +12287,72 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
         case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+        /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+         * the same mask and op1. */
+            if (op1 == OPC_MULT_G_2E) {
+                int is_mult_g_2e = 0;
+                op2 = MASK_ADDUH_QB(ctx->opcode);
+                switch (op2) {
+                case  OPC_ADDUH_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_adduh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDUH_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_adduh_r_qb(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_R_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_r_ph(cpu_gpr[rd], cpu_gpr[rs],
+                                          cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_R_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBUH_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subuh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBUH_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subuh_r_qb(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_R_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_r_ph(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_R_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                default:
+                    is_mult_g_2e = 1;
+                    break;
+                }
+                if (is_mult_g_2e == 0) {
+                    break;
+                }
+            }
         case OPC_MOD_G_2E ... OPC_MODU_G_2E:
             check_insn(env, ctx, INSN_LOONGSON2E);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
@@ -12193,6 +12412,213 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_ABSQ_S_PH_DSP:
+            op2 = MASK_ABSQ_S_PH(ctx->opcode);
+            switch (op2) {
+            case OPC_ABSQ_S_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_absq_s_qb(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_ph(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_w(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_W_PHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_w_phl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_W_PHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_w_phr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ABSQ_S.PH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_ADDU_QB_DSP:
+            op2 = MASK_ADDU_QB(ctx->opcode);
+            switch (op2) {
+            case OPC_ADDQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_w(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_s_qb(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_w(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_qb(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subu_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subu_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDSC:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addsc(cpu_gpr[rd], cpu_env,
+                                 cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDWC:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addwc(cpu_gpr[rd], cpu_env,
+                                 cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MODSUB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_modsub(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_RADDU_W_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_raddu_w_qb(cpu_gpr[rd], cpu_gpr[rs]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ADDU.QB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_CMPU_EQ_QB_DSP:
+            op2 = MASK_CMPU_EQ_QB(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECR_QB_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_precr_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_QB_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECR_SRA_PH_W:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_precr_sra_ph_w(cpu_gpr[rt], temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PRECR_SRA_R_PH_W:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_precr_sra_r_ph_w(cpu_gpr[rt], temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PRECRQ_PH_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_ph_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_RS_PH_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_rs_ph_w(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQU_S_QB_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK CMPU.EQ.QB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -12213,6 +12639,255 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
 #endif
+#if defined(TARGET_MIPS64)
+        case OPC_ABSQ_S_QH_DSP:
+            op2 = MASK_ABSQ_S_QH(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECEQ_L_PWL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_l_pwl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_L_PWR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_l_pwr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_absq_s_ob(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_pw(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_qh(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ABSQ_S.QH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
+        case OPC_ADDU_OB_DSP:
+            op2 = MASK_ADDU_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_RADDU_L_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_raddu_l_ob(cpu_gpr[rd], cpu_gpr[rs]);
+                break;
+            case OPC_SUBQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_pw(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_ob(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBUH_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subuh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBUH_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subuh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_pw(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_s_ob(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDUH_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_adduh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDUH_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_adduh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ADDU.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
+        case OPC_CMPU_EQ_OB_DSP:
+            op2 = MASK_CMPU_EQ_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECR_OB_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_precr_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_PRECR_SRA_QH_PW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_precr_sra_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
+                                               cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PRECR_SRA_R_QH_PW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_precr_sra_r_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
+                                                 cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PRECRQ_OB_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
+                                        cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_PW_L:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_pw_l(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_QH_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_qh_pw(cpu_gpr[rd], cpu_gpr[rs],
+                                        cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_RS_QH_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_rs_qh_pw(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQU_S_OB_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrqu_s_ob_qh(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK CMPU.EQ.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.9.5

  parent reply	other threads:[~2012-08-21  6:55 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
2012-08-23 13:31   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
2012-08-23 13:33   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
2012-08-23 14:18   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
2012-08-23 14:23   ` Aurelien Jarno
2012-08-21  6:53 ` Jia Liu [this message]
2012-08-23 14:28   ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
2012-08-23 14:48   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model Jia Liu
2012-08-21  9:32 ` [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases Jia Liu
2012-08-21  9:34 ` [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO Jia Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1345531999-17872-6-git-send-email-proljc@gmail.com \
    --to=proljc@gmail.com \
    --cc=aurelien@aurel32.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.