mirror of https://github.com/xqemu/xqemu.git
target-mips: Add ASE DSP multiply instructions
Add MIPS ASE DSP Multiply instructions. Signed-off-by: Jia Liu <proljc@gmail.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
77c5fa8b55
commit
a22260ae38
|
@ -2189,6 +2189,929 @@ SHIFT_PH(shra_r, rnd16_rashift);
|
|||
|
||||
#undef SHIFT_PH
|
||||
|
||||
/** DSP Multiply Sub-class insns **/
|
||||
/* Return value made up by two 16bits value.
|
||||
* FIXME give the macro a better name.
|
||||
*/
|
||||
#define MUL_RETURN32_16_PH(name, func, \
|
||||
rsmov1, rsmov2, rsfilter, \
|
||||
rtmov1, rtmov2, rtfilter) \
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint16_t rsB, rsA, rtB, rtA; \
|
||||
\
|
||||
rsB = (rs >> rsmov1) & rsfilter; \
|
||||
rsA = (rs >> rsmov2) & rsfilter; \
|
||||
rtB = (rt >> rtmov1) & rtfilter; \
|
||||
rtA = (rt >> rtmov2) & rtfilter; \
|
||||
\
|
||||
rsB = mipsdsp_##func(rsB, rtB, env); \
|
||||
rsA = mipsdsp_##func(rsA, rtA, env); \
|
||||
\
|
||||
return MIPSDSP_RETURN32_16(rsB, rsA); \
|
||||
}
|
||||
|
||||
MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
|
||||
24, 16, MIPSDSP_Q0, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
|
||||
8, 0, MIPSDSP_Q0, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
|
||||
16, 0, MIPSDSP_LO, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
|
||||
16, 0, MIPSDSP_LO, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
|
||||
16, 0, MIPSDSP_LO, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
|
||||
16, 0, MIPSDSP_LO, \
|
||||
16, 0, MIPSDSP_LO);
|
||||
|
||||
#undef MUL_RETURN32_16_PH
|
||||
|
||||
#define MUL_RETURN32_32_ph(name, func, movbits) \
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsh, rth; \
|
||||
int32_t temp; \
|
||||
\
|
||||
rsh = (rs >> movbits) & MIPSDSP_LO; \
|
||||
rth = (rt >> movbits) & MIPSDSP_LO; \
|
||||
temp = mipsdsp_##func(rsh, rth, env); \
|
||||
\
|
||||
return (target_long)(int32_t)temp; \
|
||||
}
|
||||
|
||||
MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
|
||||
MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
|
||||
|
||||
#undef MUL_RETURN32_32_ph
|
||||
|
||||
#define MUL_VOID_PH(name, use_ac_env) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsh, rsl, rth, rtl; \
|
||||
int32_t tempB, tempA; \
|
||||
int64_t acc, dotp; \
|
||||
\
|
||||
MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
|
||||
MIPSDSP_SPLIT32_16(rt, rth, rtl); \
|
||||
\
|
||||
if (use_ac_env == 1) { \
|
||||
tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \
|
||||
} else { \
|
||||
tempB = mipsdsp_mul_u16_u16(rsh, rth); \
|
||||
tempA = mipsdsp_mul_u16_u16(rsl, rtl); \
|
||||
} \
|
||||
\
|
||||
dotp = (int64_t)tempB - (int64_t)tempA; \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
dotp = dotp + acc; \
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((dotp & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
MUL_VOID_PH(mulsaq_s_w_ph, 1);
|
||||
MUL_VOID_PH(mulsa_w_ph, 0);
|
||||
|
||||
#undef MUL_VOID_PH
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define MUL_RETURN64_16_QH(name, func, \
|
||||
rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
|
||||
rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint16_t rs3, rs2, rs1, rs0; \
|
||||
uint16_t rt3, rt2, rt1, rt0; \
|
||||
uint16_t tempD, tempC, tempB, tempA; \
|
||||
\
|
||||
rs3 = (rs >> rsmov1) & rsfilter; \
|
||||
rs2 = (rs >> rsmov2) & rsfilter; \
|
||||
rs1 = (rs >> rsmov3) & rsfilter; \
|
||||
rs0 = (rs >> rsmov4) & rsfilter; \
|
||||
rt3 = (rt >> rtmov1) & rtfilter; \
|
||||
rt2 = (rt >> rtmov2) & rtfilter; \
|
||||
rt1 = (rt >> rtmov3) & rtfilter; \
|
||||
rt0 = (rt >> rtmov4) & rtfilter; \
|
||||
\
|
||||
tempD = mipsdsp_##func(rs3, rt3, env); \
|
||||
tempC = mipsdsp_##func(rs2, rt2, env); \
|
||||
tempB = mipsdsp_##func(rs1, rt1, env); \
|
||||
tempA = mipsdsp_##func(rs0, rt0, env); \
|
||||
\
|
||||
return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
|
||||
}
|
||||
|
||||
MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
|
||||
56, 48, 40, 32, MIPSDSP_Q0, \
|
||||
48, 32, 16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
|
||||
24, 16, 8, 0, MIPSDSP_Q0, \
|
||||
48, 32, 16, 0, MIPSDSP_LO);
|
||||
MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
|
||||
48, 32, 16, 0, MIPSDSP_LO, \
|
||||
48, 32, 16, 0, MIPSDSP_LO);
|
||||
|
||||
#undef MUL_RETURN64_16_QH
|
||||
|
||||
#define MUL_RETURN64_32_QH(name, \
|
||||
rsmov1, rsmov2, \
|
||||
rtmov1, rtmov2) \
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint16_t rsB, rsA; \
|
||||
uint16_t rtB, rtA; \
|
||||
uint32_t tempB, tempA; \
|
||||
\
|
||||
rsB = (rs >> rsmov1) & MIPSDSP_LO; \
|
||||
rsA = (rs >> rsmov2) & MIPSDSP_LO; \
|
||||
rtB = (rt >> rtmov1) & MIPSDSP_LO; \
|
||||
rtA = (rt >> rtmov2) & MIPSDSP_LO; \
|
||||
\
|
||||
tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \
|
||||
tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \
|
||||
\
|
||||
return ((uint64_t)tempB << 32) | (uint64_t)tempA; \
|
||||
}
|
||||
|
||||
MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
|
||||
MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
|
||||
|
||||
#undef MUL_RETURN64_32_QH
|
||||
|
||||
void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
|
||||
CPUMIPSState *env)
|
||||
{
|
||||
int16_t rs3, rs2, rs1, rs0;
|
||||
int16_t rt3, rt2, rt1, rt0;
|
||||
int32_t tempD, tempC, tempB, tempA;
|
||||
int64_t acc[2];
|
||||
int64_t temp[2];
|
||||
int64_t temp_sum;
|
||||
|
||||
MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
|
||||
MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
|
||||
|
||||
tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
|
||||
tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
|
||||
tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
|
||||
|
||||
temp[0] = ((int32_t)tempD - (int32_t)tempC) +
|
||||
((int32_t)tempB - (int32_t)tempA);
|
||||
temp[0] = (int64_t)(temp[0] << 30) >> 30;
|
||||
if (((temp[0] >> 33) & 0x01) == 0) {
|
||||
temp[1] = 0x00;
|
||||
} else {
|
||||
temp[1] = ~0ull;
|
||||
}
|
||||
|
||||
acc[0] = env->active_tc.LO[ac];
|
||||
acc[1] = env->active_tc.HI[ac];
|
||||
|
||||
temp_sum = acc[0] + temp[0];
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) {
|
||||
acc[1] += 1;
|
||||
}
|
||||
acc[0] = temp_sum;
|
||||
acc[1] += temp[1];
|
||||
|
||||
env->active_tc.HI[ac] = acc[1];
|
||||
env->active_tc.LO[ac] = acc[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint8_t rs3, rs2; \
|
||||
uint8_t rt3, rt2; \
|
||||
uint16_t tempB, tempA; \
|
||||
uint64_t tempC, dotp; \
|
||||
\
|
||||
rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \
|
||||
rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \
|
||||
rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \
|
||||
rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \
|
||||
tempB = mipsdsp_##func(rs3, rt3); \
|
||||
tempA = mipsdsp_##func(rs2, rt2); \
|
||||
dotp = (int64_t)tempB + (int64_t)tempA; \
|
||||
if (is_add) { \
|
||||
tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
|
||||
+ dotp; \
|
||||
} else { \
|
||||
tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
|
||||
- dotp; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((tempC & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
|
||||
DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
|
||||
DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
|
||||
DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
|
||||
|
||||
#undef DP_QB
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define DP_OB(name, add_sub, \
|
||||
rsmov1, rsmov2, rsmov3, rsmov4, \
|
||||
rtmov1, rtmov2, rtmov3, rtmov4) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint8_t rsD, rsC, rsB, rsA; \
|
||||
uint8_t rtD, rtC, rtB, rtA; \
|
||||
uint16_t tempD, tempC, tempB, tempA; \
|
||||
uint64_t temp[2]; \
|
||||
uint64_t acc[2]; \
|
||||
uint64_t temp_sum; \
|
||||
\
|
||||
temp[0] = 0; \
|
||||
temp[1] = 0; \
|
||||
\
|
||||
rsD = (rs >> rsmov1) & MIPSDSP_Q0; \
|
||||
rsC = (rs >> rsmov2) & MIPSDSP_Q0; \
|
||||
rsB = (rs >> rsmov3) & MIPSDSP_Q0; \
|
||||
rsA = (rs >> rsmov4) & MIPSDSP_Q0; \
|
||||
rtD = (rt >> rtmov1) & MIPSDSP_Q0; \
|
||||
rtC = (rt >> rtmov2) & MIPSDSP_Q0; \
|
||||
rtB = (rt >> rtmov3) & MIPSDSP_Q0; \
|
||||
rtA = (rt >> rtmov4) & MIPSDSP_Q0; \
|
||||
\
|
||||
tempD = mipsdsp_mul_u8_u8(rsD, rtD); \
|
||||
tempC = mipsdsp_mul_u8_u8(rsC, rtC); \
|
||||
tempB = mipsdsp_mul_u8_u8(rsB, rtB); \
|
||||
tempA = mipsdsp_mul_u8_u8(rsA, rtA); \
|
||||
\
|
||||
temp[0] = (uint64_t)tempD + (uint64_t)tempC + \
|
||||
(uint64_t)tempB + (uint64_t)tempA; \
|
||||
\
|
||||
acc[0] = env->active_tc.LO[ac]; \
|
||||
acc[1] = env->active_tc.HI[ac]; \
|
||||
\
|
||||
if (add_sub) { \
|
||||
temp_sum = acc[0] + temp[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) { \
|
||||
acc[1] += 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] + temp[1]; \
|
||||
} else { \
|
||||
temp_sum = acc[0] - temp[0]; \
|
||||
if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
|
||||
acc[1] -= 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] - temp[1]; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = temp[1]; \
|
||||
env->active_tc.LO[ac] = temp[0]; \
|
||||
}
|
||||
|
||||
DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
|
||||
DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
|
||||
DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
|
||||
DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
|
||||
|
||||
#undef DP_OB
|
||||
#endif
|
||||
|
||||
#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint16_t rsB, rsA, rtB, rtA; \
|
||||
int32_t tempA, tempB; \
|
||||
int64_t acc; \
|
||||
\
|
||||
rsB = (rs >> rsmov1) & MIPSDSP_LO; \
|
||||
rsA = (rs >> rsmov2) & MIPSDSP_LO; \
|
||||
rtB = (rt >> rtmov1) & MIPSDSP_LO; \
|
||||
rtA = (rt >> rtmov2) & MIPSDSP_LO; \
|
||||
\
|
||||
tempB = (int32_t)rsB * (int32_t)rtB; \
|
||||
tempA = (int32_t)rsA * (int32_t)rtA; \
|
||||
\
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
\
|
||||
if (is_add) { \
|
||||
acc = acc + ((int64_t)tempB + (int64_t)tempA); \
|
||||
} else { \
|
||||
acc = acc - ((int64_t)tempB + (int64_t)tempA); \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
|
||||
DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
|
||||
DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
|
||||
DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
|
||||
#undef DP_NOFUNC_PH
|
||||
|
||||
#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsB, rsA, rtB, rtA; \
|
||||
int32_t tempB, tempA; \
|
||||
int64_t acc, dotp; \
|
||||
\
|
||||
rsB = (rs >> rsmov1) & MIPSDSP_LO; \
|
||||
rsA = (rs >> rsmov2) & MIPSDSP_LO; \
|
||||
rtB = (rt >> rtmov1) & MIPSDSP_LO; \
|
||||
rtA = (rt >> rtmov2) & MIPSDSP_LO; \
|
||||
\
|
||||
tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \
|
||||
\
|
||||
dotp = (int64_t)tempB + (int64_t)tempA; \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
\
|
||||
if (is_add) { \
|
||||
acc = acc + dotp; \
|
||||
} else { \
|
||||
acc = acc - dotp; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((acc & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t) \
|
||||
(acc & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
|
||||
DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
|
||||
DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
|
||||
DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
|
||||
|
||||
#undef DP_HASFUNC_PH
|
||||
|
||||
#define DP_128OPERATION_PH(name, is_add) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsh, rsl, rth, rtl; \
|
||||
int32_t tempB, tempA, tempC62_31, tempC63; \
|
||||
int64_t acc, dotp, tempC; \
|
||||
\
|
||||
MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
|
||||
MIPSDSP_SPLIT32_16(rt, rth, rtl); \
|
||||
\
|
||||
tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \
|
||||
\
|
||||
dotp = (int64_t)tempB + (int64_t)tempA; \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
if (is_add) { \
|
||||
tempC = acc + dotp; \
|
||||
} else { \
|
||||
tempC = acc - dotp; \
|
||||
} \
|
||||
tempC63 = (tempC >> 63) & 0x01; \
|
||||
tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \
|
||||
\
|
||||
if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \
|
||||
tempC = 0x7FFFFFFF; \
|
||||
set_DSPControl_overflow_flag(1, 16 + ac, env); \
|
||||
} \
|
||||
\
|
||||
if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \
|
||||
tempC = (int64_t)(int32_t)0x80000000; \
|
||||
set_DSPControl_overflow_flag(1, 16 + ac, env); \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((tempC & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t) \
|
||||
(tempC & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
|
||||
DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
|
||||
|
||||
#undef DP_128OPERATION_HP
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define DP_QH(name, is_add, use_ac_env) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t rs3, rs2, rs1, rs0; \
|
||||
int32_t rt3, rt2, rt1, rt0; \
|
||||
int32_t tempD, tempC, tempB, tempA; \
|
||||
int64_t acc[2]; \
|
||||
int64_t temp[2]; \
|
||||
int64_t temp_sum; \
|
||||
\
|
||||
MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
|
||||
MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
|
||||
\
|
||||
if (use_ac_env) { \
|
||||
tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \
|
||||
tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \
|
||||
tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \
|
||||
} else { \
|
||||
tempD = mipsdsp_mul_u16_u16(rs3, rt3); \
|
||||
tempC = mipsdsp_mul_u16_u16(rs2, rt2); \
|
||||
tempB = mipsdsp_mul_u16_u16(rs1, rt1); \
|
||||
tempA = mipsdsp_mul_u16_u16(rs0, rt0); \
|
||||
} \
|
||||
\
|
||||
temp[0] = (int64_t)tempD + (int64_t)tempC + \
|
||||
(int64_t)tempB + (int64_t)tempA; \
|
||||
\
|
||||
if (temp[0] >= 0) { \
|
||||
temp[1] = 0; \
|
||||
} else { \
|
||||
temp[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
acc[1] = env->active_tc.HI[ac]; \
|
||||
acc[0] = env->active_tc.LO[ac]; \
|
||||
\
|
||||
if (is_add) { \
|
||||
temp_sum = acc[0] + temp[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) { \
|
||||
acc[1] = acc[1] + 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] + temp[1]; \
|
||||
} else { \
|
||||
temp_sum = acc[0] - temp[0]; \
|
||||
if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
|
||||
acc[1] = acc[1] - 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] - temp[1]; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = temp[1]; \
|
||||
env->active_tc.LO[ac] = temp[0]; \
|
||||
}
|
||||
|
||||
DP_QH(dpa_w_qh, 1, 0);
|
||||
DP_QH(dpaq_s_w_qh, 1, 1);
|
||||
DP_QH(dps_w_qh, 0, 0);
|
||||
DP_QH(dpsq_s_w_qh, 0, 1);
|
||||
|
||||
#undef DP_QH
|
||||
|
||||
#endif
|
||||
|
||||
#define DP_L_W(name, is_add) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t temp63; \
|
||||
int64_t dotp, acc; \
|
||||
uint64_t temp; \
|
||||
\
|
||||
dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
if (!is_add) { \
|
||||
dotp = -dotp; \
|
||||
} \
|
||||
\
|
||||
temp = acc + dotp; \
|
||||
if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp, \
|
||||
(0x01ull << 63))) { \
|
||||
temp63 = (temp >> 63) & 0x01; \
|
||||
if (temp63 == 1) { \
|
||||
temp = (0x01ull << 63) - 1; \
|
||||
} else { \
|
||||
temp = 0x01ull << 63; \
|
||||
} \
|
||||
\
|
||||
set_DSPControl_overflow_flag(1, 16 + ac, env); \
|
||||
} \
|
||||
\
|
||||
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); \
|
||||
}
|
||||
|
||||
DP_L_W(dpaq_sa_l_w, 1);
|
||||
DP_L_W(dpsq_sa_l_w, 0);
|
||||
|
||||
#undef DP_L_W
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define DP_L_PW(name, func) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t rs1, rs0; \
|
||||
int32_t rt1, rt0; \
|
||||
int64_t tempB[2], tempA[2]; \
|
||||
int64_t temp[2]; \
|
||||
int64_t acc[2]; \
|
||||
int64_t temp_sum; \
|
||||
\
|
||||
temp[0] = 0; \
|
||||
temp[1] = 0; \
|
||||
\
|
||||
MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
|
||||
MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
|
||||
\
|
||||
tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \
|
||||
tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \
|
||||
\
|
||||
if (tempB[0] >= 0) { \
|
||||
tempB[1] = 0x00; \
|
||||
} else { \
|
||||
tempB[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
if (tempA[0] >= 0) { \
|
||||
tempA[1] = 0x00; \
|
||||
} else { \
|
||||
tempA[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
temp_sum = tempB[0] + tempA[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)tempA[0])) { \
|
||||
temp[1] += 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] += tempB[1] + tempA[1]; \
|
||||
\
|
||||
mipsdsp_##func(acc, ac, temp, env); \
|
||||
\
|
||||
env->active_tc.HI[ac] = acc[1]; \
|
||||
env->active_tc.LO[ac] = acc[0]; \
|
||||
}
|
||||
|
||||
DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
|
||||
DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
|
||||
|
||||
#undef DP_L_PW
|
||||
|
||||
void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
|
||||
CPUMIPSState *env)
|
||||
{
|
||||
int32_t rs1, rs0;
|
||||
int32_t rt1, rt0;
|
||||
int64_t tempB[2], tempA[2];
|
||||
int64_t temp[2];
|
||||
int64_t acc[2];
|
||||
int64_t temp_sum;
|
||||
|
||||
rs1 = (rs >> 32) & MIPSDSP_LLO;
|
||||
rs0 = rs & MIPSDSP_LLO;
|
||||
rt1 = (rt >> 32) & MIPSDSP_LLO;
|
||||
rt0 = rt & MIPSDSP_LLO;
|
||||
|
||||
tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
|
||||
tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
|
||||
|
||||
if (tempB[0] >= 0) {
|
||||
tempB[1] = 0x00;
|
||||
} else {
|
||||
tempB[1] = ~0ull;
|
||||
}
|
||||
|
||||
if (tempA[0] >= 0) {
|
||||
tempA[1] = 0x00;
|
||||
} else {
|
||||
tempA[1] = ~0ull;
|
||||
}
|
||||
|
||||
acc[0] = env->active_tc.LO[ac];
|
||||
acc[1] = env->active_tc.HI[ac];
|
||||
|
||||
temp_sum = tempB[0] - tempA[0];
|
||||
if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
|
||||
tempB[1] -= 1;
|
||||
}
|
||||
temp[0] = temp_sum;
|
||||
temp[1] = tempB[1] - tempA[1];
|
||||
|
||||
if ((temp[1] & 0x01) == 0) {
|
||||
temp[1] = 0x00;
|
||||
} else {
|
||||
temp[1] = ~0ull;
|
||||
}
|
||||
|
||||
temp_sum = acc[0] + temp[0];
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) {
|
||||
acc[1] += 1;
|
||||
}
|
||||
acc[0] = temp_sum;
|
||||
acc[1] += temp[1];
|
||||
|
||||
env->active_tc.HI[ac] = acc[1];
|
||||
env->active_tc.LO[ac] = acc[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAQ_S_W(name, mov) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsh, rth; \
|
||||
int32_t tempA; \
|
||||
int64_t tempL, acc; \
|
||||
\
|
||||
rsh = (rs >> mov) & MIPSDSP_LO; \
|
||||
rth = (rt >> mov) & MIPSDSP_LO; \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
tempL = (int64_t)tempA + acc; \
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((tempL & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t) \
|
||||
(tempL & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
MAQ_S_W(maq_s_w_phl, 16);
|
||||
MAQ_S_W(maq_s_w_phr, 0);
|
||||
|
||||
#undef MAQ_S_W
|
||||
|
||||
#define MAQ_SA_W(name, mov) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rsh, rth; \
|
||||
int32_t tempA; \
|
||||
\
|
||||
rsh = (rs >> mov) & MIPSDSP_LO; \
|
||||
rth = (rt >> mov) & MIPSDSP_LO; \
|
||||
tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
|
||||
tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \
|
||||
MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \
|
||||
MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
MAQ_SA_W(maq_sa_w_phl, 16);
|
||||
MAQ_SA_W(maq_sa_w_phr, 0);
|
||||
|
||||
#undef MAQ_SA_W
|
||||
|
||||
#define MULQ_W(name, addvar) \
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint32_t rs_t, rt_t; \
|
||||
int32_t tempI; \
|
||||
int64_t tempL; \
|
||||
\
|
||||
rs_t = rs & MIPSDSP_LLO; \
|
||||
rt_t = rt & MIPSDSP_LLO; \
|
||||
\
|
||||
if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \
|
||||
tempL = 0x7FFFFFFF00000000ull; \
|
||||
set_DSPControl_overflow_flag(1, 21, env); \
|
||||
} else { \
|
||||
tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \
|
||||
tempL += addvar; \
|
||||
} \
|
||||
tempI = (tempL & MIPSDSP_LHI) >> 32; \
|
||||
\
|
||||
return (target_long)(int32_t)tempI; \
|
||||
}
|
||||
|
||||
MULQ_W(mulq_s_w, 0);
|
||||
MULQ_W(mulq_rs_w, 0x80000000ull);
|
||||
|
||||
#undef MULQ_W
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
|
||||
#define MAQ_S_W_QH(name, mov) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rs_t, rt_t; \
|
||||
int32_t temp_mul; \
|
||||
int64_t temp[2]; \
|
||||
int64_t acc[2]; \
|
||||
int64_t temp_sum; \
|
||||
\
|
||||
temp[0] = 0; \
|
||||
temp[1] = 0; \
|
||||
\
|
||||
rs_t = (rs >> mov) & MIPSDSP_LO; \
|
||||
rt_t = (rt >> mov) & MIPSDSP_LO; \
|
||||
temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
|
||||
\
|
||||
temp[0] = (int64_t)temp_mul; \
|
||||
if (temp[0] >= 0) { \
|
||||
temp[1] = 0x00; \
|
||||
} else { \
|
||||
temp[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
acc[0] = env->active_tc.LO[ac]; \
|
||||
acc[1] = env->active_tc.HI[ac]; \
|
||||
\
|
||||
temp_sum = acc[0] + temp[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) { \
|
||||
acc[1] += 1; \
|
||||
} \
|
||||
acc[0] = temp_sum; \
|
||||
acc[1] += temp[1]; \
|
||||
\
|
||||
env->active_tc.HI[ac] = acc[1]; \
|
||||
env->active_tc.LO[ac] = acc[0]; \
|
||||
}
|
||||
|
||||
MAQ_S_W_QH(maq_s_w_qhll, 48);
|
||||
MAQ_S_W_QH(maq_s_w_qhlr, 32);
|
||||
MAQ_S_W_QH(maq_s_w_qhrl, 16);
|
||||
MAQ_S_W_QH(maq_s_w_qhrr, 0);
|
||||
|
||||
#undef MAQ_S_W_QH
|
||||
|
||||
#define MAQ_SA_W(name, mov) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int16_t rs_t, rt_t; \
|
||||
int32_t temp; \
|
||||
int64_t acc[2]; \
|
||||
\
|
||||
rs_t = (rs >> mov) & MIPSDSP_LO; \
|
||||
rt_t = (rt >> mov) & MIPSDSP_LO; \
|
||||
temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
|
||||
temp = mipsdsp_sat32_acc_q31(ac, temp, env); \
|
||||
\
|
||||
acc[0] = (int64_t)(int32_t)temp; \
|
||||
if (acc[0] >= 0) { \
|
||||
acc[1] = 0x00; \
|
||||
} else { \
|
||||
acc[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = acc[1]; \
|
||||
env->active_tc.LO[ac] = acc[0]; \
|
||||
}
|
||||
|
||||
MAQ_SA_W(maq_sa_w_qhll, 48);
|
||||
MAQ_SA_W(maq_sa_w_qhlr, 32);
|
||||
MAQ_SA_W(maq_sa_w_qhrl, 16);
|
||||
MAQ_SA_W(maq_sa_w_qhrr, 0);
|
||||
|
||||
#undef MAQ_SA_W
|
||||
|
||||
#define MAQ_S_L_PW(name, mov) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t rs_t, rt_t; \
|
||||
int64_t temp[2]; \
|
||||
int64_t acc[2]; \
|
||||
int64_t temp_sum; \
|
||||
\
|
||||
temp[0] = 0; \
|
||||
temp[1] = 0; \
|
||||
\
|
||||
rs_t = (rs >> mov) & MIPSDSP_LLO; \
|
||||
rt_t = (rt >> mov) & MIPSDSP_LLO; \
|
||||
\
|
||||
temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \
|
||||
if (temp[0] >= 0) { \
|
||||
temp[1] = 0x00; \
|
||||
} else { \
|
||||
temp[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
acc[0] = env->active_tc.LO[ac]; \
|
||||
acc[1] = env->active_tc.HI[ac]; \
|
||||
\
|
||||
temp_sum = acc[0] + temp[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) { \
|
||||
acc[1] += 1; \
|
||||
} \
|
||||
acc[0] = temp_sum; \
|
||||
acc[1] += temp[1]; \
|
||||
\
|
||||
env->active_tc.HI[ac] = acc[1]; \
|
||||
env->active_tc.LO[ac] = acc[0]; \
|
||||
}
|
||||
|
||||
MAQ_S_L_PW(maq_s_l_pwl, 32);
|
||||
MAQ_S_L_PW(maq_s_l_pwr, 0);
|
||||
|
||||
#undef MAQ_S_L_PW
|
||||
|
||||
#define DM_OPERATE(name, func, is_add, sigext) \
|
||||
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t rs1, rs0; \
|
||||
int32_t rt1, rt0; \
|
||||
int64_t tempBL[2], tempAL[2]; \
|
||||
int64_t acc[2]; \
|
||||
int64_t temp[2]; \
|
||||
int64_t temp_sum; \
|
||||
\
|
||||
temp[0] = 0x00; \
|
||||
temp[1] = 0x00; \
|
||||
\
|
||||
MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
|
||||
MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
|
||||
\
|
||||
if (sigext) { \
|
||||
tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \
|
||||
tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \
|
||||
\
|
||||
if (tempBL[0] >= 0) { \
|
||||
tempBL[1] = 0x0; \
|
||||
} else { \
|
||||
tempBL[1] = ~0ull; \
|
||||
} \
|
||||
\
|
||||
if (tempAL[0] >= 0) { \
|
||||
tempAL[1] = 0x0; \
|
||||
} else { \
|
||||
tempAL[1] = ~0ull; \
|
||||
} \
|
||||
} else { \
|
||||
tempBL[0] = mipsdsp_##func(rs1, rt1); \
|
||||
tempAL[0] = mipsdsp_##func(rs0, rt0); \
|
||||
tempBL[1] = 0; \
|
||||
tempAL[1] = 0; \
|
||||
} \
|
||||
\
|
||||
acc[1] = env->active_tc.HI[ac]; \
|
||||
acc[0] = env->active_tc.LO[ac]; \
|
||||
\
|
||||
temp_sum = tempBL[0] + tempAL[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \
|
||||
temp[1] += 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] += tempBL[1] + tempAL[1]; \
|
||||
\
|
||||
if (is_add) { \
|
||||
temp_sum = acc[0] + temp[0]; \
|
||||
if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
|
||||
((uint64_t)temp_sum < (uint64_t)temp[0])) { \
|
||||
acc[1] += 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] + temp[1]; \
|
||||
} else { \
|
||||
temp_sum = acc[0] - temp[0]; \
|
||||
if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
|
||||
acc[1] -= 1; \
|
||||
} \
|
||||
temp[0] = temp_sum; \
|
||||
temp[1] = acc[1] - temp[1]; \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = temp[1]; \
|
||||
env->active_tc.LO[ac] = temp[0]; \
|
||||
}
|
||||
|
||||
DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
|
||||
DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
|
||||
DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
|
||||
DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
|
||||
#undef DM_OPERATE
|
||||
#endif
|
||||
|
||||
#undef MIPSDSP_LHI
|
||||
#undef MIPSDSP_LLO
|
||||
#undef MIPSDSP_HI
|
||||
|
|
|
@ -526,4 +526,95 @@ DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
|||
DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
#endif
|
||||
|
||||
/* DSP Multiply Sub-class insns */
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env)
|
||||
DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env)
|
||||
#if defined(TARGET_MIPS64)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
|
||||
DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
|
||||
#endif
|
||||
|
||||
#include "def-helper.h"
|
||||
|
|
|
@ -402,6 +402,13 @@ enum {
|
|||
OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
|
||||
/* MIPS DSP Multiply Sub-class insns */
|
||||
OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
|
||||
OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
|
||||
};
|
||||
|
||||
#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
|
||||
|
@ -420,6 +427,11 @@ enum {
|
|||
OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
|
||||
OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
|
||||
OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
|
||||
/* MIPS DSP Multiply Sub-class insns */
|
||||
OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
|
||||
OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
|
||||
OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
|
||||
OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
|
||||
};
|
||||
|
||||
#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
|
@ -451,6 +463,7 @@ enum {
|
|||
OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
|
||||
OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
|
||||
};
|
||||
|
||||
#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
/* MIPS DSP GPR-Based Shift Sub-class */
|
||||
|
@ -478,6 +491,33 @@ enum {
|
|||
OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
|
||||
};
|
||||
|
||||
#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
/* MIPS DSP Multiply Sub-class insns */
|
||||
OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
|
||||
OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
|
||||
};
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
|
@ -505,6 +545,12 @@ enum {
|
|||
#if defined(TARGET_MIPS64)
|
||||
#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
/* MIPS DSP Multiply Sub-class insns */
|
||||
OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
|
||||
OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
|
||||
OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
|
||||
OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
|
||||
OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
|
||||
/* MIPS DSP Arithmetic Sub-class */
|
||||
OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
|
||||
OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
|
||||
|
@ -545,6 +591,39 @@ enum {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
/* MIPS DSP Multiply Sub-class insns */
|
||||
OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
|
||||
enum {
|
||||
|
@ -13212,6 +13291,319 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
|
|||
MIPS_DEBUG("%s", opn);
|
||||
}
|
||||
|
||||
static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
|
||||
int ret, int v1, int v2, int check_ret)
|
||||
{
|
||||
const char *opn = "mipsdsp multiply";
|
||||
TCGv_i32 t0;
|
||||
TCGv v1_t;
|
||||
TCGv v2_t;
|
||||
|
||||
if ((ret == 0) && (check_ret == 1)) {
|
||||
/* Treat as NOP. */
|
||||
MIPS_DEBUG("NOP");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 = tcg_temp_new_i32();
|
||||
v1_t = tcg_temp_new();
|
||||
v2_t = tcg_temp_new();
|
||||
|
||||
tcg_gen_movi_i32(t0, ret);
|
||||
gen_load_gpr(v1_t, v1);
|
||||
gen_load_gpr(v2_t, v2);
|
||||
|
||||
switch (op1) {
|
||||
/* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
|
||||
* the same mask and op1. */
|
||||
case OPC_MULT_G_2E:
|
||||
switch (op2) {
|
||||
case OPC_MUL_PH:
|
||||
gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MUL_S_PH:
|
||||
gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULQ_S_W:
|
||||
gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULQ_RS_W:
|
||||
gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OPC_DPA_W_PH_DSP:
|
||||
switch (op2) {
|
||||
case OPC_DPAU_H_QBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAU_H_QBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSU_H_QBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSU_H_QBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPA_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAX_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQ_S_W_PH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQX_S_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQX_SA_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPS_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSX_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQ_S_W_PH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQX_S_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQX_SA_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULSAQ_S_W_PH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQ_SA_L_W:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQ_SA_L_W:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_PHL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_PHR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_PHL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_PHR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULSA_W_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_DPAQ_W_QH_DSP:
|
||||
{
|
||||
int ac = ret & 0x03;
|
||||
tcg_gen_movi_i32(t0, ac);
|
||||
|
||||
switch (op2) {
|
||||
case OPC_DMADD:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DMADDU:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DMSUB:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DMSUBU:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPA_W_QH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQ_S_W_QH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPAQ_SA_L_PW:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPAU_H_OBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPAU_H_OBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPS_W_QH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQ_S_W_QH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPSQ_SA_L_PW:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPSU_H_OBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_DPSU_H_OBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_L_PWL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_L_PWR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_QHLL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_QHLL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_QHLR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_QHLR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_QHRL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_QHRL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_S_W_QHRR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MAQ_SA_W_QHRR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MULSAQ_S_L_PW:
|
||||
check_dsp(ctx);
|
||||
gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
case OPC_MULSAQ_S_W_QH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case OPC_ADDU_QB_DSP:
|
||||
switch (op2) {
|
||||
case OPC_MULEU_S_PH_QBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEU_S_PH_QBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULQ_RS_PH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEQ_S_W_PHL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEQ_S_W_PHR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULQ_S_PH:
|
||||
check_dspr2(ctx);
|
||||
gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_ADDU_OB_DSP:
|
||||
switch (op2) {
|
||||
case OPC_MULEQ_S_PW_QHL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEQ_S_PW_QHR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEU_S_QH_OBL:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULEU_S_QH_OBR:
|
||||
check_dsp(ctx);
|
||||
gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
case OPC_MULQ_RS_QH:
|
||||
check_dsp(ctx);
|
||||
gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
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)
|
||||
|
@ -13586,6 +13978,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
|||
case OPC_SUBQH_R_W:
|
||||
gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MUL_PH:
|
||||
case OPC_MUL_S_PH:
|
||||
case OPC_MULQ_S_W:
|
||||
case OPC_MULQ_RS_W:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("MASK ADDUH.QB");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
|
@ -13661,6 +14059,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
|||
case OPC_RADDU_W_QB:
|
||||
gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MULEU_S_PH_QBL:
|
||||
case OPC_MULEU_S_PH_QBR:
|
||||
case OPC_MULQ_RS_PH:
|
||||
case OPC_MULEQ_S_W_PHL:
|
||||
case OPC_MULEQ_S_W_PHR:
|
||||
case OPC_MULQ_S_PH:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("MASK ADDU.QB");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
|
@ -13691,6 +14097,39 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
|||
case OPC_SHLL_QB_DSP:
|
||||
gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_DPA_W_PH_DSP:
|
||||
op2 = MASK_DPA_W_PH(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_DPAU_H_QBL:
|
||||
case OPC_DPAU_H_QBR:
|
||||
case OPC_DPSU_H_QBL:
|
||||
case OPC_DPSU_H_QBR:
|
||||
case OPC_DPA_W_PH:
|
||||
case OPC_DPAX_W_PH:
|
||||
case OPC_DPAQ_S_W_PH:
|
||||
case OPC_DPAQX_S_W_PH:
|
||||
case OPC_DPAQX_SA_W_PH:
|
||||
case OPC_DPS_W_PH:
|
||||
case OPC_DPSX_W_PH:
|
||||
case OPC_DPSQ_S_W_PH:
|
||||
case OPC_DPSQX_S_W_PH:
|
||||
case OPC_DPSQX_SA_W_PH:
|
||||
case OPC_MULSAQ_S_W_PH:
|
||||
case OPC_DPAQ_SA_L_W:
|
||||
case OPC_DPSQ_SA_L_W:
|
||||
case OPC_MAQ_S_W_PHL:
|
||||
case OPC_MAQ_S_W_PHR:
|
||||
case OPC_MAQ_SA_W_PHL:
|
||||
case OPC_MAQ_SA_W_PHR:
|
||||
case OPC_MULSA_W_PH:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("MASK DPAW.PH");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_DEXTM ... OPC_DEXT:
|
||||
case OPC_DINSM ... OPC_DINS:
|
||||
|
@ -13764,6 +14203,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
|||
case OPC_ADDUH_R_OB:
|
||||
gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MULEQ_S_PW_QHL:
|
||||
case OPC_MULEQ_S_PW_QHR:
|
||||
case OPC_MULEU_S_QH_OBL:
|
||||
case OPC_MULEU_S_QH_OBR:
|
||||
case OPC_MULQ_RS_QH:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("MASK ADDU.OB");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
|
@ -13792,6 +14238,45 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case OPC_DPAQ_W_QH_DSP:
|
||||
op2 = MASK_DPAQ_W_QH(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_DPAU_H_OBL:
|
||||
case OPC_DPAU_H_OBR:
|
||||
case OPC_DPSU_H_OBL:
|
||||
case OPC_DPSU_H_OBR:
|
||||
case OPC_DPA_W_QH:
|
||||
case OPC_DPAQ_S_W_QH:
|
||||
case OPC_DPS_W_QH:
|
||||
case OPC_DPSQ_S_W_QH:
|
||||
case OPC_MULSAQ_S_W_QH:
|
||||
case OPC_DPAQ_SA_L_PW:
|
||||
case OPC_DPSQ_SA_L_PW:
|
||||
case OPC_MULSAQ_S_L_PW:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
|
||||
break;
|
||||
case OPC_MAQ_S_W_QHLL:
|
||||
case OPC_MAQ_S_W_QHLR:
|
||||
case OPC_MAQ_S_W_QHRL:
|
||||
case OPC_MAQ_S_W_QHRR:
|
||||
case OPC_MAQ_SA_W_QHLL:
|
||||
case OPC_MAQ_SA_W_QHLR:
|
||||
case OPC_MAQ_SA_W_QHRL:
|
||||
case OPC_MAQ_SA_W_QHRR:
|
||||
case OPC_MAQ_S_L_PWL:
|
||||
case OPC_MAQ_S_L_PWR:
|
||||
case OPC_DMADD:
|
||||
case OPC_DMADDU:
|
||||
case OPC_DMSUB:
|
||||
case OPC_DMSUBU:
|
||||
gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("MASK DPAQ.W.QH");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OPC_SHLL_OB_DSP:
|
||||
gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue