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