[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v11 11/14] target-mips: Add ASE DSP accumulator
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH v11 11/14] target-mips: Add ASE DSP accumulator instructions |
Date: |
Wed, 17 Oct 2012 01:23:31 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Tue, Oct 16, 2012 at 12:39:15AM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Accumulator and DSPControl Access instructions.
>
> Signed-off-by: Jia Liu <address@hidden>
> ---
> target-mips/dsp_helper.c | 609
> ++++++++++++++++++++++++++++++++++++++++++++++
> target-mips/helper.h | 35 +++
> target-mips/translate.c | 355 +++++++++++++++++++++++++++
> 3 files changed, 999 insertions(+)
>
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index 06c97a2..e798702 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -3436,6 +3436,615 @@ 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(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + int32_t tempI;
> + int64_t tempDL[2];
> +
> + shift = shift & 0x0F;
> +
> + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + 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(1, 23, env);
> + }
> +
> + return (target_long)tempI;
> +}
> +
> +target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + int64_t tempDL[2];
> +
> + shift = shift & 0x0F;
> +
> + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + 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(1, 23, env);
> + }
> +
> + return (target_long)(int32_t)(tempDL[0] >> 1);
> +}
> +
> +target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + int32_t tempI, temp64;
> + int64_t tempDL[2];
> +
> + shift = shift & 0x0F;
> +
> + mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> + if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> + (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> + 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(1, 23, env);
> + }
> +
> + return (target_long)tempI;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> +
> + shift = shift & 0x3F;
> +
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> + return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> + uint32_t temp128;
> +
> + shift = shift & 0x3F;
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> + 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] != ~0ull)) {
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> + uint32_t temp128;
> +
> + shift = shift & 0x3F;
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> + 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] != ~0ull)) {
> + if (temp128 == 0) {
> + temp[0] = 0x0FFFFFFFF;
> + } else {
> + temp[0] = 0x0100000000;
> + }
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> + target_ulong result;
> +
> + shift = shift & 0x3F;
> +
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> + result = (temp[1] << 63) | (temp[0] >> 1);
> +
> + return result;
> +}
> +
> +target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> + uint32_t temp128;
> + target_ulong result;
> +
> + shift = shift & 0x3F;
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> + 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] != ~0ull)) {
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + result = (temp[1] << 63) | (temp[0] >> 1);
> +
> + return result;
> +}
> +
> +target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + uint64_t temp[3];
> + uint32_t temp128;
> + target_ulong result;
> +
> + shift = shift & 0x3F;
> + mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> + 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] != ~0ull)) {
> + if (temp128 == 0) {
> + temp[1] &= 0xFFFFFFFFFFFFFFFEull;
> + temp[0] |= 0xFFFFFFFFFFFFFFFEull;
> + } else {
> + temp[1] |= 0x01;
> + temp[0] &= 0x01;
> + }
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> + result = (temp[1] << 63) | (temp[0] >> 1);
> +
> + return result;
> +}
> +#endif
> +
> +target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + int64_t temp;
> +
> + shift = shift & 0x0F;
> +
> + temp = mipsdsp_rashift_short_acc(ac, shift, env);
> + if (temp > 0x0000000000007FFFull) {
> + temp = 0x00007FFF;
> + set_DSPControl_overflow_flag(1, 23, env);
> + } else if (temp < 0xFFFFFFFFFFFF8000ull) {
> + temp = 0xFFFF8000;
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + return (target_long)(int32_t)(temp & 0xFFFFFFFF);
> +}
> +
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
> + CPUMIPSState *env)
> +{
> + int64_t temp[2];
> + uint32_t temp127;
> +
> + shift = shift & 0x1F;
> +
> + mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
> +
> + temp127 = (temp[1] >> 63) & 0x01;
> +
> + if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
> + temp[0] &= 0xFFFF0000;
> + temp[0] |= 0x00007FFF;
> + set_DSPControl_overflow_flag(1, 23, env);
> + } else if ((temp127 == 1) &&
> + (temp[1] < 0xFFFFFFFFFFFFFFFFll
> + || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
> + temp[0] &= 0xFFFF0000;
> + temp[0] |= 0x00008000;
> + set_DSPControl_overflow_flag(1, 23, env);
> + }
> +
> + return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
> +}
> +
> +#endif
> +
> +target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState
> *env)
> +{
> + int32_t start_pos;
> + int sub;
> + uint32_t temp;
> + uint64_t acc;
> +
> + size = size & 0x1F;
> +
> + 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(0, env);
> + } else {
> + set_DSPControl_efi(1, env);
> + }
> +
> + return (target_ulong)temp;
> +}
> +
> +target_ulong helper_extpdp(target_ulong ac, target_ulong size,
> + CPUMIPSState *env)
> +{
> + int32_t start_pos;
> + int sub;
> + uint32_t temp;
> + uint64_t acc;
> +
> + size = size & 0x1F;
> + 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(start_pos - (size + 1), env);
> + set_DSPControl_efi(0, env);
> + } else {
> + set_DSPControl_efi(1, env);
> + }
> +
> + return (target_ulong)temp;
> +}
> +
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState
> *env)
> +{
> + 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(0, env);
> + } else {
> + set_DSPControl_efi(1, env);
> + }
> +
> + return temp;
> +}
> +
> +target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
> + CPUMIPSState *env)
> +{
> + 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_pos(sub, env);
> + set_DSPControl_efi(0, env);
> + } else {
> + set_DSPControl_efi(1, env);
> + }
> +
> + return temp;
> +}
> +
> +#endif
> +
> +void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
> +{
> + int8_t rs5_0;
> + uint64_t temp, acc;
> +
> + rs5_0 = rs & 0x3F;
> + rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
> + rs5_0 = MIPSDSP_ABS(rs5_0);
> + 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 (rs5_0 > 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(target_ulong shift, target_ulong ac, CPUMIPSState *env)
> +{
> + int8_t shift_t;
> + uint64_t tempB, tempA;
> +
> + shift_t = (uint8_t)(shift << 1) >> 1;
> + shift_t = MIPSDSP_ABS(shift_t);
> +
> + tempB = env->active_tc.HI[ac];
> + tempA = env->active_tc.LO[ac];
> +
> + if (shift_t != 0) {
> + if (shift_t >= 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(target_ulong ac, target_ulong rs, CPUMIPSState *env)
> +{
> + 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(pos + 32, env);
> + }
> +}
> +
> +#if defined(TARGET_MIPS64)
> +void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
> +{
> + 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(pos, env);
> + }
> +}
> +#endif
> +
> +void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
> +{
> + 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(target_ulong masknum, CPUMIPSState *env)
> +{
> + 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 3d3c596..45af62f 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -676,4 +676,39 @@ 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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
> +
> +
> +
> #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index ea939d7..3442d8c 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,30 @@ 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 +705,32 @@ 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,
> +};
> +
> #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> enum {
> /* DSP Bit/Manipulation Sub-class */
> @@ -14217,6 +14272,240 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext
> *ctx,
> MIPS_DEBUG("%s", opn);
> }
>
> +static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t
> op2,
> + int ret, int v1, int v2, int check_ret)
> +
> +{
> + const char *opn = "mipsdsp accumulator";
> + TCGv t0 = tcg_temp_new();
> + TCGv t1 = tcg_temp_new();
> + TCGv v1_t = tcg_temp_new();
> + TCGv v2_t = tcg_temp_new();
> + int16_t imm;
> +
> + if ((ret == 0) && (check_ret == 1)) {
> + /* Treat as NOP. */
> + MIPS_DEBUG("NOP");
> + return;
> + }
> +
> + if (v1 == 0) {
> + tcg_gen_movi_tl(v1_t, 0);
> + } else {
> + gen_load_gpr(v1_t, v1);
> + }
> +
> + if (v2 == 0) {
> + tcg_gen_movi_tl(v2_t, 0);
> + } else {
> + gen_load_gpr(v2_t, v2);
> + }
> +
Same comments as the previous patches apply here.
> + switch (op1) {
> + case OPC_EXTR_W_DSP:
> + check_dsp(ctx);
> + switch (op2) {
> + case OPC_EXTR_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTR_R_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTR_RS_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTR_S_H:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTRV_S_H:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_EXTRV_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_EXTRV_R_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_EXTRV_RS_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_EXTP:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTPV:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_EXTPDP:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_EXTPDPV:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_SHILO:
> + imm = (ctx->opcode >> 20) & 0x3F;
> + tcg_gen_movi_tl(t0, ret);
> + tcg_gen_movi_tl(t1, imm);
> + gen_helper_shilo(t0, t1, cpu_env);
> + break;
> + case OPC_SHILOV:
> + tcg_gen_movi_tl(t0, ret);
> + gen_helper_shilo(t0, v1_t, cpu_env);
> + break;
> + case OPC_MTHLIP:
> + tcg_gen_movi_tl(t0, ret);
> + gen_helper_mthlip(t0, v1_t, cpu_env);
> + break;
> + case OPC_WRDSP:
> + imm = (ctx->opcode >> 11) & 0x3FF;
> + tcg_gen_movi_tl(t0, imm);
> + gen_helper_wrdsp(v1_t, t0, cpu_env);
> + break;
> + case OPC_RDDSP:
> + imm = (ctx->opcode >> 16) & 0x03FF;
> + tcg_gen_movi_tl(t0, imm);
> + gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
> + break;
> + }
> + break;
> +#ifdef TARGET_MIPS64
> + case OPC_DEXTR_W_DSP:
> + check_dsp(ctx);
> + switch (op2) {
> + case OPC_DMTHLIP:
> + tcg_gen_movi_tl(t0, ret);
> + gen_helper_dmthlip(v1_t, t0, cpu_env);
> + break;
> + case OPC_DSHILO:
> + {
> + int shift = (ctx->opcode >> 19) & 0x7F;
> + int ac = (ctx->opcode >> 11) & 0x03;
> + tcg_gen_movi_tl(t0, shift);
> + tcg_gen_movi_tl(t1, ac);
> + gen_helper_dshilo(t0, t1, cpu_env);
> + break;
> + }
> + case OPC_DSHILOV:
> + {
> + int ac = (ctx->opcode >> 11) & 0x03;
> + tcg_gen_movi_tl(t0, ac);
> + gen_helper_dshilo(v1_t, t0, cpu_env);
> + break;
> + }
> + case OPC_DEXTP:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> +
> + gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTPV:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTPDP:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTPDPV:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTR_L:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_R_L:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_RS_L:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_R_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_RS_W:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTR_S_H:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTRV_S_H:
> + tcg_gen_movi_tl(t0, v2);
> + tcg_gen_movi_tl(t1, v1);
> + gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> + break;
> + case OPC_DEXTRV_L:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTRV_R_L:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTRV_RS_L:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTRV_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTRV_R_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + case OPC_DEXTRV_RS_W:
> + tcg_gen_movi_tl(t0, v2);
> + gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
> + break;
> + }
> + break;
> +#endif
> + }
> +
> + tcg_temp_free(t0);
> + tcg_temp_free(t1);
> + tcg_temp_free(v1_t);
> + tcg_temp_free(v2_t);
> +
> + (void)opn; /* avoid a compiler warning */
> + MIPS_DEBUG("%s", opn);
> +}
> +
> /* End MIPSDSP functions. */
>
> static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -14794,6 +15083,38 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx, int *is_branch)
> op2 = MASK_APPEND(ctx->opcode);
> gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
> break;
> + case OPC_EXTR_W_DSP:
> + op2 = MASK_EXTR_W(ctx->opcode);
> + switch (op2) {
> + case OPC_EXTR_W:
> + case OPC_EXTR_R_W:
> + case OPC_EXTR_RS_W:
> + case OPC_EXTR_S_H:
> + case OPC_EXTRV_S_H:
> + case OPC_EXTRV_W:
> + case OPC_EXTRV_R_W:
> + case OPC_EXTRV_RS_W:
> + case OPC_EXTP:
> + case OPC_EXTPV:
> + case OPC_EXTPDP:
> + case OPC_EXTPDPV:
> + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
> + break;
> + case OPC_RDDSP:
> + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
> + break;
> + case OPC_SHILO:
> + case OPC_SHILOV:
> + case OPC_MTHLIP:
> + case OPC_WRDSP:
> + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
> + 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:
> @@ -14938,6 +15259,40 @@ static void decode_opc (CPUMIPSState *env,
> DisasContext *ctx, int *is_branch)
> op2 = MASK_DAPPEND(ctx->opcode);
> gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
> break;
> + case OPC_DEXTR_W_DSP:
> + op2 = MASK_DEXTR_W(ctx->opcode);
> + switch (op2) {
> + case OPC_DEXTP:
> + case OPC_DEXTPDP:
> + case OPC_DEXTPDPV:
> + case OPC_DEXTPV:
> + case OPC_DEXTR_L:
> + case OPC_DEXTR_R_L:
> + case OPC_DEXTR_RS_L:
> + case OPC_DEXTR_W:
> + case OPC_DEXTR_R_W:
> + case OPC_DEXTR_RS_W:
> + case OPC_DEXTR_S_H:
> + case OPC_DEXTRV_L:
> + case OPC_DEXTRV_R_L:
> + case OPC_DEXTRV_RS_L:
> + case OPC_DEXTRV_S_H:
> + case OPC_DEXTRV_W:
> + case OPC_DEXTRV_R_W:
> + case OPC_DEXTRV_RS_W:
> + gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
> + break;
> + case OPC_DMTHLIP:
> + case OPC_DSHILO:
> + case OPC_DSHILOV:
> + gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
> + break;
> + default: /* Invalid */
> + MIPS_INVAL("MASK EXTR.W");
> + generate_exception(ctx, EXCP_RI);
> + break;
> + }
> + break;
> case OPC_DPAQ_W_QH_DSP:
> op2 = MASK_DPAQ_W_QH(ctx->opcode);
> switch (op2) {
> --
> 1.7.10.2 (Apple Git-33)
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
address@hidden http://www.aurel32.net
- Re: [Qemu-devel] [PATCH v11 05/14] target-mips: Add ASE DSP load instructions, (continued)
- [Qemu-devel] [PATCH v11 07/14] target-mips: Add ASE DSP GPR based shift instructions, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 09/14] target-mips: Add ASE DSP bit/manipulation instructions, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 08/14] target-mips: Add ASE DSP multiply instructions, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 06/14] target-mips: Add ASE DSP arithmetic instructions, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 11/14] target-mips: Add ASE DSP accumulator instructions, Jia Liu, 2012/10/15
- Re: [Qemu-devel] [PATCH v11 11/14] target-mips: Add ASE DSP accumulator instructions,
Aurelien Jarno <=
- [Qemu-devel] [PATCH v11 13/14] target-mips: Add ASE DSP testcases, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 10/14] target-mips: Add ASE DSP compare-pick instructions, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 12/14] target-mips: Add ASE DSP processors, Jia Liu, 2012/10/15
- [Qemu-devel] [PATCH v11 14/14] target-mips: Change TODO file, Jia Liu, 2012/10/15