On Thu, Sep 27, 2012 at 09:24:48PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Accumulator and DSPControl Access instructions.
> 
> Signed-off-by: Jia Liu <pro...@gmail.com>
> ---
>  target-mips/dsp_helper.c |  609 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |   35 +++
>  target-mips/translate.c  |  340 ++++++++++++++++++++++++++
>  3 files changed, 984 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index dabece4..6ff063b 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -3476,6 +3476,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 7102074..fc034b8 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 */
> @@ -14201,6 +14256,225 @@ 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();
> +    int16_t imm;
> +
> +    if ((ret == 0) && (check_ret == 1)) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    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, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], 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, cpu_gpr[v1], 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, cpu_gpr[v1], 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, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_MTHLIP:
> +            tcg_gen_movi_tl(t0, ret);
> +            gen_helper_mthlip(t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_WRDSP:
> +            imm = (ctx->opcode >> 11) & 0x3FF;
> +            tcg_gen_movi_tl(t0, imm);
> +            gen_helper_wrdsp(cpu_gpr[v1], 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(cpu_gpr[v1], 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(cpu_gpr[v1], 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, cpu_gpr[v1], 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, cpu_gpr[v1], 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, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_R_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_r_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_RS_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_rs_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        }

In all the functions above, v0 and v1 can be the zero register.

> +        break;
> +#endif
> +    }
> +
> +
> +    tcg_temp_free(t0);
> +    tcg_temp_free(t1);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -14778,6 +15052,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:
> @@ -14922,6 +15228,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
aurel...@aurel32.net                 http://www.aurel32.net

Reply via email to