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 09/13] target-mips-ase-dsp: Add compare pick instructions
Date: Tue, 21 Aug 2012 14:53:15 +0800	[thread overview]
Message-ID: <1345531999-17872-10-git-send-email-proljc@gmail.com> (raw)
In-Reply-To: <1345531999-17872-1-git-send-email-proljc@gmail.com>

Add MIPS ASE DSP Compare-Pick instructions.

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

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 4564d9c..f41808e 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -6290,6 +6290,923 @@ target_ulong helper_dinsv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
 }
 #endif
 
+/** DSP Compare-Pick Sub-class insns **/
+void helper_cmpu_eq_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    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;
+
+    cc3 = (rs3 == rt3);
+    cc2 = (rs2 == rt2);
+    cc1 = (rs1 == rt1);
+    cc0 = (rs0 == rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+void helper_cmpu_lt_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    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;
+
+    cc3 = (rs3 < rt3);
+    cc2 = (rs2 < rt2);
+    cc1 = (rs1 < rt1);
+    cc0 = (rs0 < rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+void helper_cmpu_le_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    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;
+
+    cc3 = (rs3 <= rt3);
+    cc2 = (rs2 <= rt2);
+    cc1 = (rs1 <= rt1);
+    cc0 = (rs0 <= rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+
+target_ulong helper_cmpgu_eq_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    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;
+
+    cc3 = (rs3 == rt3);
+    cc2 = (rs2 == rt2);
+    cc1 = (rs1 == rt1);
+    cc0 = (rs0 == rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_cmpgu_lt_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    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;
+
+    cc3 = (rs3 < rt3);
+    cc2 = (rs2 < rt2);
+    cc1 = (rs1 < rt1);
+    cc0 = (rs0 < rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_cmpgu_le_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    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;
+
+    cc3 = (rs3 <= rt3);
+    cc2 = (rs2 <= rt2);
+    cc1 = (rs1 <= rt1);
+    cc0 = (rs0 <= rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+void helper_cmp_eq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh == rth);
+    ccA = (rsl == rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+void helper_cmp_lt_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh < rth);
+    ccA = (rsl < rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+void helper_cmp_le_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh <= rth);
+    ccA = (rsl <= rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_cmpu_eq_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+void helper_cmpu_lt_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+void helper_cmpu_le_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+target_ulong helper_cmpgdu_eq_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgdu_lt_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgdu_le_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_eq_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_lt_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_le_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+void helper_cmp_eq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 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;
+
+    if (rs3 == rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 == rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 == rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 == rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_lt_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 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;
+
+    if (rs3 < rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 < rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 < rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 < rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_le_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 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;
+
+    if (rs3 <= rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 <= rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 <= rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 <= rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_eq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 == rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 == rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+
+void helper_cmp_lt_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 < rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 < rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+
+void helper_cmp_le_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 <= rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 <= rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+#endif
+
+target_ulong helper_pick_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tp3, tp2, tp1, tp0;
+
+    uint32_t dsp27, dsp26, dsp25, dsp24, rd;
+    target_ulong dsp;
+
+    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;
+
+    dsp = env->active_tc.DSPControl;
+    dsp27 = (dsp >> 27) & 0x01;
+    dsp26 = (dsp >> 26) & 0x01;
+    dsp25 = (dsp >> 25) & 0x01;
+    dsp24 = (dsp >> 24) & 0x01;
+
+    tp3 = dsp27 == 1 ? rs3 : rt3;
+    tp2 = dsp26 == 1 ? rs2 : rt2;
+    tp1 = dsp25 == 1 ? rs1 : rt1;
+    tp0 = dsp24 == 1 ? rs0 : rt0;
+
+    rd = ((uint32_t)tp3 << 24) |
+         ((uint32_t)tp2 << 16) |
+         ((uint32_t)tp1 <<  8) |
+         (uint32_t)tp0;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_pick_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t dsp25, dsp24;
+    uint32_t rd;
+    target_ulong dsp;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    dsp = env->active_tc.DSPControl;
+    dsp25 = (dsp >> 25) & 0x01;
+    dsp24 = (dsp >> 24) & 0x01;
+
+    tempB = (dsp25 == 1) ? rsh : rth;
+    tempA = (dsp24 == 1) ? rsl : rtl;
+    rd = (((uint32_t)tempB << 16) & MIPSDSP_HI) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_pick_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint32_t cond;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    cond = get_DSPControl_24(env, 8);
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        temp[i] = (cond % 2) == 1 ? rs_t[i] : rt_t[i];
+        cond = cond / 2;
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_pick_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t cond;
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    cond = get_DSPControl_24(env, 4);
+
+    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;
+
+    tempA = ((cond % 2) == 1) ? rs0 : rt0;
+    cond = cond / 2;
+    tempB = ((cond % 2) == 1) ? rs1 : rt1;
+    cond = cond / 2;
+    tempC = ((cond % 2) == 1) ? rs2 : rt2;
+    cond = cond / 2;
+    tempD = ((cond % 2) == 1) ? rs3 : rt3;
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_pick_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t cond;
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    cond = get_DSPControl_24(env, 2);
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempA = ((cond % 2) == 1) ? rs0 : rt0;
+    cond = cond / 2;
+    tempB = ((cond % 2) == 1) ? rs1 : rt1;
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+#endif
+
+target_ulong helper_append(target_ulong rt, target_ulong rs, uint32_t sa)
+{
+    int len;
+    uint32_t temp;
+
+    len = sa & 0x1F;
+
+    if (len == 0) {
+        temp = rt;
+    } else {
+        temp = (rt << len) | (rs & (((uint32_t)0x01 << len) - 1));
+    }
+    rt = temp;
+
+    return (target_long)(int32_t)temp;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dappend(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t filter;
+    uint64_t temp;
+
+    filter = 0;
+    temp = 0;
+
+    if (sa == 0) {
+        temp = rt;
+    } else {
+        filter = (0x01 << sa) - 1;
+        temp = rt << sa;
+        temp |= rs & filter;
+    }
+
+    return temp;
+}
+
+#endif
+
+target_ulong helper_prepend(uint32_t sa, target_ulong rs, target_ulong rt)
+{
+    uint32_t temp;
+
+    if (sa == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (32 - sa)) | rt >> sa;
+    }
+
+    rt = temp;
+
+    return (target_long)(int32_t)rt;
+}
+
+#if defined(TARGET_MIPS64)
+/*
+ * The instruction describtion really confused me.
+ *
+ * Description:
+ * The shift argument is provided by the instruction argument,
+ * sa, interpreted as an unsigned five-bit integer and biased
+ * by 32, allowing shift amounts between 32 and 63.
+ *
+ * Operation:
+ * shift5..0 ← 1 || sa4..0
+ * if ( shift = 0 ) then
+ *
+ * Why put 1 at sa5, and test shift is equal zero or not?
+ *
+ */
+target_ulong helper_prependd(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t shift;
+    uint64_t temp;
+
+    shift = sa & 0x10;
+
+    if (shift == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (64 - shift)) | (rt >> shift);
+    }
+
+    return temp;
+}
+
+target_ulong helper_prependw(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t shift;
+    uint64_t temp;
+
+    shift = sa;
+
+    if (shift == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (64 - shift)) | (rt >> shift);
+    }
+
+    return temp;
+}
+#endif
+
+target_ulong helper_balign(uint32_t bp, target_ulong rt, target_ulong rs)
+{
+    uint32_t temp;
+    bp = bp & 0x03;
+
+    if (bp == 0 || bp == 2) {
+        return rt;
+    } else {
+        temp = (rt << (8 * bp)) | (rs >> (8 * (4 - bp)));
+    }
+    rt = temp;
+
+    return (target_long)(int32_t)rt;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dbalign(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint8_t bp;
+    uint64_t temp;
+
+    bp = sa & 0x07;
+
+    if ((bp == 0) || (bp == 2) || (bp == 4)) {
+        temp = rt;
+    } else {
+        temp = (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));
+    }
+
+    return temp;
+}
+
+#endif
+
+target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsl, rth;
+    uint32_t rd;
+
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rd = (rsl << 16) | rth;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
+{
+    uint32_t rs0, rt1;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+
+    tempB = rs0;
+    tempA = rt1;
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index df86ef9..273501c 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -589,4 +589,56 @@ DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
 DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl);
 #endif
 
+/* DSP Compare-Pick Sub-class insns */
+DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(pick_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(pick_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(append, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dappend, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(prepend, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(prependd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_3(prependw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(balign, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 1a9df0f..b493582 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -348,6 +348,11 @@ enum {
 #if defined(TARGET_MIPS64)
     OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
 #endif
+    /* MIPS DSP Compare-Pick Sub-class */
+    OPC_APPEND_DSP     = 0x31 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -473,6 +478,22 @@ enum {
     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,
+    /* DSP Compare-Pick Sub-class */
+    OPC_CMPU_EQ_QB       = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPU_LT_QB       = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPU_LE_QB       = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_EQ_QB      = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_LT_QB      = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_LE_QB      = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_EQ_QB     = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_LT_QB     = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_LE_QB     = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_EQ_PH        = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_LT_PH        = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_LE_PH        = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PICK_QB          = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PICK_PH          = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PACKRL_PH        = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
 };
 
 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -535,6 +556,14 @@ enum {
     OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
 };
 
+#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Compare-Pick Sub-class */
+    OPC_APPEND  = (0x00 << 6) | OPC_APPEND_DSP,
+    OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
+    OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -603,6 +632,26 @@ enum {
 #if defined(TARGET_MIPS64)
 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
+    /* DSP Compare-Pick Sub-class */
+    OPC_CMP_EQ_PW         = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LT_PW         = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LE_PW         = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_EQ_QH         = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LT_QH         = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LE_QH         = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_EQ_OB      = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_LT_OB      = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_LE_OB      = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_EQ_OB       = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_LT_OB       = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_LE_OB       = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_EQ_OB        = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_LT_OB        = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_LE_OB        = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PACKRL_PW         = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_OB           = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_PW           = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_QH           = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
     /* 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,
@@ -616,6 +665,17 @@ enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* DSP Compare-Pick Sub-class */
+    OPC_DAPPEND  = (0x00 << 6) | OPC_DAPPEND_DSP,
+    OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
+    OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
+    OPC_DBALIGN  = (0x10 << 6) | OPC_DAPPEND_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* DSP Bit/Manipulation Sub-class */
@@ -12951,6 +13011,101 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_env,
                                            cpu_gpr[rs], cpu_gpr[rt]);
                 break;
+            case OPC_CMPU_EQ_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_eq_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LT_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_lt_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LE_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_le_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_EQ_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_eq_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LT_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_lt_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LE_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_le_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_EQ_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_eq_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMPGDU_LT_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_lt_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMPGDU_LE_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_le_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMP_EQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PACKRL_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_packrl_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK CMPU.EQ.QB");
                 generate_exception(ctx, EXCP_RI);
@@ -13291,6 +13446,42 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_APPEND_DSP:
+            op2 = MASK_APPEND(ctx->opcode);
+            switch (op2) {
+            case OPC_APPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_append(cpu_gpr[rt], cpu_gpr[rt],
+                                      cpu_gpr[rs], temp_rd);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PREPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_prepend(cpu_gpr[rt], temp_rd,
+                                       cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_BALIGN:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_balign(cpu_gpr[rt], temp_rd,
+                                      cpu_gpr[rt], cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK APPEND");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -13643,6 +13834,91 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_CMPU_EQ_OB_DSP:
             op2 = MASK_CMPU_EQ_OB(ctx->opcode);
             switch (op2) {
+            case OPC_CMP_EQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_EQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_EQ_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_eq_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_LT_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_lt_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_LE_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_le_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_EQ_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_eq_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LT_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_lt_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LE_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_le_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_EQ_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_eq_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LT_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_lt_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LE_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_le_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PACKRL_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_packrl_pw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             case OPC_PRECR_OB_QH:
                 check_insn(env, ctx, ASE_DSPR2);
                 gen_helper_precr_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
@@ -13699,6 +13975,53 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DAPPEND_DSP:
+            op2 = MASK_DAPPEND(ctx->opcode);
+            switch (op2) {
+            case OPC_DAPPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_dappend(cpu_gpr[rt], cpu_gpr[rs],
+                                       cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PREPENDD:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_prependd(cpu_gpr[rt], cpu_gpr[rs],
+                                        cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PREPENDW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_prependw(cpu_gpr[rt], cpu_gpr[rs],
+                                        cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_DBALIGN:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                  TCGv_i32 sa_v = tcg_const_i32(rd);
+                  gen_helper_dbalign(cpu_gpr[rt], cpu_gpr[rs],
+                                     cpu_gpr[rt], sa_v);
+                  tcg_temp_free_i32(sa_v);
+                  break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK DAPPEND");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_DPAQ_W_QH_DSP:
             {
                 int ac = rd & 0x03;
-- 
1.7.9.5

  parent reply	other threads:[~2012-08-21  6:58 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 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
2012-08-23 14:28   ` 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 ` Jia Liu [this message]
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-10-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.