target-tricore: Add instructions of RRR1 opcode format, which have 0x63 as first opcode
Add helpers: * msub64_q_ssov: multiply two 32 bit q-format number, sub the result from a 64 bit q-format number and saturate. * msub32_q_sub_ssov: sub two 64 bit q-format numbers and return a 32 bit result. * msubr_q_ssov: multiply two 32 bit q-format numbers, sub the result from a 32 bit q-format number and saturate. * msubr_q: multiply two 32 bit q-format numbers and sub the result from a 32 bit q-format number. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
This commit is contained in:
parent
f4aef476af
commit
62e47b2e6d
@ -43,6 +43,9 @@ DEF_HELPER_4(madd64_suov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_5(msub64_q_ssov, i64, env, i64, i32, i32, i32)
|
||||
DEF_HELPER_3(msub32_q_sub_ssov, i32, env, i64, i64)
|
||||
DEF_HELPER_5(msubr_q_ssov, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_3(absdif_h_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_2(abs_ssov, i32, env, i32)
|
||||
@ -60,6 +63,7 @@ DEF_HELPER_3(add_h, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_b, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_h, i32, env, i32, i32)
|
||||
DEF_HELPER_4(subr_h, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_5(msubr_q, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eq_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eq_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eqany_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
|
@ -838,6 +838,132 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
helper_msub32_q_sub_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2)
|
||||
{
|
||||
int64_t result;
|
||||
int64_t t1 = (int64_t)r1;
|
||||
int64_t t2 = (int64_t)r2;
|
||||
|
||||
result = t1 - t2;
|
||||
|
||||
env->PSW_USB_AV = (result ^ result * 2u);
|
||||
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||
|
||||
/* we do the saturation by hand, since we produce an overflow on the host
|
||||
if the mul before was (0x80000000 * 0x80000000) << 1). If this is the
|
||||
case, we flip the saturated value. */
|
||||
if (r2 == 0x8000000000000000LL) {
|
||||
if (result > 0x7fffffffLL) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
result = INT32_MIN;
|
||||
} else if (result < -0x80000000LL) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
result = INT32_MAX;
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
}
|
||||
} else {
|
||||
if (result > 0x7fffffffLL) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
result = INT32_MAX;
|
||||
} else if (result < -0x80000000LL) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
result = INT32_MIN;
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
}
|
||||
}
|
||||
return (uint32_t)result;
|
||||
}
|
||||
|
||||
uint64_t helper_msub64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2,
|
||||
uint32_t r3, uint32_t n)
|
||||
{
|
||||
int64_t t1 = (int64_t)r1;
|
||||
int64_t t2 = sextract64(r2, 0, 32);
|
||||
int64_t t3 = sextract64(r3, 0, 32);
|
||||
int64_t result, mul;
|
||||
int64_t ovf;
|
||||
|
||||
mul = (t2 * t3) << n;
|
||||
result = t1 - mul;
|
||||
|
||||
env->PSW_USB_AV = (result ^ result * 2u) >> 32;
|
||||
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||
|
||||
ovf = (result ^ t1) & (t1 ^ mul);
|
||||
/* we do the saturation by hand, since we produce an overflow on the host
|
||||
if the mul before was (0x80000000 * 0x80000000) << 1). If this is the
|
||||
case, we flip the saturated value. */
|
||||
if (mul == 0x8000000000000000LL) {
|
||||
if (ovf >= 0) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
/* ext_ret > MAX_INT */
|
||||
if (mul >= 0) {
|
||||
result = INT64_MAX;
|
||||
/* ext_ret < MIN_INT */
|
||||
} else {
|
||||
result = INT64_MIN;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ovf < 0) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV = (1 << 31);
|
||||
/* ext_ret > MAX_INT */
|
||||
if (mul < 0) {
|
||||
result = INT64_MAX;
|
||||
/* ext_ret < MIN_INT */
|
||||
} else {
|
||||
result = INT64_MIN;
|
||||
}
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint64_t)result;
|
||||
}
|
||||
|
||||
uint32_t helper_msubr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2,
|
||||
uint32_t r3, uint32_t n)
|
||||
{
|
||||
int64_t t1 = sextract64(r1, 0, 32);
|
||||
int64_t t2 = sextract64(r2, 0, 32);
|
||||
int64_t t3 = sextract64(r3, 0, 32);
|
||||
int64_t mul, ret;
|
||||
|
||||
if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) {
|
||||
mul = 0x7fffffff;
|
||||
} else {
|
||||
mul = (t2 * t3) << n;
|
||||
}
|
||||
|
||||
ret = t1 - mul + 0x8000;
|
||||
|
||||
env->PSW_USB_AV = ret ^ ret * 2u;
|
||||
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||
|
||||
if (ret > 0x7fffffffll) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||
ret = INT32_MAX;
|
||||
} else if (ret < -0x80000000ll) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||
ret = INT32_MIN;
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
}
|
||||
return ret & 0xffff0000ll;
|
||||
}
|
||||
|
||||
uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
|
||||
{
|
||||
int32_t b, i;
|
||||
@ -1126,6 +1252,34 @@ uint32_t helper_subr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
|
||||
return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
|
||||
}
|
||||
|
||||
uint32_t helper_msubr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2,
|
||||
uint32_t r3, uint32_t n)
|
||||
{
|
||||
int64_t t1 = sextract64(r1, 0, 32);
|
||||
int64_t t2 = sextract64(r2, 0, 32);
|
||||
int64_t t3 = sextract64(r3, 0, 32);
|
||||
int64_t mul, ret;
|
||||
|
||||
if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) {
|
||||
mul = 0x7fffffff;
|
||||
} else {
|
||||
mul = (t2 * t3) << n;
|
||||
}
|
||||
|
||||
ret = t1 - mul + 0x8000;
|
||||
|
||||
if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) {
|
||||
env->PSW_USB_V = (1 << 31);
|
||||
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
}
|
||||
env->PSW_USB_AV = ret ^ ret * 2u;
|
||||
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||
|
||||
return ret & 0xffff0000ll;
|
||||
}
|
||||
|
||||
uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
|
||||
{
|
||||
int32_t b, i;
|
||||
|
@ -1890,6 +1890,287 @@ gen_msubr32s_h(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n, uint32_t mode)
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msubr_q(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_const_i32(n);
|
||||
gen_helper_msubr_q(ret, cpu_env, r1, r2, r3, temp);
|
||||
tcg_temp_free(temp);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msubrs_q(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_const_i32(n);
|
||||
gen_helper_msubr_q_ssov(ret, cpu_env, r1, r2, r3, temp);
|
||||
tcg_temp_free(temp);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msub32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n,
|
||||
uint32_t up_shift, CPUTriCoreState *env)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
TCGv temp3 = tcg_temp_new();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
TCGv_i64 t4 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_i32_i64(t2, arg2);
|
||||
tcg_gen_ext_i32_i64(t3, arg3);
|
||||
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
|
||||
tcg_gen_ext_i32_i64(t1, arg1);
|
||||
/* if we shift part of the fraction out, we need to round up */
|
||||
tcg_gen_andi_i64(t4, t2, (1ll << (up_shift - n)) - 1);
|
||||
tcg_gen_setcondi_i64(TCG_COND_NE, t4, t4, 0);
|
||||
tcg_gen_sari_i64(t2, t2, up_shift - n);
|
||||
tcg_gen_add_i64(t2, t2, t4);
|
||||
|
||||
tcg_gen_sub_i64(t3, t1, t2);
|
||||
tcg_gen_trunc_i64_i32(temp3, t3);
|
||||
/* calc v bit */
|
||||
tcg_gen_setcondi_i64(TCG_COND_GT, t1, t3, 0x7fffffffLL);
|
||||
tcg_gen_setcondi_i64(TCG_COND_LT, t2, t3, -0x80000000LL);
|
||||
tcg_gen_or_i64(t1, t1, t2);
|
||||
tcg_gen_trunc_i64_i32(cpu_PSW_V, t1);
|
||||
tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
|
||||
/* We produce an overflow on the host if the mul before was
|
||||
(0x80000000 * 0x80000000) << 1). If this is the
|
||||
case, we negate the ovf. */
|
||||
if (n == 1) {
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp, arg2, 0x80000000);
|
||||
tcg_gen_setcond_tl(TCG_COND_EQ, temp2, arg2, arg3);
|
||||
tcg_gen_and_tl(temp, temp, temp2);
|
||||
tcg_gen_shli_tl(temp, temp, 31);
|
||||
/* negate v bit, if special condition */
|
||||
tcg_gen_xor_tl(cpu_PSW_V, cpu_PSW_V, temp);
|
||||
}
|
||||
/* Calc SV bit */
|
||||
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
|
||||
/* Calc AV/SAV bits */
|
||||
tcg_gen_add_tl(cpu_PSW_AV, temp3, temp3);
|
||||
tcg_gen_xor_tl(cpu_PSW_AV, temp3, cpu_PSW_AV);
|
||||
/* calc SAV */
|
||||
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
|
||||
/* write back result */
|
||||
tcg_gen_mov_tl(ret, temp3);
|
||||
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
tcg_temp_free(temp3);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_temp_free_i64(t4);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_m16sub32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
if (n == 0) {
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
} else { /* n is exspected to be 1 */
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
tcg_gen_shli_tl(temp, temp, 1);
|
||||
/* catch special case r1 = r2 = 0x8000 */
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, temp, 0x80000000);
|
||||
tcg_gen_sub_tl(temp, temp, temp2);
|
||||
}
|
||||
gen_sub_d(ret, arg1, temp);
|
||||
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_m16subs32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
if (n == 0) {
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
} else { /* n is exspected to be 1 */
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
tcg_gen_shli_tl(temp, temp, 1);
|
||||
/* catch special case r1 = r2 = 0x8000 */
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, temp, 0x80000000);
|
||||
tcg_gen_sub_tl(temp, temp, temp2);
|
||||
}
|
||||
gen_subs(ret, arg1, temp);
|
||||
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_m16sub64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
|
||||
TCGv arg3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
if (n == 0) {
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
} else { /* n is exspected to be 1 */
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
tcg_gen_shli_tl(temp, temp, 1);
|
||||
/* catch special case r1 = r2 = 0x8000 */
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, temp, 0x80000000);
|
||||
tcg_gen_sub_tl(temp, temp, temp2);
|
||||
}
|
||||
tcg_gen_ext_i32_i64(t2, temp);
|
||||
tcg_gen_shli_i64(t2, t2, 16);
|
||||
tcg_gen_concat_i32_i64(t1, arg1_low, arg1_high);
|
||||
gen_sub64_d(t3, t1, t2);
|
||||
/* write back result */
|
||||
tcg_gen_extr_i64_i32(rl, rh, t3);
|
||||
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_m16subs64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
|
||||
TCGv arg3, uint32_t n)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
|
||||
if (n == 0) {
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
} else { /* n is exspected to be 1 */
|
||||
tcg_gen_mul_tl(temp, arg2, arg3);
|
||||
tcg_gen_shli_tl(temp, temp, 1);
|
||||
/* catch special case r1 = r2 = 0x8000 */
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, temp, 0x80000000);
|
||||
tcg_gen_sub_tl(temp, temp, temp2);
|
||||
}
|
||||
tcg_gen_ext_i32_i64(t2, temp);
|
||||
tcg_gen_shli_i64(t2, t2, 16);
|
||||
tcg_gen_concat_i32_i64(t1, arg1_low, arg1_high);
|
||||
|
||||
gen_helper_sub64_ssov(t1, cpu_env, t1, t2);
|
||||
tcg_gen_extr_i64_i32(rl, rh, t1);
|
||||
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msub64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
|
||||
TCGv arg3, uint32_t n, CPUTriCoreState *env)
|
||||
{
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
TCGv_i64 t4 = tcg_temp_new_i64();
|
||||
TCGv temp, temp2;
|
||||
|
||||
tcg_gen_concat_i32_i64(t1, arg1_low, arg1_high);
|
||||
tcg_gen_ext_i32_i64(t2, arg2);
|
||||
tcg_gen_ext_i32_i64(t3, arg3);
|
||||
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
if (n != 0) {
|
||||
tcg_gen_shli_i64(t2, t2, 1);
|
||||
}
|
||||
tcg_gen_sub_i64(t4, t1, t2);
|
||||
/* calc v bit */
|
||||
tcg_gen_xor_i64(t3, t4, t1);
|
||||
tcg_gen_xor_i64(t2, t1, t2);
|
||||
tcg_gen_and_i64(t3, t3, t2);
|
||||
tcg_gen_trunc_shr_i64_i32(cpu_PSW_V, t3, 32);
|
||||
/* We produce an overflow on the host if the mul before was
|
||||
(0x80000000 * 0x80000000) << 1). If this is the
|
||||
case, we negate the ovf. */
|
||||
if (n == 1) {
|
||||
temp = tcg_temp_new();
|
||||
temp2 = tcg_temp_new();
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, temp, arg2, 0x80000000);
|
||||
tcg_gen_setcond_tl(TCG_COND_EQ, temp2, arg2, arg3);
|
||||
tcg_gen_and_tl(temp, temp, temp2);
|
||||
tcg_gen_shli_tl(temp, temp, 31);
|
||||
/* negate v bit, if special condition */
|
||||
tcg_gen_xor_tl(cpu_PSW_V, cpu_PSW_V, temp);
|
||||
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
/* write back result */
|
||||
tcg_gen_extr_i64_i32(rl, rh, t4);
|
||||
/* Calc SV bit */
|
||||
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
|
||||
/* Calc AV/SAV bits */
|
||||
tcg_gen_add_tl(cpu_PSW_AV, rh, rh);
|
||||
tcg_gen_xor_tl(cpu_PSW_AV, rh, cpu_PSW_AV);
|
||||
/* calc SAV */
|
||||
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
|
||||
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_temp_free_i64(t4);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msubs32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n,
|
||||
uint32_t up_shift)
|
||||
{
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
TCGv_i64 t4 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_ext_i32_i64(t1, arg1);
|
||||
tcg_gen_ext_i32_i64(t2, arg2);
|
||||
tcg_gen_ext_i32_i64(t3, arg3);
|
||||
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
/* if we shift part of the fraction out, we need to round up */
|
||||
tcg_gen_andi_i64(t4, t2, (1ll << (up_shift - n)) - 1);
|
||||
tcg_gen_setcondi_i64(TCG_COND_NE, t4, t4, 0);
|
||||
tcg_gen_sari_i64(t3, t2, up_shift - n);
|
||||
tcg_gen_add_i64(t3, t3, t4);
|
||||
|
||||
gen_helper_msub32_q_sub_ssov(ret, cpu_env, t1, t3);
|
||||
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
tcg_temp_free_i64(t4);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gen_msubs64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
|
||||
TCGv arg3, uint32_t n)
|
||||
{
|
||||
TCGv_i64 r1 = tcg_temp_new_i64();
|
||||
TCGv temp = tcg_const_i32(n);
|
||||
|
||||
tcg_gen_concat_i32_i64(r1, arg1_low, arg1_high);
|
||||
gen_helper_msub64_q_ssov(r1, cpu_env, r1, arg2, arg3, temp);
|
||||
tcg_gen_extr_i64_i32(rl, rh, r1);
|
||||
|
||||
tcg_temp_free_i64(r1);
|
||||
tcg_temp_free(temp);
|
||||
}
|
||||
|
||||
static inline void gen_abs(TCGv ret, TCGv r1)
|
||||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
@ -6822,6 +7103,162 @@ static void decode_rrr1_msub(CPUTriCoreState *env, DisasContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
|
||||
{
|
||||
uint32_t op2;
|
||||
uint32_t r1, r2, r3, r4, n;
|
||||
TCGv temp, temp2;
|
||||
|
||||
op2 = MASK_OP_RRR1_OP2(ctx->opcode);
|
||||
r1 = MASK_OP_RRR1_S1(ctx->opcode);
|
||||
r2 = MASK_OP_RRR1_S2(ctx->opcode);
|
||||
r3 = MASK_OP_RRR1_S3(ctx->opcode);
|
||||
r4 = MASK_OP_RRR1_D(ctx->opcode);
|
||||
n = MASK_OP_RRR1_N(ctx->opcode);
|
||||
|
||||
temp = tcg_const_i32(n);
|
||||
temp2 = tcg_temp_new();
|
||||
|
||||
switch (op2) {
|
||||
case OPC2_32_RRR1_MSUB_Q_32:
|
||||
gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
cpu_gpr_d[r2], n, 32, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_64:
|
||||
gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
|
||||
n, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_32_L:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
|
||||
gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
temp, n, 16, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_64_L:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
|
||||
gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
|
||||
n, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_32_U:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
|
||||
gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
temp, n, 16, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_64_U:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
|
||||
gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
|
||||
n, env);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_32_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_m16sub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_64_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_m16sub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_32_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_m16sub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUB_Q_64_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_m16sub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_32:
|
||||
gen_msubs32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
cpu_gpr_d[r2], n, 32);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_64:
|
||||
gen_msubs64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
|
||||
n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_32_L:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
|
||||
gen_msubs32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
temp, n, 16);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_64_L:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
|
||||
gen_msubs64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
|
||||
n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_32_U:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
|
||||
gen_msubs32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||
temp, n, 16);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_64_U:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
|
||||
gen_msubs64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
|
||||
n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_32_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_m16subs32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_64_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_m16subs64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_32_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_m16subs32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBS_Q_64_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_m16subs64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
|
||||
cpu_gpr_d[r3+1], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBR_H_64_UL:
|
||||
gen_msubr64_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r3+1],
|
||||
cpu_gpr_d[r1], cpu_gpr_d[r2], n, 2);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBRS_H_64_UL:
|
||||
gen_msubr64s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r3+1],
|
||||
cpu_gpr_d[r1], cpu_gpr_d[r2], n, 2);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBR_Q_32_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_msubr_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBR_Q_32_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_msubr_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBRS_Q_32_LL:
|
||||
tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
|
||||
tcg_gen_ext16s_tl(temp2, cpu_gpr_d[r2]);
|
||||
gen_msubrs_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
case OPC2_32_RRR1_MSUBRS_Q_32_UU:
|
||||
tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 16);
|
||||
tcg_gen_sari_tl(temp2, cpu_gpr_d[r2], 16);
|
||||
gen_msubrs_q(cpu_gpr_d[r4], cpu_gpr_d[r3], temp, temp2, n);
|
||||
break;
|
||||
}
|
||||
tcg_temp_free(temp);
|
||||
tcg_temp_free(temp2);
|
||||
}
|
||||
|
||||
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
||||
{
|
||||
int op1;
|
||||
@ -7131,6 +7568,9 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
||||
case OPCM_32_RRR1_MSUB_H:
|
||||
decode_rrr1_msub(env, ctx);
|
||||
break;
|
||||
case OPCM_32_RRR1_MSUB_Q:
|
||||
decode_rrr1_msubq_h(env, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1328,8 +1328,8 @@ enum {
|
||||
OPC2_32_RRR1_MSUBS_Q_64_LL = 0x3d,
|
||||
OPC2_32_RRR1_MSUBS_Q_32_UU = 0x24,
|
||||
OPC2_32_RRR1_MSUBS_Q_64_UU = 0x3c,
|
||||
OPC2_32_RRR1_MSUBR_H_32_UL = 0x1e,
|
||||
OPC2_32_RRR1_MSUBRS_H_32_UL = 0x3e,
|
||||
OPC2_32_RRR1_MSUBR_H_64_UL = 0x1e,
|
||||
OPC2_32_RRR1_MSUBRS_H_64_UL = 0x3e,
|
||||
OPC2_32_RRR1_MSUBR_Q_32_LL = 0x07,
|
||||
OPC2_32_RRR1_MSUBR_Q_32_UU = 0x06,
|
||||
OPC2_32_RRR1_MSUBRS_Q_32_LL = 0x27,
|
||||
|
Loading…
Reference in New Issue
Block a user