[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v7 11/14] target-mips-ase-dsp: Add DSP accumulator i
From: |
Jia Liu |
Subject: |
[Qemu-devel] [PATCH v7 11/14] target-mips-ase-dsp: Add DSP accumulator instructions |
Date: |
Tue, 28 Aug 2012 14:36:22 +0800 |
Add MIPS ASE DSP Accumulator and DSPControl Access instructions.
Signed-off-by: Jia Liu <address@hidden>
---
target-mips/dsp_helper.c | 1044 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 52 +++
target-mips/translate.c | 425 +++++++++++++++++++
3 files changed, 1521 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 94eab09..386e2aa 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 */
@@ -13500,6 +13555,162 @@ static void decode_opc (CPUMIPSState *env,
DisasContext *ctx, int *is_branch)
break;
}
break;
+ case OPC_EXTR_W_DSP:
+ check_dsp(ctx);
+ op2 = MASK_EXTR_W(ctx->opcode);
+ switch (op2) {
+ case OPC_EXTR_W:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
@@ -14037,6 +14248,220 @@ static void decode_opc (CPUMIPSState *env,
DisasContext *ctx, int *is_branch)
break;
#endif
#if defined(TARGET_MIPS64)
+ case OPC_DEXTR_W_DSP:
+ check_dsp(ctx);
+ op2 = MASK_DEXTR_W(ctx->opcode);
+ switch (op2) {
+ case OPC_DMTHLIP:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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
- [Qemu-devel] [PATCH v7 00/14] QEMU MIPS ASE DSP sup port, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 01/14] target-mips-ase-dsp : Add internal functions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 02/14] target-mips-ase-dsp: Add dsp resources access check, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 04/14] target-mips-ase-dsp: Add branch instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 05/14] target-mips-ase-dsp: Add load instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 06/14] target-mips-ase-dsp: Add arithmetic instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 09/14] target-mips-ase-dsp: Add bit/manipulation instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 08/14] target-mips-ase-dsp: Add multiply instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 10/14] target-mips-ase-dsp : Add compare-pick instructions, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 11/14] target-mips-ase-dsp: Add DSP accumulator instructions,
Jia Liu <=
- [Qemu-devel] [PATCH v7 12/14] target-mips-ase-dsp: Add MIPS DSP processors, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 14/14] target-mips-ase-dsp: Change TODO file, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 13/14] target-mips-ase-dsp: Add testcases, Jia Liu, 2012/08/28
- [Qemu-devel] [PATCH v7 07/14] target-mips-ase-dsp: Add GPR-based shift instructions, Jia Liu, 2012/08/28