Add instructions of RR opcode format, that have 0xb as the first opcode. Add helper functions, for hword and byte arithmetics: * add_h_ssov/suov: Add two halfword and saturate on overflow. * sub_h_ssov/suov: Sub two halfword and saturate on overflow. * absdif_h_ssov: Compute absolute difference for halfwords and saturate on overflow. * abs_h_ssov/suov: Compute absolute value for two halfwords and saturate on overflow. * abs_b/h: Compute absolute value for four/two bytes/halfwords * absdif_b/h: Compute absolute difference for four/two bytes/halfwords * add_b/h: Add four/two bytes/halfwords. * sub_b/h: Sub four/two bytes/halfwords. * eq_b/h: Compare four/two bytes/halfwords with four/two bytes/halfwords on equality and set all bits of to either one ore zero. * eqany_b/h: Compare four/two bytes/halfwords with four/two bytes/halfwords on equality. * lt_b/bu/h/hu: Compare four/two bytes/halfwords with four/two bytes/halfwords on less than signed and unsigned. * max_b/bu/h/hu: Calculate max for four/two bytes/halfwords signed and unsigned. * min_b/bu/h/hu: Calculate min for four/two bytes/halfwords signed and unsigned. Add helper function abs_ssov, that computes the absolute value for a 32 bit integer and saturates on overflow. Add microcode generator functions: * gen_sub_CC: Caluclates sub and sets the carry bit. * gen_subc_CC: Caluclates sub and carry and sets the carry bit * gen_abs: Compute absolute value for a 32 bit integer. * gen_cond_w: Compares two 32 bit values on cond and sets result either zero or all bits one.
OPC2_32_RR_MIN switched with OPC2_32_RR_MIN_U. Signed-off-by: Bastian Koppelmann <kbast...@mail.uni-paderborn.de> --- target-tricore/helper.h | 32 +++ target-tricore/op_helper.c | 533 +++++++++++++++++++++++++++++++++++++++ target-tricore/translate.c | 388 ++++++++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 4 +- 4 files changed, 955 insertions(+), 2 deletions(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 6c07bd7..ce3f6db 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -18,8 +18,12 @@ /* Arithmetic */ DEF_HELPER_3(add_ssov, 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_suov, 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_h_ssov, i32, env, i32, i32) +DEF_HELPER_3(sub_h_suov, i32, env, i32, i32) DEF_HELPER_3(mul_ssov, i32, env, i32, i32) DEF_HELPER_3(mul_suov, i32, env, i32, i32) DEF_HELPER_3(sha_ssov, i32, env, i32, i32) @@ -32,6 +36,34 @@ 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_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) +DEF_HELPER_2(abs_h_ssov, i32, env, i32) +/* hword/byte arithmetic */ +DEF_HELPER_2(abs_b, i32, env, i32) +DEF_HELPER_2(abs_h, i32, env, i32) +DEF_HELPER_3(absdif_b, i32, env, i32, i32) +DEF_HELPER_3(absdif_h, 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(sub_b, i32, env, i32, i32) +DEF_HELPER_3(sub_h, i32, env, i32, i32) +DEF_HELPER_2(eq_b, i32, i32, i32) +DEF_HELPER_2(eq_h, i32, i32, i32) +DEF_HELPER_2(eqany_b, i32, i32, i32) +DEF_HELPER_2(eqany_h, i32, i32, i32) +DEF_HELPER_2(lt_b, i32, i32, i32) +DEF_HELPER_2(lt_bu, i32, i32, i32) +DEF_HELPER_2(lt_h, i32, i32, i32) +DEF_HELPER_2(lt_hu, i32, i32, i32) +DEF_HELPER_2(max_b, i32, i32, i32) +DEF_HELPER_2(max_bu, i32, i32, i32) +DEF_HELPER_2(max_h, i32, i32, i32) +DEF_HELPER_2(max_hu, i32, i32, i32) +DEF_HELPER_2(min_b, i32, i32, i32) +DEF_HELPER_2(min_bu, i32, i32, i32) +DEF_HELPER_2(min_h, i32, i32, i32) +DEF_HELPER_2(min_hu, i32, i32, i32) /* CSA */ DEF_HELPER_2(call, void, env, i32) DEF_HELPER_1(ret, void, env) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 3843348..3885897 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -97,6 +97,62 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off) env->PSW_USB_SAV |= env->PSW_USB_AV; \ } while (0) +#define SSOV16(env, hw0, hw1) do { \ + int32_t max_pos = INT16_MAX; \ + int32_t max_neg = INT16_MIN; \ + int32_t av0, av1; \ + \ + env->PSW_USB_V = 0; \ + av0 = hw0 ^ hw0 * 2u; \ + if (hw0 > max_pos) { \ + env->PSW_USB_V = (1 << 31); \ + hw0 = max_pos; \ + } else if (hw0 < max_neg) { \ + env->PSW_USB_V = (1 << 31); \ + hw0 = max_neg; \ + } \ + \ + av1 = hw1 ^ hw1 * 2u; \ + if (hw1 > max_pos) { \ + env->PSW_USB_V = (1 << 31); \ + hw1 = max_pos; \ + } else if (hw1 < max_neg) { \ + env->PSW_USB_V = (1 << 31); \ + hw1 = max_neg; \ + } \ + \ + env->PSW_USB_SV |= env->PSW_USB_V; \ + env->PSW_USB_AV = (av0 | av1) << 16; \ + env->PSW_USB_SAV |= env->PSW_USB_AV; \ +} while (0) + +#define SUOV16(env, hw0, hw1) do { \ + int32_t max_pos = UINT16_MAX; \ + int32_t av0, av1; \ + \ + env->PSW_USB_V = 0; \ + av0 = hw0 ^ hw0 * 2u; \ + if (hw0 > max_pos) { \ + env->PSW_USB_V = (1 << 31); \ + hw0 = max_pos; \ + } else if (hw0 < 0) { \ + env->PSW_USB_V = (1 << 31); \ + hw0 = 0; \ + } \ + \ + av1 = hw1 ^ hw1 * 2u; \ + if (hw1 > max_pos) { \ + env->PSW_USB_V = (1 << 31); \ + hw1 = max_pos; \ + } else if (hw1 < 0) { \ + env->PSW_USB_V = (1 << 31); \ + hw1 = 0; \ + } \ + \ + env->PSW_USB_SV |= env->PSW_USB_V; \ + env->PSW_USB_AV = (av0 | av1) << 16; \ + env->PSW_USB_SAV |= env->PSW_USB_AV; \ +} while (0) target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) @@ -109,6 +165,18 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + int32_t ret_hw0, ret_hw1; + + ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16); + ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16); + SSOV16(env, ret_hw0, ret_hw1); + + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); +} + target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -120,6 +188,18 @@ target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + int32_t ret_hw0, ret_hw1; + + ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16); + ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16); + SUOV16(env, ret_hw0, ret_hw1); + + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); +} + target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -131,6 +211,18 @@ target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + int32_t ret_hw0, ret_hw1; + + ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16); + ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16); + SSOV16(env, ret_hw0, ret_hw1); + + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); +} + target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -142,6 +234,18 @@ target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, return ret; } +target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + int32_t ret_hw0, ret_hw1; + + ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16); + ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16); + SUOV16(env, ret_hw0, ret_hw1); + + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); +} + target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -182,6 +286,28 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1) +{ + target_ulong result; + result = ((int32_t)r1 >= 0) ? r1 : (0 - r1); + SSOV32(env, result, result); + return result; +} + +uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1) +{ + int32_t ret_h0, ret_h1; + + ret_h0 = sextract32(r1, 0, 16); + ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0); + + ret_h1 = sextract32(r1, 16, 16); + ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1); + + SSOV16(env, ret_h0, ret_h1); + return (ret_h0 & 0xffff) | (ret_h1 << 16); +} + target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -199,6 +325,33 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, return ret; } +uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1, + target_ulong r2) +{ + int32_t t1, t2; + int32_t ret_h0, ret_h1; + + t1 = sextract32(r1, 0, 16); + t2 = sextract32(r2, 0, 16); + if (t1 > t2) { + ret_h0 = t1 - t2; + } else { + ret_h0 = t2 - t1; + } + + t1 = sextract32(r1, 16, 16); + t2 = sextract32(r2, 16, 16); + if (t1 > t2) { + ret_h1 = t1 - t2; + } else { + ret_h1 = t2 - t1; + } + + SSOV16(env, ret_h0, ret_h1); + + return (ret_h0 & 0xffff) | (ret_h1 << 16); +} + target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { @@ -366,6 +519,386 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, return ret; } +uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg) +{ + int32_t b, i; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 4; i++) { + b = sextract32(arg, i * 8, 8); + b = (b >= 0) ? b : (0 - b); + ovf |= (b > 0x7F) || (b < -0x80); + avf |= b ^ b * 2u; + ret |= (b & 0xff) << (i * 8); + } + + env->PSW_USB_V = ovf << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 24; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg) +{ + int32_t h, i; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 2; i++) { + h = sextract32(arg, i * 16, 16); + h = (h >= 0) ? h : (0 - h); + ovf |= (h > 0x7FFF) || (h < -0x8000); + avf |= h ^ h * 2u; + ret |= (h & 0xffff) << (i * 16); + } + + env->PSW_USB_V = ovf << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 16; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t b, i; + int32_t extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 4; i++) { + extr_r2 = sextract32(r2, i * 8, 8); + b = sextract32(r1, i * 8, 8); + b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b); + ovf |= (b > 0x7F) || (b < -0x80); + avf |= b ^ b * 2u; + ret |= (b & 0xff) << (i * 8); + } + + env->PSW_USB_V = ovf << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 24; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} + +uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t h, i; + int32_t extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 2; i++) { + extr_r2 = sextract32(r2, i * 16, 16); + h = sextract32(r1, i * 16, 16); + h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h); + ovf |= (h > 0x7FFF) || (h < -0x8000); + avf |= h ^ h * 2u; + ret |= (h & 0xffff) << (i * 16); + } + + env->PSW_USB_V = ovf << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 16; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t b, i; + int32_t extr_r1, extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + uint32_t ret = 0; + + for (i = 0; i < 4; i++) { + extr_r1 = sextract32(r1, i * 8, 8); + extr_r2 = sextract32(r2, i * 8, 8); + + b = extr_r1 + extr_r2; + ovf |= ((b > 0x7f) || (b < -0x80)); + avf |= b ^ b * 2u; + ret |= ((b & 0xff) << (i*8)); + } + + env->PSW_USB_V = (ovf << 31); + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 24; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t h, i; + int32_t extr_r1, extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 2; i++) { + extr_r1 = sextract32(r1, i * 16, 16); + extr_r2 = sextract32(r2, i * 16, 16); + h = extr_r1 + extr_r2; + ovf |= ((h > 0x7fff) || (h < -0x8000)); + avf |= h ^ h * 2u; + ret |= (h & 0xffff) << (i * 16); + } + + env->PSW_USB_V = (ovf << 31); + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = (avf << 16); + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t b, i; + int32_t extr_r1, extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + uint32_t ret = 0; + + for (i = 0; i < 4; i++) { + extr_r1 = sextract32(r1, i * 8, 8); + extr_r2 = sextract32(r2, i * 8, 8); + + b = extr_r1 - extr_r2; + ovf |= ((b > 0x7f) || (b < -0x80)); + avf |= b ^ b * 2u; + ret |= ((b & 0xff) << (i*8)); + } + + env->PSW_USB_V = (ovf << 31); + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 24; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t h, i; + int32_t extr_r1, extr_r2; + int32_t ovf = 0; + int32_t avf = 0; + int32_t ret = 0; + + for (i = 0; i < 2; i++) { + extr_r1 = sextract32(r1, i * 16, 16); + extr_r2 = sextract32(r2, i * 16, 16); + h = extr_r1 - extr_r2; + ovf |= ((h > 0x7fff) || (h < -0x8000)); + avf |= h ^ h * 2u; + ret |= (h & 0xffff) << (i * 16); + } + + env->PSW_USB_V = (ovf << 31); + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = avf << 16; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_eq_b(target_ulong r1, target_ulong r2) +{ + int32_t ret; + int32_t i, msk; + + ret = 0; + msk = 0xff; + for (i = 0; i < 4; i++) { + if ((r1 & msk) == (r2 & msk)) { + ret |= msk; + } + msk = msk << 8; + } + + return ret; +} + +uint32_t helper_eq_h(target_ulong r1, target_ulong r2) +{ + int32_t ret = 0; + + if ((r1 & 0xffff) == (r2 & 0xffff)) { + ret = 0xffff; + } + + if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) { + ret |= 0xffff0000; + } + + return ret; +} + +uint32_t helper_eqany_b(target_ulong r1, target_ulong r2) +{ + int32_t i; + uint32_t ret = 0; + + for (i = 0; i < 4; i++) { + ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8)); + } + + return ret; +} + +uint32_t helper_eqany_h(target_ulong r1, target_ulong r2) +{ + uint32_t ret; + + ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16)); + ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16)); + + return ret; +} + +uint32_t helper_lt_b(target_ulong r1, target_ulong r2) +{ + int32_t i; + uint32_t ret = 0; + + for (i = 0; i < 4; i++) { + if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) { + ret |= (0xff << (i * 8)); + } + } + + return ret; +} + +uint32_t helper_lt_bu(target_ulong r1, target_ulong r2) +{ + int32_t i; + uint32_t ret = 0; + + for (i = 0; i < 4; i++) { + if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) { + ret |= (0xff << (i * 8)); + } + } + + return ret; +} + +uint32_t helper_lt_h(target_ulong r1, target_ulong r2) +{ + uint32_t ret = 0; + + if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) { + ret |= 0xffff; + } + + if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) { + ret |= 0xffff0000; + } + + return ret; +} + +uint32_t helper_lt_hu(target_ulong r1, target_ulong r2) +{ + uint32_t ret = 0; + + if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) { + ret |= 0xffff; + } + + if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) { + ret |= 0xffff0000; + } + + return ret; +} + +#define EXTREMA_H_B(name, op) \ +uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \ +{ \ + int32_t i, extr_r1, extr_r2; \ + uint32_t ret = 0; \ + \ + for (i = 0; i < 4; i++) { \ + extr_r1 = sextract32(r1, i * 8, 8); \ + extr_r2 = sextract32(r2, i * 8, 8); \ + extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret |= (extr_r1 & 0xff) << (i * 8); \ + } \ + return ret; \ +} \ + \ +uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\ +{ \ + int32_t i; \ + uint32_t extr_r1, extr_r2; \ + uint32_t ret = 0; \ + \ + for (i = 0; i < 4; i++) { \ + extr_r1 = extract32(r1, i * 8, 8); \ + extr_r2 = extract32(r2, i * 8, 8); \ + extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret |= (extr_r1 & 0xff) << (i * 8); \ + } \ + return ret; \ +} \ + \ +uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \ +{ \ + int32_t extr_r1, extr_r2; \ + uint32_t ret = 0; \ + \ + extr_r1 = sextract32(r1, 0, 16); \ + extr_r2 = sextract32(r2, 0, 16); \ + ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret = ret & 0xffff; \ + \ + extr_r1 = sextract32(r1, 16, 16); \ + extr_r2 = sextract32(r2, 16, 16); \ + extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret |= extr_r1 << 16; \ + \ + return ret; \ +} \ + \ +uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\ +{ \ + uint32_t extr_r1, extr_r2; \ + uint32_t ret = 0; \ + \ + extr_r1 = extract32(r1, 0, 16); \ + extr_r2 = extract32(r2, 0, 16); \ + ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret = ret & 0xffff; \ + \ + extr_r1 = extract32(r1, 16, 16); \ + extr_r2 = extract32(r2, 16, 16); \ + extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ + ret |= extr_r1 << (16); \ + \ + return ret; \ +} \ + +EXTREMA_H_B(max, >) +EXTREMA_H_B(min, <) + +#undef EXTREMA_H_B + /* context save area (CSA) related helpers */ static int cdc_increment(target_ulong *psw) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 65abf45..a1f29db 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -719,6 +719,62 @@ static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2) tcg_temp_free(result); } +static inline void gen_sub_CC(TCGv ret, TCGv r1, TCGv r2) +{ + TCGv result = tcg_temp_new(); + TCGv temp = tcg_temp_new(); + + tcg_gen_sub_tl(result, r1, r2); + /* calc C bit */ + tcg_gen_setcond_tl(TCG_COND_GEU, cpu_PSW_C, r1, r2); + /* calc V bit */ + tcg_gen_xor_tl(cpu_PSW_V, result, r1); + tcg_gen_xor_tl(temp, r1, r2); + tcg_gen_and_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 bit */ + tcg_gen_add_tl(cpu_PSW_AV, result, result); + tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); + /* calc SAV bit */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + /* write back result */ + tcg_gen_mov_tl(ret, result); + + tcg_temp_free(result); + tcg_temp_free(temp); +} + +static inline void gen_subc_CC(TCGv ret, TCGv r1, TCGv r2) +{ + TCGv temp = tcg_temp_new(); + tcg_gen_not_tl(temp, r2); + gen_addc_CC(ret, r1, temp); + tcg_temp_free(temp); +} + +static inline void gen_abs(TCGv ret, TCGv r1) +{ + TCGv temp = tcg_temp_new(); + TCGv t0 = tcg_const_i32(0); + + tcg_gen_neg_tl(temp, r1); + tcg_gen_movcond_tl(TCG_COND_GE, ret, r1, t0, r1, temp); + /* overflow can only happen, if r1 = 0x80000000 */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, r1, 0x80000000); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* calc SV bit */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* Calc AV bit */ + tcg_gen_add_tl(cpu_PSW_AV, ret, ret); + tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); + /* calc SAV bit */ + tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + + tcg_temp_free(temp); + tcg_temp_free(t0); +} + static inline void gen_absdif(TCGv ret, TCGv r1, TCGv r2) { TCGv temp = tcg_temp_new_i32(); @@ -1208,6 +1264,18 @@ gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con, tcg_temp_free(temp); } +/* ret = (r1 cond r2) ? 0xFFFFFFFF ? 0x00000000;*/ +static inline void gen_cond_w(TCGCond cond, TCGv ret, TCGv r1, TCGv r2) +{ + TCGv temp = tcg_temp_new(); + + tcg_gen_setcond_tl(cond, temp, r1, r2); + tcg_gen_movi_tl(ret, 0); + tcg_gen_sub_tl(ret, ret, temp); + + tcg_temp_free(temp); +} + static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con) { TCGv b0 = tcg_temp_new(); @@ -3797,6 +3865,322 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx, } } +/* RR format */ +static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r3, r2, r1; + + r3 = MASK_OP_RR_D(ctx->opcode); + r2 = MASK_OP_RR_S2(ctx->opcode); + r1 = MASK_OP_RR_S1(ctx->opcode); + op2 = MASK_OP_RR_OP2(ctx->opcode); + + switch (op2) { + case OPC2_32_RR_ABS: + gen_abs(cpu_gpr_d[r3], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABS_B: + gen_helper_abs_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABS_H: + gen_helper_abs_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSDIF: + gen_absdif(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSDIF_B: + gen_helper_absdif_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSDIF_H: + gen_helper_absdif_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSDIFS: + gen_helper_absdif_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSDIFS_H: + gen_helper_absdif_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSS: + gen_helper_abs_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ABSS_H: + gen_helper_abs_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADD: + gen_add_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADD_B: + gen_helper_add_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADD_H: + gen_helper_add_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDC: + gen_addc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDS: + gen_adds(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDS_H: + gen_helper_add_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDS_HU: + gen_helper_add_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDS_U: + gen_helper_add_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ADDX: + gen_add_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_AND_EQ: + gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_AND_GE: + gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_AND_GE_U: + gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_AND_LT: + gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_AND_LT_U: + gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_AND_NE: + gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_and_tl); + break; + case OPC2_32_RR_EQ: + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_EQ_B: + gen_helper_eq_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_EQ_H: + gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_EQ_W: + gen_cond_w(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_EQANY_B: + gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_EQANY_H: + gen_helper_eqany_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_GE: + tcg_gen_setcond_tl(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_GE_U: + tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT: + tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_U: + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_B: + gen_helper_lt_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_BU: + gen_helper_lt_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_H: + gen_helper_lt_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_HU: + gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_W: + gen_cond_w(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_LT_WU: + gen_cond_w(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX: + tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX_U: + tcg_gen_movcond_tl(TCG_COND_GTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX_B: + gen_helper_max_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX_BU: + gen_helper_max_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX_H: + gen_helper_max_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MAX_HU: + gen_helper_max_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN: + tcg_gen_movcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN_U: + tcg_gen_movcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN_B: + gen_helper_min_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN_BU: + gen_helper_min_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN_H: + gen_helper_min_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MIN_HU: + gen_helper_min_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MOV: + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_NE: + tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_OR_EQ: + gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_OR_GE: + gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_OR_GE_U: + gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_OR_LT: + gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_OR_LT_U: + gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_OR_NE: + gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_or_tl); + break; + case OPC2_32_RR_SAT_B: + gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7f, -0x80); + break; + case OPC2_32_RR_SAT_BU: + gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xff); + break; + case OPC2_32_RR_SAT_H: + gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7fff, -0x8000); + break; + case OPC2_32_RR_SAT_HU: + gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xffff); + break; + case OPC2_32_RR_SH_EQ: + gen_sh_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_GE: + gen_sh_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_GE_U: + gen_sh_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_LT: + gen_sh_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_LT_U: + gen_sh_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_NE: + gen_sh_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUB: + gen_sub_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUB_B: + gen_helper_sub_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUB_H: + gen_helper_sub_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBC: + gen_subc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBS: + gen_subs(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBS_U: + gen_subsu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBS_H: + gen_helper_sub_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBS_HU: + gen_helper_sub_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SUBX: + gen_sub_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_XOR_EQ: + gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + case OPC2_32_RR_XOR_GE: + gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + case OPC2_32_RR_XOR_GE_U: + gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + case OPC2_32_RR_XOR_LT: + gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + case OPC2_32_RR_XOR_LT_U: + gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + case OPC2_32_RR_XOR_NE: + gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1], + cpu_gpr_d[r2], &tcg_gen_xor_tl); + break; + } +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -4027,6 +4411,10 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPC1_32_RLC_MTCR: decode_rlc_opc(env, ctx, op1); break; +/* RR Format */ + case OPCM_32_RR_ACCUMULATOR: + decode_rr_accumulator(env, ctx); + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 0a9122c..40ca202 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1033,8 +1033,8 @@ enum { OPC2_32_RR_MAX_BU = 0x5b, OPC2_32_RR_MAX_H = 0x7a, OPC2_32_RR_MAX_HU = 0x7b, - OPC2_32_RR_MIN = 0x19, - OPC2_32_RR_MIN_U = 0x18, + OPC2_32_RR_MIN = 0x18, + OPC2_32_RR_MIN_U = 0x19, OPC2_32_RR_MIN_B = 0x58, OPC2_32_RR_MIN_BU = 0x59, OPC2_32_RR_MIN_H = 0x78, -- 2.1.3