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