Commit 26690560 authored by Jia Liu's avatar Jia Liu Committed by Aurelien Jarno
Browse files

target-mips: Add ASE DSP compare-pick instructions



Add MIPS ASE DSP Compare-Pick instructions.

Signed-off-by: default avatarJia Liu <proljc@gmail.com>
Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
parent 1cb6686c
Loading
Loading
Loading
Loading
+233 −0
Original line number Diff line number Diff line
@@ -3167,6 +3167,239 @@ BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
#undef BIT_INSV


/** DSP Compare-Pick Sub-class insns **/
#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
target_ulong helper_##name(target_ulong rs, target_ulong rt) \
{                                                       \
    uint32_t rs_t, rt_t;                                \
    uint8_t cc;                                         \
    uint32_t temp = 0;                                  \
    int i;                                              \
                                                        \
    for (i = 0; i < split_num; i++) {                   \
        rs_t = (rs >> (bit_size * i)) & filter;         \
        rt_t = (rt >> (bit_size * i)) & filter;         \
        cc = mipsdsp_##func(rs_t, rt_t);                \
        temp |= cc << i;                                \
    }                                                   \
                                                        \
    return (target_ulong)temp;                          \
}

CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);

#ifdef TARGET_MIPS64
CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
#endif

#undef CMP_HAS_RET


#define CMP_NO_RET(name, func, split_num, filter, bit_size) \
void helper_##name(target_ulong rs, target_ulong rt,        \
                            CPUMIPSState *env)              \
{                                                           \
    int##bit_size##_t rs_t, rt_t;                           \
    int##bit_size##_t flag = 0;                             \
    int##bit_size##_t cc;                                   \
    int i;                                                  \
                                                            \
    for (i = 0; i < split_num; i++) {                       \
        rs_t = (rs >> (bit_size * i)) & filter;             \
        rt_t = (rt >> (bit_size * i)) & filter;             \
                                                            \
        cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t);  \
        flag |= cc << i;                                    \
    }                                                       \
                                                            \
    set_DSPControl_24(flag, split_num, env);                \
}

CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);

CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);

#ifdef TARGET_MIPS64
CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);

CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);

CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
#endif
#undef CMP_NO_RET

#if defined(TARGET_MIPS64)

#define CMPGDU_OB(name) \
target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
                                       CPUMIPSState *env)  \
{                                                     \
    int i;                                            \
    uint8_t rs_t, rt_t;                               \
    uint32_t cond;                                    \
                                                      \
    cond = 0;                                         \
                                                      \
    for (i = 0; i < 8; i++) {                         \
        rs_t = (rs >> (8 * i)) & MIPSDSP_Q0;          \
        rt_t = (rt >> (8 * i)) & MIPSDSP_Q0;          \
                                                      \
        if (mipsdsp_cmpu_##name(rs_t, rt_t)) {        \
            cond |= 0x01 << i;                        \
        }                                             \
    }                                                 \
                                                      \
    set_DSPControl_24(cond, 8, env);                  \
                                                      \
    return (uint64_t)cond;                            \
}

CMPGDU_OB(eq)
CMPGDU_OB(lt)
CMPGDU_OB(le)
#undef CMPGDU_OB
#endif

#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
                            CPUMIPSState *env)                 \
{                                                              \
    uint32_t rs_t, rt_t;                                       \
    uint32_t cc;                                               \
    target_ulong dsp;                                          \
    int i;                                                     \
    target_ulong result = 0;                                   \
                                                               \
    dsp = env->active_tc.DSPControl;                           \
    for (i = 0; i < split_num; i++) {                          \
        rs_t = (rs >> (bit_size * i)) & filter;                \
        rt_t = (rt >> (bit_size * i)) & filter;                \
        cc = (dsp >> (24 + i)) & 0x01;                         \
        cc = cc == 1 ? rs_t : rt_t;                            \
                                                               \
        result |= (target_ulong)cc << (bit_size * i);          \
    }                                                          \
                                                               \
    if (ret32bit) {                                            \
        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
    }                                                          \
                                                               \
    return result;                                             \
}

PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);

#ifdef TARGET_MIPS64
PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
#endif
#undef PICK_INSN

#define APPEND_INSN(name, ret_32) \
target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
{                                                                         \
    target_ulong temp;                                                    \
                                                                          \
    if (ret_32) {                                                         \
        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
    } else {                                                              \
        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
    }                                                                     \
                                                                          \
    return temp;                                                          \
}

APPEND_INSN(append, 1);
#ifdef TARGET_MIPS64
APPEND_INSN(dappend, 0);
#endif
#undef APPEND_INSN

#define PREPEND_INSN(name, or_val, ret_32)                    \
target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
                           uint32_t sa)                       \
{                                                             \
    sa |= or_val;                                             \
                                                              \
    if (1) {                                                  \
        return (target_long)(int32_t)(uint32_t)               \
            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
             ((rt & MIPSDSP_LLO) >> sa));                     \
    } else {                                                  \
        return (rs << (64 - sa)) | (rt >> sa);                \
    }                                                         \
}

PREPEND_INSN(prepend, 0, 1);
#ifdef TARGET_MIPS64
PREPEND_INSN(prependw, 0, 0);
PREPEND_INSN(prependd, 0x20, 0);
#endif
#undef PREPEND_INSN

#define BALIGN_INSN(name, filter, ret32) \
target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
{                                                                         \
    bp = bp & 0x03;                                                       \
                                                                          \
    if ((bp & 1) == 0) {                                                  \
        return rt;                                                        \
    } else {                                                              \
        if (ret32) {                                                      \
            return (target_long)(int32_t)((rt << (8 * bp)) |              \
                                          (rs >> (8 * (4 - bp))));        \
        } else {                                                          \
            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
        }                                                                 \
    }                                                                     \
}

BALIGN_INSN(balign, 0x03, 1);
#if defined(TARGET_MIPS64)
BALIGN_INSN(dbalign, 0x07, 0);
#endif
#undef BALIGN_INSN

target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
{
    uint32_t rsl, rth;

    rsl =  rs & MIPSDSP_LO;
    rth = (rt & MIPSDSP_HI) >> 16;

    return (target_long)(int32_t)((rsl << 16) | rth);
}

#if defined(TARGET_MIPS64)
target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
{
    uint32_t rs0, rt1;

    rs0 = rs & MIPSDSP_LLO;
    rt1 = (rt >> 32) & MIPSDSP_LLO;

    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
}
#endif

#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
#undef MIPSDSP_HI
+52 −0
Original line number Diff line number Diff line
@@ -624,4 +624,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, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env)
#endif
DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
#endif
DEF_HELPER_FLAGS_3(append, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_3(dappend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#endif
DEF_HELPER_FLAGS_3(prepend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_3(prependd, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
DEF_HELPER_FLAGS_3(prependw, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#endif
DEF_HELPER_FLAGS_3(balign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
#endif
DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
#if defined(TARGET_MIPS64)
DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
#endif

#include "def-helper.h"
+350 −0

File changed.

Preview size limit exceeded, changes collapsed.