aboutsummaryrefslogtreecommitdiff
path: root/target-mips/dsp_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips/dsp_helper.c')
-rw-r--r--target-mips/dsp_helper.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 919ff299f6..fcdc1bbcb9 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -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