target-tricore: Add instructions of RRR1 opcode format, which have 0x83 as first opcode
Add helpers: * add64_ssov: adds two 64 bit values and saturates the result. * addr_h/_ssov: adds two halfwords with two words in q-format with rounding / and saturates each result independetly. Add microcode generator: * gen_add64_d: adds two 64 bit values. * gen_addsub64_h: adds/subtracts one halfwords with a word and adds/ subtracts another halftword with another word. * gen_madd_h/s_h: multiply four halfwords, add each result left justfied to two word values / and saturate each result. * gen_maddm_h/s_h: multiply four halfwords, add each result left justfied to two words values in q-format / and saturate each result. * gen_maddr32/64_h/s_h: multiply four halfwords, add each result left justfied to two halftwords/words values in q-format / and saturate each result. Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
2984cfbdb4
commit
2e430e1cdc
@ -17,9 +17,11 @@
|
|||||||
|
|
||||||
/* Arithmetic */
|
/* Arithmetic */
|
||||||
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
|
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
|
||||||
|
DEF_HELPER_3(add64_ssov, i64, env, i64, i64)
|
||||||
DEF_HELPER_3(add_suov, i32, env, i32, i32)
|
DEF_HELPER_3(add_suov, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
|
DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
|
DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
|
||||||
|
DEF_HELPER_4(addr_h_ssov, i32, env, i64, i32, i32)
|
||||||
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
|
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
|
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
|
DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
|
||||||
@ -44,6 +46,7 @@ DEF_HELPER_2(abs_b, i32, env, i32)
|
|||||||
DEF_HELPER_2(abs_h, i32, env, i32)
|
DEF_HELPER_2(abs_h, i32, env, i32)
|
||||||
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
|
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(absdif_h, i32, env, i32, i32)
|
DEF_HELPER_3(absdif_h, i32, env, i32, i32)
|
||||||
|
DEF_HELPER_4(addr_h, i32, env, i64, i32, i32)
|
||||||
DEF_HELPER_3(add_b, i32, env, i32, i32)
|
DEF_HELPER_3(add_b, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(add_h, i32, env, i32, i32)
|
DEF_HELPER_3(add_h, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(sub_b, i32, env, i32, i32)
|
DEF_HELPER_3(sub_b, i32, env, i32, i32)
|
||||||
|
@ -184,6 +184,31 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
|
|||||||
return ssov32(env, result);
|
return ssov32(env, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t helper_add64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2)
|
||||||
|
{
|
||||||
|
uint64_t result;
|
||||||
|
int64_t ovf;
|
||||||
|
|
||||||
|
result = r1 + r2;
|
||||||
|
ovf = (result ^ r1) & ~(r1 ^ r2);
|
||||||
|
env->PSW_USB_AV = (result ^ result * 2u) >> 32;
|
||||||
|
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||||
|
if (ovf < 0) {
|
||||||
|
env->PSW_USB_V = (1 << 31);
|
||||||
|
env->PSW_USB_SV = (1 << 31);
|
||||||
|
/* ext_ret > MAX_INT */
|
||||||
|
if ((int64_t)r1 >= 0) {
|
||||||
|
result = INT64_MAX;
|
||||||
|
/* ext_ret < MIN_INT */
|
||||||
|
} else {
|
||||||
|
result = INT64_MIN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
env->PSW_USB_V = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
|
target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
|
||||||
target_ulong r2)
|
target_ulong r2)
|
||||||
{
|
{
|
||||||
@ -194,6 +219,53 @@ target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
|
|||||||
return ssov16(env, ret_hw0, ret_hw1);
|
return ssov16(env, ret_hw0, ret_hw1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t helper_addr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
|
||||||
|
uint32_t r2_h)
|
||||||
|
{
|
||||||
|
int64_t mul_res0 = sextract64(r1, 0, 32);
|
||||||
|
int64_t mul_res1 = sextract64(r1, 32, 32);
|
||||||
|
int64_t r2_low = sextract64(r2_l, 0, 32);
|
||||||
|
int64_t r2_high = sextract64(r2_h, 0, 32);
|
||||||
|
int64_t result0, result1;
|
||||||
|
uint32_t ovf0, ovf1;
|
||||||
|
uint32_t avf0, avf1;
|
||||||
|
|
||||||
|
ovf0 = ovf1 = 0;
|
||||||
|
|
||||||
|
result0 = r2_low + mul_res0 + 0x8000;
|
||||||
|
result1 = r2_high + mul_res1 + 0x8000;
|
||||||
|
|
||||||
|
avf0 = result0 * 2u;
|
||||||
|
avf0 = result0 ^ avf0;
|
||||||
|
avf1 = result1 * 2u;
|
||||||
|
avf1 = result1 ^ avf1;
|
||||||
|
|
||||||
|
if (result0 > INT32_MAX) {
|
||||||
|
ovf0 = (1 << 31);
|
||||||
|
result0 = INT32_MAX;
|
||||||
|
} else if (result0 < INT32_MIN) {
|
||||||
|
ovf0 = (1 << 31);
|
||||||
|
result0 = INT32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result1 > INT32_MAX) {
|
||||||
|
ovf1 = (1 << 31);
|
||||||
|
result1 = INT32_MAX;
|
||||||
|
} else if (result1 < INT32_MIN) {
|
||||||
|
ovf1 = (1 << 31);
|
||||||
|
result1 = INT32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
env->PSW_USB_V = ovf0 | ovf1;
|
||||||
|
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||||
|
|
||||||
|
env->PSW_USB_AV = avf0 | avf1;
|
||||||
|
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||||
|
|
||||||
|
return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
|
target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
|
||||||
target_ulong r2)
|
target_ulong r2)
|
||||||
{
|
{
|
||||||
@ -619,6 +691,44 @@ uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t helper_addr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
|
||||||
|
uint32_t r2_h)
|
||||||
|
{
|
||||||
|
int64_t mul_res0 = sextract64(r1, 0, 32);
|
||||||
|
int64_t mul_res1 = sextract64(r1, 32, 32);
|
||||||
|
int64_t r2_low = sextract64(r2_l, 0, 32);
|
||||||
|
int64_t r2_high = sextract64(r2_h, 0, 32);
|
||||||
|
int64_t result0, result1;
|
||||||
|
uint32_t ovf0, ovf1;
|
||||||
|
uint32_t avf0, avf1;
|
||||||
|
|
||||||
|
ovf0 = ovf1 = 0;
|
||||||
|
|
||||||
|
result0 = r2_low + mul_res0 + 0x8000;
|
||||||
|
result1 = r2_high + mul_res1 + 0x8000;
|
||||||
|
|
||||||
|
if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) {
|
||||||
|
ovf0 = (1 << 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) {
|
||||||
|
ovf1 = (1 << 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
env->PSW_USB_V = ovf0 | ovf1;
|
||||||
|
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||||
|
|
||||||
|
avf0 = result0 * 2u;
|
||||||
|
avf0 = result0 ^ avf0;
|
||||||
|
avf1 = result1 * 2u;
|
||||||
|
avf1 = result1 ^ avf1;
|
||||||
|
|
||||||
|
env->PSW_USB_AV = avf0 | avf1;
|
||||||
|
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||||
|
|
||||||
|
return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
|
uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
|
||||||
{
|
{
|
||||||
int32_t b, i;
|
int32_t b, i;
|
||||||
|
@ -80,6 +80,13 @@ enum {
|
|||||||
BS_EXCP = 3,
|
BS_EXCP = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MODE_LL = 0,
|
||||||
|
MODE_LU = 1,
|
||||||
|
MODE_UL = 2,
|
||||||
|
MODE_UU = 3,
|
||||||
|
};
|
||||||
|
|
||||||
void tricore_cpu_dump_state(CPUState *cs, FILE *f,
|
void tricore_cpu_dump_state(CPUState *cs, FILE *f,
|
||||||
fprintf_function cpu_fprintf, int flags)
|
fprintf_function cpu_fprintf, int flags)
|
||||||
{
|
{
|
||||||
@ -395,6 +402,88 @@ static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2)
|
|||||||
tcg_temp_free(t0);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_add64_d(TCGv_i64 ret, TCGv_i64 r1, TCGv_i64 r2)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_temp_new();
|
||||||
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 result = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_add_i64(result, r1, r2);
|
||||||
|
/* calc v bit */
|
||||||
|
tcg_gen_xor_i64(t1, result, r1);
|
||||||
|
tcg_gen_xor_i64(t0, r1, r2);
|
||||||
|
tcg_gen_andc_i64(t1, t1, t0);
|
||||||
|
tcg_gen_trunc_shr_i64_i32(cpu_PSW_V, t1, 32);
|
||||||
|
/* calc SV bit */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
|
||||||
|
/* calc AV/SAV bits */
|
||||||
|
tcg_gen_trunc_shr_i64_i32(temp, result, 32);
|
||||||
|
tcg_gen_add_tl(cpu_PSW_AV, temp, temp);
|
||||||
|
tcg_gen_xor_tl(cpu_PSW_AV, temp, cpu_PSW_AV);
|
||||||
|
/* calc SAV */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
|
||||||
|
/* write back result */
|
||||||
|
tcg_gen_mov_i64(ret, result);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free_i64(result);
|
||||||
|
tcg_temp_free_i64(t0);
|
||||||
|
tcg_temp_free_i64(t1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_addsub64_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
|
||||||
|
TCGv r3, void(*op1)(TCGv, TCGv, TCGv),
|
||||||
|
void(*op2)(TCGv, TCGv, TCGv))
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_temp_new();
|
||||||
|
TCGv temp2 = tcg_temp_new();
|
||||||
|
TCGv temp3 = tcg_temp_new();
|
||||||
|
TCGv temp4 = tcg_temp_new();
|
||||||
|
|
||||||
|
(*op1)(temp, r1_low, r2);
|
||||||
|
/* calc V0 bit */
|
||||||
|
tcg_gen_xor_tl(temp2, temp, r1_low);
|
||||||
|
tcg_gen_xor_tl(temp3, r1_low, r2);
|
||||||
|
if (op1 == tcg_gen_add_tl) {
|
||||||
|
tcg_gen_andc_tl(temp2, temp2, temp3);
|
||||||
|
} else {
|
||||||
|
tcg_gen_and_tl(temp2, temp2, temp3);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*op2)(temp3, r1_high, r3);
|
||||||
|
/* calc V1 bit */
|
||||||
|
tcg_gen_xor_tl(cpu_PSW_V, temp3, r1_high);
|
||||||
|
tcg_gen_xor_tl(temp4, r1_high, r3);
|
||||||
|
if (op2 == tcg_gen_add_tl) {
|
||||||
|
tcg_gen_andc_tl(cpu_PSW_V, cpu_PSW_V, temp4);
|
||||||
|
} else {
|
||||||
|
tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp4);
|
||||||
|
}
|
||||||
|
/* combine V0/V1 bits */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_V, cpu_PSW_V, temp2);
|
||||||
|
/* calc sv bit */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
|
||||||
|
/* write result */
|
||||||
|
tcg_gen_mov_tl(ret_low, temp);
|
||||||
|
tcg_gen_mov_tl(ret_high, temp3);
|
||||||
|
/* calc AV bit */
|
||||||
|
tcg_gen_add_tl(temp, ret_low, ret_low);
|
||||||
|
tcg_gen_xor_tl(temp, temp, ret_low);
|
||||||
|
tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high);
|
||||||
|
tcg_gen_xor_tl(cpu_PSW_AV, cpu_PSW_AV, ret_high);
|
||||||
|
tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
|
||||||
|
/* calc SAV bit */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free(temp2);
|
||||||
|
tcg_temp_free(temp3);
|
||||||
|
tcg_temp_free(temp4);
|
||||||
|
}
|
||||||
|
|
||||||
/* ret = r2 + (r1 * r3); */
|
/* ret = r2 + (r1 * r3); */
|
||||||
static inline void gen_madd32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
|
static inline void gen_madd32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
|
||||||
{
|
{
|
||||||
@ -523,6 +612,221 @@ gen_maddui64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
|
|||||||
tcg_temp_free(temp);
|
tcg_temp_free(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_madd_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
|
||||||
|
TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv temp2 = tcg_temp_new();
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_gen_extr_i64_i32(temp, temp2, temp64);
|
||||||
|
gen_addsub64_h(ret_low, ret_high, r1_low, r1_high, temp, temp2,
|
||||||
|
tcg_gen_add_tl, tcg_gen_add_tl);
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free(temp2);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gen_adds(TCGv ret, TCGv r1, TCGv r2);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_madds_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
|
||||||
|
TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv temp2 = tcg_temp_new();
|
||||||
|
TCGv temp3 = tcg_temp_new();
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_gen_extr_i64_i32(temp, temp2, temp64);
|
||||||
|
gen_adds(ret_low, r1_low, temp);
|
||||||
|
tcg_gen_mov_tl(temp, cpu_PSW_V);
|
||||||
|
tcg_gen_mov_tl(temp3, cpu_PSW_AV);
|
||||||
|
gen_adds(ret_high, r1_high, temp2);
|
||||||
|
/* combine v bits */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_V, cpu_PSW_V, temp);
|
||||||
|
/* combine av bits */
|
||||||
|
tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp3);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free(temp2);
|
||||||
|
tcg_temp_free(temp3);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddm_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
|
||||||
|
TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 temp64_2 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 temp64_3 = tcg_temp_new_i64();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_gen_concat_i32_i64(temp64_2, r1_low, r1_high);
|
||||||
|
gen_add64_d(temp64_3, temp64_2, temp64);
|
||||||
|
/* write back result */
|
||||||
|
tcg_gen_extr_i64_i32(ret_low, ret_high, temp64_3);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
tcg_temp_free_i64(temp64_2);
|
||||||
|
tcg_temp_free_i64(temp64_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddms_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
|
||||||
|
TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 temp64_2 = tcg_temp_new_i64();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mulm_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_gen_concat_i32_i64(temp64_2, r1_low, r1_high);
|
||||||
|
gen_helper_add64_ssov(temp64, cpu_env, temp64_2, temp64);
|
||||||
|
tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
tcg_temp_free_i64(temp64_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddr64_h(TCGv ret, TCGv r1_low, TCGv r1_high, TCGv r2, TCGv r3, uint32_t n,
|
||||||
|
uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gen_helper_addr_h(ret, cpu_env, temp64, r1_low, r1_high);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddr32_h(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_temp_new();
|
||||||
|
TCGv temp2 = tcg_temp_new();
|
||||||
|
|
||||||
|
tcg_gen_andi_tl(temp2, r1, 0xffff0000);
|
||||||
|
tcg_gen_shli_tl(temp, r1, 16);
|
||||||
|
gen_maddr64_h(ret, temp, temp2, r2, r3, n, mode);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free(temp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddr64s_h(TCGv ret, TCGv r1_low, TCGv r1_high, TCGv r2, TCGv r3,
|
||||||
|
uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_const_i32(n);
|
||||||
|
TCGv_i64 temp64 = tcg_temp_new_i64();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_LL:
|
||||||
|
GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_LU:
|
||||||
|
GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UL:
|
||||||
|
GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
case MODE_UU:
|
||||||
|
GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gen_helper_addr_h_ssov(ret, cpu_env, temp64, r1_low, r1_high);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free_i64(temp64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gen_maddr32s_h(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n, uint32_t mode)
|
||||||
|
{
|
||||||
|
TCGv temp = tcg_temp_new();
|
||||||
|
TCGv temp2 = tcg_temp_new();
|
||||||
|
|
||||||
|
tcg_gen_andi_tl(temp2, r1, 0xffff0000);
|
||||||
|
tcg_gen_shli_tl(temp, r1, 16);
|
||||||
|
gen_maddr64s_h(ret, temp, temp2, r2, r3, n, mode);
|
||||||
|
|
||||||
|
tcg_temp_free(temp);
|
||||||
|
tcg_temp_free(temp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ret = r2 - (r1 * r3); */
|
/* ret = r2 - (r1 * r3); */
|
||||||
static inline void gen_msub32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
|
static inline void gen_msub32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
|
||||||
{
|
{
|
||||||
@ -5300,6 +5604,119 @@ static void decode_rrr2_msub(CPUTriCoreState *env, DisasContext *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RRR1 format */
|
||||||
|
static void decode_rrr1_madd(CPUTriCoreState *env, DisasContext *ctx)
|
||||||
|
{
|
||||||
|
uint32_t op2;
|
||||||
|
uint32_t r1, r2, r3, r4, n;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
switch (op2) {
|
||||||
|
case OPC2_32_RRR1_MADD_H_LL:
|
||||||
|
gen_madd_h(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, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADD_H_LU:
|
||||||
|
gen_madd_h(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, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADD_H_UL:
|
||||||
|
gen_madd_h(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, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADD_H_UU:
|
||||||
|
gen_madd_h(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, MODE_UU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDS_H_LL:
|
||||||
|
gen_madds_h(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, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDS_H_LU:
|
||||||
|
gen_madds_h(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, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDS_H_UL:
|
||||||
|
gen_madds_h(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, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDS_H_UU:
|
||||||
|
gen_madds_h(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, MODE_UU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDM_H_LL:
|
||||||
|
gen_maddm_h(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, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDM_H_LU:
|
||||||
|
gen_maddm_h(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, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDM_H_UL:
|
||||||
|
gen_maddm_h(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, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDM_H_UU:
|
||||||
|
gen_maddm_h(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, MODE_UU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDMS_H_LL:
|
||||||
|
gen_maddms_h(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, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDMS_H_LU:
|
||||||
|
gen_maddms_h(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, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDMS_H_UL:
|
||||||
|
gen_maddms_h(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, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDMS_H_UU:
|
||||||
|
gen_maddms_h(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, MODE_UU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDR_H_LL:
|
||||||
|
gen_maddr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDR_H_LU:
|
||||||
|
gen_maddr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDR_H_UL:
|
||||||
|
gen_maddr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDR_H_UU:
|
||||||
|
gen_maddr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_UU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDRS_H_LL:
|
||||||
|
gen_maddr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_LL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDRS_H_LU:
|
||||||
|
gen_maddr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_LU);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDRS_H_UL:
|
||||||
|
gen_maddr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_UL);
|
||||||
|
break;
|
||||||
|
case OPC2_32_RRR1_MADDRS_H_UU:
|
||||||
|
gen_maddr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
|
||||||
|
cpu_gpr_d[r2], n, MODE_UU);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int op1;
|
int op1;
|
||||||
@ -5596,6 +6013,10 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
|||||||
case OPCM_32_RRR2_MSUB:
|
case OPCM_32_RRR2_MSUB:
|
||||||
decode_rrr2_msub(env, ctx);
|
decode_rrr2_msub(env, ctx);
|
||||||
break;
|
break;
|
||||||
|
/* RRR1 format */
|
||||||
|
case OPCM_32_RRR1_MADD:
|
||||||
|
decode_rrr1_madd(env, ctx);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user