From 30a0d72f949fc46e54a180cf703e89b6d3df157d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 7 Mar 2015 15:43:32 +0100 Subject: target-tricore: Fix two helper functions (clang warnings) clang report: target-tricore/op_helper.c:1247:24: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] target-tricore/op_helper.c:1248:25: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] target-tricore/op_helper.c:1249:19: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] target-tricore/op_helper.c:1297:24: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] target-tricore/op_helper.c:1298:25: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] target-tricore/op_helper.c:1299:19: warning: taking the absolute value of unsigned type 'uint32_t' (aka 'unsigned int') has no effect [-Wabsolute-value] Fix also the divisor which was taken from the wrong register (thanks to Peter Maydell for this hint). Cc: Bastian Koppelmann Signed-off-by: Stefan Weil Message-Id: <1425739412-8144-1-git-send-email-sw@weilnetz.de> Signed-off-by: Bastian Koppelmann --- target-tricore/op_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 97b0c8b..2cfa95d 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -1953,9 +1953,9 @@ uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) quotient_sign = 1; } - abs_sig_dividend = abs(r1) >> 7; - abs_base_dividend = abs(r1) & 0x7f; - abs_divisor = abs(r1); + abs_sig_dividend = abs((int32_t)r1) >> 7; + abs_base_dividend = abs((int32_t)r1) & 0x7f; + abs_divisor = abs((int32_t)r2); /* calc overflow */ env->PSW_USB_V = 0; if ((quotient_sign) && (abs_divisor)) { @@ -2003,9 +2003,9 @@ uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) quotient_sign = 1; } - abs_sig_dividend = abs(r1) >> 7; - abs_base_dividend = abs(r1) & 0x7f; - abs_divisor = abs(r1); + abs_sig_dividend = abs((int32_t)r1) >> 7; + abs_base_dividend = abs((int32_t)r1) & 0x7f; + abs_divisor = abs((int32_t)r2); /* calc overflow */ env->PSW_USB_V = 0; if ((quotient_sign) && (abs_divisor)) { -- cgit v1.1 From 2b9d09bb3c44de934de03864d56ddd8a38ed863a Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 19 Mar 2015 15:36:14 +0000 Subject: target-tricore: fix DVINIT_HU/BU calculating overflow before result dvinit_hu/bu for ISA v1.3 calculate the higher part of the result, that is needed for the overflow bits, after calculating the overflow bits. Signed-off-by: Bastian Koppelmann --- target-tricore/translate.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 0b7cf06..989a047 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6240,7 +6240,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) uint32_t op2; int r1, r2, r3; - TCGv temp, temp2; + TCGv temp, temp2, temp3; op2 = MASK_OP_RR_OP2(ctx->opcode); r3 = MASK_OP_RR_D(ctx->opcode); @@ -6261,14 +6261,17 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_DVINIT_BU: temp = tcg_temp_new(); temp2 = tcg_temp_new(); + temp3 = tcg_temp_new(); + + tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 8); /* reset av */ tcg_gen_movi_tl(cpu_PSW_AV, 0); if (!tricore_feature(env, TRICORE_FEATURE_131)) { /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */ - tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]); + tcg_gen_neg_tl(temp, temp3); /* use cpu_PSW_AV to compare against 0 */ - tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV, - temp, cpu_gpr_d[r3+1]); + tcg_gen_movcond_tl(TCG_COND_LT, temp, temp3, cpu_PSW_AV, + temp, temp3); tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]); tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV, temp2, cpu_gpr_d[r2]); @@ -6281,12 +6284,12 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) /* sv */ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); /* write result */ - tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 8); tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 24); - tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp); + tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp3); tcg_temp_free(temp); tcg_temp_free(temp2); + tcg_temp_free(temp3); break; case OPC2_32_RR_DVINIT_H: gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], @@ -6295,14 +6298,17 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_DVINIT_HU: temp = tcg_temp_new(); temp2 = tcg_temp_new(); + temp3 = tcg_temp_new(); + + tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 16); /* reset av */ tcg_gen_movi_tl(cpu_PSW_AV, 0); if (!tricore_feature(env, TRICORE_FEATURE_131)) { /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */ - tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]); + tcg_gen_neg_tl(temp, temp3); /* use cpu_PSW_AV to compare against 0 */ - tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV, - temp, cpu_gpr_d[r3+1]); + tcg_gen_movcond_tl(TCG_COND_LT, temp, temp3, cpu_PSW_AV, + temp, temp3); tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]); tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV, temp2, cpu_gpr_d[r2]); @@ -6315,11 +6321,11 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) /* sv */ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); /* write result */ - tcg_gen_mov_tl(temp, cpu_gpr_d[r1]); - tcg_gen_shri_tl(cpu_gpr_d[r3+1], temp, 16); - tcg_gen_shli_tl(cpu_gpr_d[r3], temp, 16); + tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp3); + tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 16); tcg_temp_free(temp); tcg_temp_free(temp2); + tcg_temp_free(temp3); break; case OPC2_32_RR_DVINIT: temp = tcg_temp_new(); -- cgit v1.1 From 00e1754ff1f6294a29e08398a120663eac723216 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Tue, 10 Feb 2015 18:12:31 +0000 Subject: target-tricore: fix RRPW_DEXTR using wrong reg RRPW_DEXTR used r1 for the low part and r2 for the high part. It should be the other way round. This also fixes that the result of the first shift was not saved in a temp and could overwrite registers that were needed for the second shift. Signed-off-by: Bastian Koppelmann --- target-tricore/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 989a047..bbcfee9 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8044,8 +8044,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) tcg_gen_rotli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], const16); } else { temp = tcg_temp_new(); - tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r2], const16); - tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 32 - const16); + tcg_gen_shli_tl(temp, cpu_gpr_d[r1], const16); + tcg_gen_shri_tl(cpu_gpr_d[r3], cpu_gpr_d[r2], 32 - const16); tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], temp); tcg_temp_free(temp); } -- cgit v1.1 From f69c24e4584f2161f90ee7caba38728aa77f937f Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 23 Mar 2015 18:24:42 +0100 Subject: target-tricore: properly fix dvinit_b/h_13 The TriCore documentation was wrong on how to calculate ovf bits for those two instructions, which I confirmed with real hardware (TC1796 chip). An ovf actually happens, if the result (without remainder) does not fit into 8/16 bits. Signed-off-by: Bastian Koppelmann --- target-tricore/op_helper.c | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 2cfa95d..220ec4a 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -1942,29 +1942,19 @@ uint64_t helper_unpack(target_ulong arg1) uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) { uint64_t ret; - int32_t abs_sig_dividend, abs_base_dividend, abs_divisor; - int32_t quotient_sign; + int32_t abs_sig_dividend, abs_divisor; ret = sextract32(r1, 0, 32); ret = ret << 24; - quotient_sign = 0; if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { ret |= 0xffffff; - quotient_sign = 1; } - abs_sig_dividend = abs((int32_t)r1) >> 7; - abs_base_dividend = abs((int32_t)r1) & 0x7f; + abs_sig_dividend = abs((int32_t)r1) >> 8; abs_divisor = abs((int32_t)r2); - /* calc overflow */ - env->PSW_USB_V = 0; - if ((quotient_sign) && (abs_divisor)) { - env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) && - (abs_base_dividend >= abs_divisor)) || - (abs_sig_dividend > abs_divisor)); - } else { - env->PSW_USB_V = (abs_sig_dividend >= abs_divisor); - } + /* calc overflow + ofv if (a/b >= 255) <=> (a/255 >= b) */ + env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; env->PSW_USB_V = env->PSW_USB_V << 31; env->PSW_USB_SV |= env->PSW_USB_V; env->PSW_USB_AV = 0; @@ -1992,29 +1982,19 @@ uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) { uint64_t ret; - int32_t abs_sig_dividend, abs_base_dividend, abs_divisor; - int32_t quotient_sign; + int32_t abs_sig_dividend, abs_divisor; ret = sextract32(r1, 0, 32); ret = ret << 16; - quotient_sign = 0; if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { ret |= 0xffff; - quotient_sign = 1; } - abs_sig_dividend = abs((int32_t)r1) >> 7; - abs_base_dividend = abs((int32_t)r1) & 0x7f; + abs_sig_dividend = abs((int32_t)r1) >> 16; abs_divisor = abs((int32_t)r2); - /* calc overflow */ - env->PSW_USB_V = 0; - if ((quotient_sign) && (abs_divisor)) { - env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) && - (abs_base_dividend >= abs_divisor)) || - (abs_sig_dividend > abs_divisor)); - } else { - env->PSW_USB_V = (abs_sig_dividend >= abs_divisor); - } + /* calc overflow + ofv if (a/b >= 0xffff) <=> (a/0xffff >= b) */ + env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; env->PSW_USB_V = env->PSW_USB_V << 31; env->PSW_USB_SV |= env->PSW_USB_V; env->PSW_USB_AV = 0; -- cgit v1.1