From 781b717c5049f42d45d31fd47617f3129c07541c Mon Sep 17 00:00:00 2001 From: Alex Zuepke Date: Fri, 12 Dec 2014 15:10:27 +0100 Subject: [PATCH 01/13] target-tricore: fix offset masking in BOL format Signed-off-by: Alex Zuepke Reviewed-by: Bastian Koppelmann Signed-off-by: Bastian Koppelmann --- target-tricore/tricore-opcodes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 0a9122cfb9..70ac5ffc7d 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -114,7 +114,7 @@ /* BOL Format */ #define MASK_OP_BOL_OFF16(op) ((MASK_BITS_SHIFT(op, 16, 21) + \ (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \ - (MASK_BITS_SHIFT(op, 22, 27) >> 10)) + (MASK_BITS_SHIFT(op, 22, 27) << 10)) #define MASK_OP_BOL_OFF16_SEXT(op) ((MASK_BITS_SHIFT(op, 16, 21) + \ (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \ (MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10)) From af715d980271a1c8ea9596bf9147b5421a49e01a Mon Sep 17 00:00:00 2001 From: Alex Zuepke Date: Fri, 12 Dec 2014 15:10:28 +0100 Subject: [PATCH 02/13] target-tricore: typo in BOL format Signed-off-by: Alex Zuepke Reviewed-by: Bastian Koppelmann Signed-off-by: Bastian Koppelmann --- target-tricore/translate.c | 4 ++-- target-tricore/tricore-opcodes.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 65abf453f0..c1322238a7 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3203,7 +3203,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1) tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL); tcg_temp_free(temp); break; - case OPC1_32_BOL_LD_W_LONFOFF: + case OPC1_32_BOL_LD_W_LONGOFF: temp = tcg_temp_new(); tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address); tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL); @@ -3930,7 +3930,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) break; /* BOL-format */ case OPC1_32_BOL_LD_A_LONGOFF: - case OPC1_32_BOL_LD_W_LONFOFF: + case OPC1_32_BOL_LD_W_LONGOFF: case OPC1_32_BOL_LEA_LONGOFF: case OPC1_32_BOL_ST_W_LONGOFF: case OPC1_32_BOL_ST_A_LONGOFF: diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 70ac5ffc7d..7aa6aed4d3 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -447,7 +447,7 @@ enum { OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR = 0x69, /* BOL Format */ OPC1_32_BOL_LD_A_LONGOFF = 0x99, - OPC1_32_BOL_LD_W_LONFOFF = 0x19, + OPC1_32_BOL_LD_W_LONGOFF = 0x19, OPC1_32_BOL_LEA_LONGOFF = 0xd9, OPC1_32_BOL_ST_W_LONGOFF = 0x59, OPC1_32_BOL_ST_A_LONGOFF = 0xb5, /* 1.6 only */ From 4b5b44357651b7563790e246be64bc55f4d90d47 Mon Sep 17 00:00:00 2001 From: Alex Zuepke Date: Fri, 12 Dec 2014 15:10:29 +0100 Subject: [PATCH 03/13] target-tricore: add missing 64-bit MOV in RLC format Signed-off-by: Alex Zuepke Reviewed-by: Bastian Koppelmann Signed-off-by: Bastian Koppelmann --- target-tricore/translate.c | 12 ++++++++++++ target-tricore/tricore-opcodes.h | 1 + 2 files changed, 13 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index c1322238a7..e3eeedba95 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3781,6 +3781,17 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx, case OPC1_32_RLC_MOV: tcg_gen_movi_tl(cpu_gpr_d[r2], const16); break; + case OPC1_32_RLC_MOV_64: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + if ((r2 & 0x1) != 0) { + /* TODO: raise OPD trap */ + } + tcg_gen_movi_tl(cpu_gpr_d[r2], const16); + tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15); + } else { + /* TODO: raise illegal opcode trap */ + } + break; case OPC1_32_RLC_MOV_U: const16 = MASK_OP_RLC_CONST16(ctx->opcode); tcg_gen_movi_tl(cpu_gpr_d[r2], const16); @@ -4021,6 +4032,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPC1_32_RLC_ADDIH_A: case OPC1_32_RLC_MFCR: case OPC1_32_RLC_MOV: + case OPC1_32_RLC_MOV_64: case OPC1_32_RLC_MOV_U: case OPC1_32_RLC_MOV_H: case OPC1_32_RLC_MOVH_A: diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 7aa6aed4d3..a76a7e4c45 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -487,6 +487,7 @@ enum { OPC1_32_RLC_ADDIH_A = 0x11, OPC1_32_RLC_MFCR = 0x4d, OPC1_32_RLC_MOV = 0x3b, + OPC1_32_RLC_MOV_64 = 0xfb, /* 1.6 only */ OPC1_32_RLC_MOV_U = 0xbb, OPC1_32_RLC_MOV_H = 0x7b, OPC1_32_RLC_MOVH_A = 0x91, From 45820fccaf731a2fec5d0cb5416f944104e89373 Mon Sep 17 00:00:00 2001 From: Alex Zuepke Date: Fri, 19 Dec 2014 12:34:34 +0100 Subject: [PATCH 04/13] target-tricore: pretty-print register dump and show more status registers Now using psw_read() to retrieve the status bits correctly. Signed-off-by: Alex Zuepke Reviewed-by: Bastian Koppelmann Signed-off-by: Bastian Koppelmann --- target-tricore/translate.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index e3eeedba95..3d8734650b 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -85,22 +85,31 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, { TriCoreCPU *cpu = TRICORE_CPU(cs); CPUTriCoreState *env = &cpu->env; + uint32_t psw; int i; - cpu_fprintf(f, "PC=%08x\n", env->PC); - for (i = 0; i < 16; ++i) { - if ((i & 3) == 0) { - cpu_fprintf(f, "GPR A%02d:", i); - } - cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]); - } - for (i = 0; i < 16; ++i) { - if ((i & 3) == 0) { - cpu_fprintf(f, "GPR D%02d:", i); - } - cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]); - } + psw = psw_read(env); + cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC); + cpu_fprintf(f, " PSW: " TARGET_FMT_lx, psw); + cpu_fprintf(f, " ICR: " TARGET_FMT_lx, env->ICR); + cpu_fprintf(f, "\nPCXI: " TARGET_FMT_lx, env->PCXI); + cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX); + cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX); + + for (i = 0; i < 16; ++i) { + if ((i & 3) == 0) { + cpu_fprintf(f, "\nGPR A%02d:", i); + } + cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]); + } + for (i = 0; i < 16; ++i) { + if ((i & 3) == 0) { + cpu_fprintf(f, "\nGPR D%02d:", i); + } + cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]); + } + cpu_fprintf(f, "\n"); } /* From 7f13420ec000ad7644b65ea1a32b5674ad0cd204 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 15 Dec 2014 21:36:31 +0000 Subject: [PATCH 05/13] target-tricore: Fix mask handling JNZ.T being 7 bit long The mask is actually 7 bit long, instead of 6, so the expression checking for JNZ.T is always false. Let's make the mask 1 bit wider. 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 3d8734650b..8f9e13e085 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3828,8 +3828,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) op1 = MASK_OP_MAJOR(ctx->opcode); - /* handle JNZ.T opcode only being 6 bit long */ - if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) { + /* handle JNZ.T opcode only being 7 bit long */ + if (unlikely((op1 & 0x7f) == OPCM_32_BRN_JTT)) { op1 = OPCM_32_BRN_JTT; } From e4e39176305adff59b05a02a072ae1369d0a2274 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 27 Nov 2014 13:45:09 +0000 Subject: [PATCH 06/13] target-tricore: Change SSOV/SUOV makro name to SSOV32/SUOV32 Those makros are exclusively used for 32 bit arithmetics and won't work for 16 bit with two halfwords. So lets get rid of the len parameter and make them always use 32 bit. Now no token pasting is needed anymore and they can be regular functions. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/op_helper.c | 132 ++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 75 deletions(-) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 4da76ff232..f1a8d16d30 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -56,118 +56,111 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off) return reg - index + new_index; } -#define SSOV(env, ret, arg, len) do { \ - int64_t max_pos = INT##len ##_MAX; \ - int64_t max_neg = INT##len ##_MIN; \ - if (arg > max_pos) { \ - env->PSW_USB_V = (1 << 31); \ - env->PSW_USB_SV = (1 << 31); \ - ret = (target_ulong)max_pos; \ - } else { \ - if (arg < max_neg) { \ - env->PSW_USB_V = (1 << 31); \ - env->PSW_USB_SV = (1 << 31); \ - ret = (target_ulong)max_neg; \ - } else { \ - env->PSW_USB_V = 0; \ - ret = (target_ulong)arg; \ - } \ - } \ - env->PSW_USB_AV = arg ^ arg * 2u; \ - env->PSW_USB_SAV |= env->PSW_USB_AV; \ -} while (0) +static uint32_t ssov32(CPUTriCoreState *env, int64_t arg) +{ + uint32_t ret; + int64_t max_pos = INT32_MAX; + int64_t max_neg = INT32_MIN; + if (arg > max_pos) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + ret = (target_ulong)max_pos; + } else { + if (arg < max_neg) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + ret = (target_ulong)max_neg; + } else { + env->PSW_USB_V = 0; + ret = (target_ulong)arg; + } + } + env->PSW_USB_AV = arg ^ arg * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} -#define SUOV(env, ret, arg, len) do { \ - int64_t max_pos = UINT##len ##_MAX; \ - if (arg > max_pos) { \ - env->PSW_USB_V = (1 << 31); \ - env->PSW_USB_SV = (1 << 31); \ - ret = (target_ulong)max_pos; \ - } else { \ - if (arg < 0) { \ - env->PSW_USB_V = (1 << 31); \ - env->PSW_USB_SV = (1 << 31); \ - ret = 0; \ - } else { \ - env->PSW_USB_V = 0; \ - ret = (target_ulong)arg; \ - } \ - } \ - env->PSW_USB_AV = arg ^ arg * 2u; \ - env->PSW_USB_SAV |= env->PSW_USB_AV; \ -} while (0) +static uint32_t suov32(CPUTriCoreState *env, int64_t arg) +{ + uint32_t ret; + int64_t max_pos = UINT32_MAX; + if (arg > max_pos) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + ret = (target_ulong)max_pos; + } else { + if (arg < 0) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + ret = 0; + } else { + env->PSW_USB_V = 0; + ret = (target_ulong)arg; + } + } + env->PSW_USB_AV = arg ^ arg * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t result = t1 + t2; - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 + t2; - SUOV(env, ret, result, 32); - return ret; + return suov32(env, result); } target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t result = t1 - t2; - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 - t2; - SUOV(env, ret, result, 32); - return ret; + return suov32(env, result); } target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t result = t1 * t2; - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 * t2; - SUOV(env, ret, result, 32); - return ret; + return suov32(env, result); } target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int32_t t2 = sextract64(r2, 0, 6); int64_t result; @@ -178,14 +171,12 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, } else { result = t1 >> -t2; } - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t result; @@ -195,36 +186,31 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, } else { result = t2 - t1; } - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t t3 = sextract64(r3, 0, 32); int64_t result; result = t2 + (t1 * t3); - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { - target_ulong ret; uint64_t t1 = extract64(r1, 0, 32); uint64_t t2 = extract64(r2, 0, 32); uint64_t t3 = extract64(r3, 0, 32); int64_t result; result = t2 + (t1 * t3); - SUOV(env, ret, result, 32); - return ret; + return suov32(env, result); } uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, @@ -286,29 +272,25 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { - target_ulong ret; int64_t t1 = sextract64(r1, 0, 32); int64_t t2 = sextract64(r2, 0, 32); int64_t t3 = sextract64(r3, 0, 32); int64_t result; result = t2 - (t1 * t3); - SSOV(env, ret, result, 32); - return ret; + return ssov32(env, result); } target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { - target_ulong ret; int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t t3 = extract64(r3, 0, 32); int64_t result; result = t2 - (t1 * t3); - SUOV(env, ret, result, 32); - return ret; + return suov32(env, result); } uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, From d5de7839d78b08c7bd14b03dac0413699b90da67 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 27 Nov 2014 14:30:33 +0000 Subject: [PATCH 07/13] target-tricore: Add instructions of RR opcode format, that have 0xb as the first opcode 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 Reviewed-by: Richard Henderson --- target-tricore/helper.h | 32 ++ target-tricore/op_helper.c | 525 +++++++++++++++++++++++++++++++ target-tricore/translate.c | 383 ++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 4 +- 4 files changed, 942 insertions(+), 2 deletions(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 6c07bd7f28..df87c0d2d7 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_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) +DEF_HELPER_FLAGS_2(eqany_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(lt_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(lt_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(lt_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(lt_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, 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 f1a8d16d30..26e01ed1b9 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -103,6 +103,66 @@ static uint32_t suov32(CPUTriCoreState *env, int64_t arg) return ret; } +static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) +{ + 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; + return (hw0 & 0xffff) | (hw1 << 16); +} + +static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) +{ + 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; + return (hw0 & 0xffff) | (hw1 << 16); +} target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) @@ -113,6 +173,16 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, return ssov32(env, result); } +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); + return ssov16(env, ret_hw0, ret_hw1); +} + target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -122,6 +192,16 @@ target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, return suov32(env, result); } +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); + return suov16(env, ret_hw0, ret_hw1); +} + target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -131,6 +211,16 @@ target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, return ssov32(env, result); } +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); + return ssov16(env, ret_hw0, ret_hw1); +} + target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -140,6 +230,16 @@ target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, return suov32(env, result); } +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); + return suov16(env, ret_hw0, ret_hw1); +} + target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -174,6 +274,26 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, return ssov32(env, result); } +uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1) +{ + target_ulong result; + result = ((int32_t)r1 >= 0) ? r1 : (0 - r1); + return ssov32(env, 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); + + return ssov16(env, ret_h0, ret_h1); +} + target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2) { @@ -189,6 +309,31 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, return ssov32(env, result); } +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; + } + + return ssov16(env, ret_h0, ret_h1); +} + target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, target_ulong r2, target_ulong r3) { @@ -348,6 +493,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 8f9e13e085..7111b52dd7 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -728,6 +728,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(); @@ -1217,6 +1273,13 @@ 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) +{ + tcg_gen_setcond_tl(cond, ret, r1, r2); + tcg_gen_neg_tl(ret, ret); +} + static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con) { TCGv b0 = tcg_temp_new(); @@ -3817,6 +3880,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; @@ -4048,6 +4427,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 a76a7e4c45..17d9ad950b 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1034,8 +1034,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, From 0b79a78169d813d11ad32f103e7a2c64c32bd705 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 28 Nov 2014 17:07:26 +0000 Subject: [PATCH 08/13] target-tricore: Add instructions of RR opcode format, that have 0xf as the first opcode Add instructions of RR opcode format, that have 0xf as the first opcode. Add helper functions: * clo/z/s: Counts leading ones/zeros/signs. * clo/z/s_h: Count leading ones/zeros/signs in two haflwords. * sh/_h: Shifts one/two word/hwords. * sha/_h: Shifts one/two word/hwords arithmeticly. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/helper.h | 12 +++ target-tricore/op_helper.c | 160 +++++++++++++++++++++++++++++++++++++ target-tricore/translate.c | 78 ++++++++++++++++++ 3 files changed, 250 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index df87c0d2d7..3b85c1a5ec 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -64,6 +64,18 @@ DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +/* count leading ... */ +DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32) +/* sh */ +DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_3(sha, i32, env, i32, i32) +DEF_HELPER_2(sha_h, 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 26e01ed1b9..98f28d5623 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -873,6 +873,166 @@ EXTREMA_H_B(min, <) #undef EXTREMA_H_B +uint32_t helper_clo(target_ulong r1) +{ + return clo32(r1); +} + +uint32_t helper_clo_h(target_ulong r1) +{ + uint32_t ret_hw0 = extract32(r1, 0, 16); + uint32_t ret_hw1 = extract32(r1, 16, 16); + + ret_hw0 = clo32(ret_hw0 << 16); + ret_hw1 = clo32(ret_hw1 << 16); + + if (ret_hw0 > 16) { + ret_hw0 = 16; + } + if (ret_hw1 > 16) { + ret_hw1 = 16; + } + + return ret_hw0 | (ret_hw1 << 16); +} + +uint32_t helper_clz(target_ulong r1) +{ + return clz32(r1); +} + +uint32_t helper_clz_h(target_ulong r1) +{ + uint32_t ret_hw0 = extract32(r1, 0, 16); + uint32_t ret_hw1 = extract32(r1, 16, 16); + + ret_hw0 = clz32(ret_hw0 << 16); + ret_hw1 = clz32(ret_hw1 << 16); + + if (ret_hw0 > 16) { + ret_hw0 = 16; + } + if (ret_hw1 > 16) { + ret_hw1 = 16; + } + + return ret_hw0 | (ret_hw1 << 16); +} + +uint32_t helper_cls(target_ulong r1) +{ + return clrsb32(r1); +} + +uint32_t helper_cls_h(target_ulong r1) +{ + uint32_t ret_hw0 = extract32(r1, 0, 16); + uint32_t ret_hw1 = extract32(r1, 16, 16); + + ret_hw0 = clrsb32(ret_hw0 << 16); + ret_hw1 = clrsb32(ret_hw1 << 16); + + if (ret_hw0 > 15) { + ret_hw0 = 15; + } + if (ret_hw1 > 15) { + ret_hw1 = 15; + } + + return ret_hw0 | (ret_hw1 << 16); +} + +uint32_t helper_sh(target_ulong r1, target_ulong r2) +{ + int32_t shift_count = sextract32(r2, 0, 6); + + if (shift_count == -32) { + return 0; + } else if (shift_count < 0) { + return r1 >> -shift_count; + } else { + return r1 << shift_count; + } +} + +uint32_t helper_sh_h(target_ulong r1, target_ulong r2) +{ + int32_t ret_hw0, ret_hw1; + int32_t shift_count; + + shift_count = sextract32(r2, 0, 5); + + if (shift_count == -16) { + return 0; + } else if (shift_count < 0) { + ret_hw0 = extract32(r1, 0, 16) >> -shift_count; + ret_hw1 = extract32(r1, 16, 16) >> -shift_count; + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); + } else { + ret_hw0 = extract32(r1, 0, 16) << shift_count; + ret_hw1 = extract32(r1, 16, 16) << shift_count; + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); + } +} + +uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2) +{ + int32_t shift_count; + int64_t result, t1; + uint32_t ret; + + shift_count = sextract32(r2, 0, 6); + t1 = sextract32(r1, 0, 32); + + if (shift_count == 0) { + env->PSW_USB_C = env->PSW_USB_V = 0; + ret = r1; + } else if (shift_count == -32) { + env->PSW_USB_C = r1; + env->PSW_USB_V = 0; + ret = t1 >> 31; + } else if (shift_count > 0) { + result = t1 << shift_count; + /* calc carry */ + env->PSW_USB_C = ((result & 0xffffffff00000000) != 0); + /* calc v */ + env->PSW_USB_V = (((result > 0x7fffffffLL) || + (result < -0x80000000LL)) << 31); + /* calc sv */ + env->PSW_USB_SV |= env->PSW_USB_V; + ret = (uint32_t)result; + } else { + env->PSW_USB_V = 0; + env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1)); + ret = t1 >> -shift_count; + } + + env->PSW_USB_AV = ret ^ ret * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + + return ret; +} + +uint32_t helper_sha_h(target_ulong r1, target_ulong r2) +{ + int32_t shift_count; + int32_t ret_hw0, ret_hw1; + + shift_count = sextract32(r2, 0, 5); + + if (shift_count == 0) { + return r1; + } else if (shift_count < 0) { + ret_hw0 = sextract32(r1, 0, 16) >> -shift_count; + ret_hw1 = sextract32(r1, 16, 16) >> -shift_count; + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); + } else { + ret_hw0 = sextract32(r1, 0, 16) << shift_count; + ret_hw1 = sextract32(r1, 16, 16) << shift_count; + return (ret_hw0 & 0xffff) | (ret_hw1 << 16); + } +} + /* 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 7111b52dd7..16fb448d9c 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -4196,6 +4196,81 @@ static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx) } } +static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r3, r2, r1; + TCGv temp; + + r3 = MASK_OP_RR_D(ctx->opcode); + r2 = MASK_OP_RR_S2(ctx->opcode); + r1 = MASK_OP_RR_S1(ctx->opcode); + + temp = tcg_temp_new(); + op2 = MASK_OP_RR_OP2(ctx->opcode); + + switch (op2) { + case OPC2_32_RR_AND: + tcg_gen_and_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ANDN: + tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_CLO: + gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_CLO_H: + gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_CLS: + gen_helper_cls(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_CLS_H: + gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_CLZ: + gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_CLZ_H: + gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_NAND: + tcg_gen_nand_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_NOR: + tcg_gen_nor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_OR: + tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_ORN: + tcg_gen_orc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH: + gen_helper_sh(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SH_H: + gen_helper_sh_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SHA: + gen_helper_sha(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SHA_H: + gen_helper_sha_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_SHAS: + gen_shas(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_XNOR: + tcg_gen_eqv_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_XOR: + tcg_gen_xor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + } + tcg_temp_free(temp); +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -4431,6 +4506,9 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR_ACCUMULATOR: decode_rr_accumulator(env, ctx); break; + case OPCM_32_RR_LOGICAL_SHIFT: + decode_rr_logical_shift(env, ctx); + break; } } From f2f1585f60df656dc1755727cc66a0c3c8dd627d Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Tue, 2 Dec 2014 17:15:09 +0000 Subject: [PATCH 09/13] target-tricore: Add instructions of RR opcode format, that have 0x1 as the first opcode Add instructions of RR opcode format, that have 0x1 as the first opcode. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 97 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 16fb448d9c..92d6a19ade 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -4271,6 +4271,97 @@ static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx) tcg_temp_free(temp); } +static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2, n; + int r1, r2, r3; + TCGv temp; + + op2 = MASK_OP_RR_OP2(ctx->opcode); + r3 = MASK_OP_RR_D(ctx->opcode); + r2 = MASK_OP_RR_S2(ctx->opcode); + r1 = MASK_OP_RR_S1(ctx->opcode); + n = MASK_OP_RR_N(ctx->opcode); + + switch (op2) { + case OPC2_32_RR_ADD_A: + tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]); + break; + case OPC2_32_RR_ADDSC_A: + temp = tcg_temp_new(); + tcg_gen_shli_tl(temp, cpu_gpr_d[r1], n); + tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r2], temp); + tcg_temp_free(temp); + break; + case OPC2_32_RR_ADDSC_AT: + temp = tcg_temp_new(); + tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 3); + tcg_gen_add_tl(temp, cpu_gpr_a[r2], temp); + tcg_gen_andi_tl(cpu_gpr_a[r3], temp, 0xFFFFFFFC); + tcg_temp_free(temp); + break; + case OPC2_32_RR_EQ_A: + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1], + cpu_gpr_a[r2]); + break; + case OPC2_32_RR_EQZ: + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1], 0); + break; + case OPC2_32_RR_GE_A: + tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_a[r1], + cpu_gpr_a[r2]); + break; + case OPC2_32_RR_LT_A: + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_a[r1], + cpu_gpr_a[r2]); + break; + case OPC2_32_RR_MOV_A: + tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_MOV_AA: + tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_a[r2]); + break; + case OPC2_32_RR_MOV_D: + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_a[r2]); + break; + case OPC2_32_RR_NE_A: + tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1], + cpu_gpr_a[r2]); + break; + case OPC2_32_RR_NEZ_A: + tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1], 0); + break; + case OPC2_32_RR_SUB_A: + tcg_gen_sub_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]); + break; + } +} + +static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1; + + op2 = MASK_OP_RR_OP2(ctx->opcode); + r1 = MASK_OP_RR_S1(ctx->opcode); + + switch (op2) { + case OPC2_32_RR_JI: + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); + break; + case OPC2_32_RR_JLI: + tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); + break; + case OPC2_32_RR_CALLI: + gen_helper_1arg(call, ctx->next_pc); + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); + break; + } + tcg_gen_exit_tb(0); + ctx->bstate = BS_BRANCH; +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -4509,6 +4600,12 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR_LOGICAL_SHIFT: decode_rr_logical_shift(env, ctx); break; + case OPCM_32_RR_ADRESS: + decode_rr_address(env, ctx); + break; + case OPCM_32_RR_IDIRECT: + decode_rr_idirect(env, ctx); + break; } } From e2bed107c6d1dbde564029ac2bca450cdb3f596e Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Tue, 2 Dec 2014 17:22:27 +0000 Subject: [PATCH 10/13] target-tricore: Add instructions of RR opcode format, that have 0x4b as the first opcode Add instructions of RR opcode format, that have 0x4b as the first opcode. Add helper functions: * parity: Calculates the parity bits for every byte of a 32 int. * bmerge/bsplit: Merges two regs into one bitwise/Splits one reg into two bitwise. * unpack: unpack a IEEE 754 single precision floating point number as exponent and mantissa. * dvinit_b_13/131: (ISA v1.3/v1.31)Prepare operands for a divide operation, where the quotient result is guaranteed to fit into 8 bit. * dvinit_h_13/131: (ISA v1.3/v1.31)Prepare operands for a divide operation, where the quotient result is guaranteed to fit into 16 bit. OPCM_32_RR_FLOAT -> OPCM_32_RR_DIVIDE. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/helper.h | 11 ++ target-tricore/op_helper.c | 195 +++++++++++++++++++++++++++++++ target-tricore/translate.c | 183 +++++++++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 2 +- 4 files changed, 390 insertions(+), 1 deletion(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 3b85c1a5ec..0294512651 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -76,6 +76,17 @@ DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_3(sha, i32, env, i32, i32) DEF_HELPER_2(sha_h, i32, i32, i32) +/* merge/split/parity */ +DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32) +DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32) +/* float */ +DEF_HELPER_1(unpack, i64, i32) +/* dvinit */ +DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) +DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) +DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32) +DEF_HELPER_3(dvinit_h_131, i64, env, 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 98f28d5623..63d2d56a9d 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -1033,6 +1033,201 @@ uint32_t helper_sha_h(target_ulong r1, target_ulong r2) } } +uint32_t helper_bmerge(target_ulong r1, target_ulong r2) +{ + uint32_t i, ret; + + ret = 0; + for (i = 0; i < 16; i++) { + ret |= (r1 & 1) << (2 * i + 1); + ret |= (r2 & 1) << (2 * i); + r1 = r1 >> 1; + r2 = r2 >> 1; + } + return ret; +} + +uint64_t helper_bsplit(uint32_t r1) +{ + int32_t i; + uint64_t ret; + + ret = 0; + for (i = 0; i < 32; i = i + 2) { + /* even */ + ret |= (r1 & 1) << (i/2); + r1 = r1 >> 1; + /* odd */ + ret |= (uint64_t)(r1 & 1) << (i/2 + 32); + r1 = r1 >> 1; + } + return ret; +} + +uint32_t helper_parity(target_ulong r1) +{ + uint32_t ret; + uint32_t nOnes, i; + + ret = 0; + nOnes = 0; + for (i = 0; i < 8; i++) { + ret ^= (r1 & 1); + r1 = r1 >> 1; + } + /* second byte */ + nOnes = 0; + for (i = 0; i < 8; i++) { + nOnes ^= (r1 & 1); + r1 = r1 >> 1; + } + ret |= nOnes << 8; + /* third byte */ + nOnes = 0; + for (i = 0; i < 8; i++) { + nOnes ^= (r1 & 1); + r1 = r1 >> 1; + } + ret |= nOnes << 16; + /* fourth byte */ + nOnes = 0; + for (i = 0; i < 8; i++) { + nOnes ^= (r1 & 1); + r1 = r1 >> 1; + } + ret |= nOnes << 24; + + return ret; +} + +uint64_t helper_unpack(target_ulong arg1) +{ + int32_t fp_exp = extract32(arg1, 23, 8); + int32_t fp_frac = extract32(arg1, 0, 23); + uint64_t ret; + int32_t int_exp, int_mant; + + if (fp_exp == 255) { + int_exp = 255; + int_mant = (fp_frac << 7); + } else if ((fp_exp == 0) && (fp_frac == 0)) { + int_exp = -127; + int_mant = 0; + } else if ((fp_exp == 0) && (fp_frac != 0)) { + int_exp = -126; + int_mant = (fp_frac << 7); + } else { + int_exp = fp_exp - 127; + int_mant = (fp_frac << 7); + int_mant |= (1 << 30); + } + ret = int_exp; + ret = ret << 32; + ret |= int_mant; + + return ret; +} + +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; + + 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(r1) >> 7; + abs_base_dividend = abs(r1) & 0x7f; + abs_divisor = abs(r1); + /* 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); + } + env->PSW_USB_V = env->PSW_USB_V << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + + return ret; +} + +uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint64_t ret = sextract32(r1, 0, 32); + + ret = ret << 24; + if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { + ret |= 0xffffff; + } + /* calc overflow */ + env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80))); + env->PSW_USB_V = env->PSW_USB_V << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + + return ret; +} + +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; + + 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(r1) >> 7; + abs_base_dividend = abs(r1) & 0x7f; + abs_divisor = abs(r1); + /* 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); + } + env->PSW_USB_V = env->PSW_USB_V << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + + return ret; +} + +uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint64_t ret = sextract32(r1, 0, 32); + + ret = ret << 16; + if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { + ret |= 0xffff; + } + /* calc overflow */ + env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000))); + env->PSW_USB_V = env->PSW_USB_V << 31; + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + + return ret; +} + /* 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 92d6a19ade..1708456281 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -1356,6 +1356,56 @@ static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos) tcg_temp_free(temp2); } +static inline void gen_bsplit(TCGv rl, TCGv rh, TCGv r1) +{ + TCGv_i64 temp = tcg_temp_new_i64(); + + gen_helper_bsplit(temp, r1); + tcg_gen_extr_i64_i32(rl, rh, temp); + + tcg_temp_free_i64(temp); +} + +static inline void gen_unpack(TCGv rl, TCGv rh, TCGv r1) +{ + TCGv_i64 temp = tcg_temp_new_i64(); + + gen_helper_unpack(temp, r1); + tcg_gen_extr_i64_i32(rl, rh, temp); + + tcg_temp_free_i64(temp); +} + +static inline void +gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2) +{ + TCGv_i64 ret = tcg_temp_new_i64(); + + if (!tricore_feature(env, TRICORE_FEATURE_131)) { + gen_helper_dvinit_b_13(ret, cpu_env, r1, r2); + } else { + gen_helper_dvinit_b_131(ret, cpu_env, r1, r2); + } + tcg_gen_extr_i64_i32(rl, rh, ret); + + tcg_temp_free_i64(ret); +} + +static inline void +gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2) +{ + TCGv_i64 ret = tcg_temp_new_i64(); + + if (!tricore_feature(env, TRICORE_FEATURE_131)) { + gen_helper_dvinit_h_13(ret, cpu_env, r1, r2); + } else { + gen_helper_dvinit_h_131(ret, cpu_env, r1, r2); + } + tcg_gen_extr_i64_i32(rl, rh, ret); + + tcg_temp_free_i64(ret); +} + /* helpers for generating program flow micro-ops */ static inline void gen_save_pc(target_ulong pc) @@ -4362,6 +4412,136 @@ static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx) ctx->bstate = BS_BRANCH; } +static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int r1, r2, r3; + + TCGv temp, temp2; + + op2 = MASK_OP_RR_OP2(ctx->opcode); + r3 = MASK_OP_RR_D(ctx->opcode); + r2 = MASK_OP_RR_S2(ctx->opcode); + r1 = MASK_OP_RR_S1(ctx->opcode); + + switch (op2) { + case OPC2_32_RR_BMERGE: + gen_helper_bmerge(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + break; + case OPC2_32_RR_BSPLIT: + gen_bsplit(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_DVINIT_B: + gen_dvinit_b(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_DVINIT_BU: + temp = tcg_temp_new(); + temp2 = tcg_temp_new(); + /* 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]); + /* 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_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]); + tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2); + } else { + /* overflow = (D[b] == 0) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0); + } + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* 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_temp_free(temp); + tcg_temp_free(temp2); + break; + case OPC2_32_RR_DVINIT_H: + gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + break; + case OPC2_32_RR_DVINIT_HU: + temp = tcg_temp_new(); + temp2 = tcg_temp_new(); + /* 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]); + /* 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_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]); + tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2); + } else { + /* overflow = (D[b] == 0) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0); + } + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* 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_temp_free(temp); + tcg_temp_free(temp2); + break; + case OPC2_32_RR_DVINIT: + temp = tcg_temp_new(); + temp2 = tcg_temp_new(); + /* overflow = ((D[b] == 0) || + ((D[b] == 0xFFFFFFFF) && (D[a] == 0x80000000))) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, temp, cpu_gpr_d[r2], 0xffffffff); + tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r1], 0x80000000); + tcg_gen_and_tl(temp, temp, temp2); + tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r2], 0); + tcg_gen_or_tl(cpu_PSW_V, temp, temp2); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* sv */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* reset av */ + tcg_gen_movi_tl(cpu_PSW_AV, 0); + /* write result */ + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); + /* sign extend to high reg */ + tcg_gen_sari_tl(cpu_gpr_d[r3+1], cpu_gpr_d[r1], 31); + tcg_temp_free(temp); + tcg_temp_free(temp2); + break; + case OPC2_32_RR_DVINIT_U: + /* overflow = (D[b] == 0) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0); + tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); + /* sv */ + tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); + /* reset av */ + tcg_gen_movi_tl(cpu_PSW_AV, 0); + /* write result */ + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); + /* zero extend to high reg*/ + tcg_gen_movi_tl(cpu_gpr_d[r3+1], 0); + break; + case OPC2_32_RR_PARITY: + gen_helper_parity(cpu_gpr_d[r3], cpu_gpr_d[r1]); + break; + case OPC2_32_RR_UNPACK: + gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); + break; + } +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -4606,6 +4786,9 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR_IDIRECT: decode_rr_idirect(env, ctx); break; + case OPCM_32_RR_DIVIDE: + decode_rr_divide(env, ctx); + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 17d9ad950b..d66f879a39 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -496,7 +496,7 @@ enum { OPCM_32_RR_LOGICAL_SHIFT = 0x0f, OPCM_32_RR_ACCUMULATOR = 0x0b, OPCM_32_RR_ADRESS = 0x01, - OPCM_32_RR_FLOAT = 0x4b, + OPCM_32_RR_DIVIDE = 0x4b, OPCM_32_RR_IDIRECT = 0x2d, /* RR1 Format */ OPCM_32_RR1_MUL = 0xb3, From b5fd8fa34594da327e2965a8c3b5dddf21f862ff Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 5 Dec 2014 14:37:17 +0000 Subject: [PATCH 11/13] target-tricore: Add missing 1.6 insn of BOL opcode format Some of the 1.6 ISA instructions were still missing. So let's add them. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 49 +++++++++++++++++++++++++++++++- target-tricore/tricore-opcodes.h | 6 ++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 1708456281..ecb2399ccd 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3344,8 +3344,49 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1) case OPC1_32_BOL_ST_W_LONGOFF: gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL); break; + case OPC1_32_BOL_LD_B_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_LD_BU_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_LD_H_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_LD_HU_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_ST_B_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB); + } else { + /* raise illegal opcode trap */ + } + break; + case OPC1_32_BOL_ST_H_LONGOFF: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW); + } else { + /* raise illegal opcode trap */ + } + break; } - } /* RC format */ @@ -4679,6 +4720,12 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPC1_32_BOL_LEA_LONGOFF: case OPC1_32_BOL_ST_W_LONGOFF: case OPC1_32_BOL_ST_A_LONGOFF: + case OPC1_32_BOL_LD_B_LONGOFF: + case OPC1_32_BOL_LD_BU_LONGOFF: + case OPC1_32_BOL_LD_H_LONGOFF: + case OPC1_32_BOL_LD_HU_LONGOFF: + case OPC1_32_BOL_ST_B_LONGOFF: + case OPC1_32_BOL_ST_H_LONGOFF: decode_bol_opc(env, ctx, op1); break; /* BRC Format */ diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index d66f879a39..afc22883e0 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -451,6 +451,12 @@ enum { OPC1_32_BOL_LEA_LONGOFF = 0xd9, OPC1_32_BOL_ST_W_LONGOFF = 0x59, OPC1_32_BOL_ST_A_LONGOFF = 0xb5, /* 1.6 only */ + OPC1_32_BOL_LD_B_LONGOFF = 0x79, /* 1.6 only */ + OPC1_32_BOL_LD_BU_LONGOFF = 0x39, /* 1.6 only */ + OPC1_32_BOL_LD_H_LONGOFF = 0xc9, /* 1.6 only */ + OPC1_32_BOL_LD_HU_LONGOFF = 0xb9, /* 1.6 only */ + OPC1_32_BOL_ST_B_LONGOFF = 0xe9, /* 1.6 only */ + OPC1_32_BOL_ST_H_LONGOFF = 0xf9, /* 1.6 only */ /* BRC Format */ OPCM_32_BRC_EQ_NEQ = 0xdf, OPCM_32_BRC_GE = 0xff, From 436d63ff3e3f87cda3e8df35827a40093cc17430 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 3 Dec 2014 17:40:21 +0000 Subject: [PATCH 12/13] target-tricore: Fix MFCR/MTCR insn and B format offset. Fix gen_mtcr using wrong register. Fix gen_mtcr/mfcr using sign extended offsets. Fix B format insn using not sign extendend offsets. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 6 ++++-- target-tricore/tricore-opcodes.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index ecb2399ccd..bd35c299cf 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3939,6 +3939,7 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx, tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16); break; case OPC1_32_RLC_MFCR: + const16 = MASK_OP_RLC_CONST16(ctx->opcode); gen_mfcr(env, cpu_gpr_d[r2], const16); break; case OPC1_32_RLC_MOV: @@ -3966,7 +3967,8 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx, tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16); break; case OPC1_32_RLC_MTCR: - gen_mtcr(env, ctx, cpu_gpr_d[r2], const16); + const16 = MASK_OP_RLC_CONST16(ctx->opcode); + gen_mtcr(env, ctx, cpu_gpr_d[r1], const16); break; } } @@ -4670,7 +4672,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPC1_32_B_JA: case OPC1_32_B_JL: case OPC1_32_B_JLA: - address = MASK_OP_B_DISP24(ctx->opcode); + address = MASK_OP_B_DISP24_SEXT(ctx->opcode); gen_compute_branch(ctx, op1, 0, 0, 0, address); break; /* Bit-format */ diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index afc22883e0..919063e422 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -94,6 +94,8 @@ /* B Format */ #define MASK_OP_B_DISP24(op) (MASK_BITS_SHIFT(op, 16, 31) + \ (MASK_BITS_SHIFT(op, 8, 15) << 16)) +#define MASK_OP_B_DISP24_SEXT(op) (MASK_BITS_SHIFT(op, 16, 31) + \ + (MASK_BITS_SHIFT_SEXT(op, 8, 15) << 16)) /* BIT Format */ #define MASK_OP_BIT_D(op) MASK_BITS_SHIFT(op, 28, 31) #define MASK_OP_BIT_POS2(op) MASK_BITS_SHIFT(op, 23, 27) From 9655b9328a566116c198c52792775a0641d56915 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Fri, 12 Dec 2014 16:55:34 +0000 Subject: [PATCH 13/13] target-tricore: Add instructions of RR1 opcode format, that have 0xb3 as first opcode Add instructions of RR1 opcode format, that have 0xb3 as first opcode. Add helper functions mulh, mulmh and mulrh, that compute multiplication, with multiprecision (mulmh) or rounding (mulrh) of 4 halfwords, being either low or high parts of two 32 bit regs. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/helper.h | 4 + target-tricore/op_helper.c | 72 ++++++++++++++ target-tricore/translate.c | 197 +++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 0294512651..068dc7b422 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -87,6 +87,10 @@ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32) +/* mulh */ +DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) +DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) +DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, 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 63d2d56a9d..13e27291c1 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -1228,6 +1228,78 @@ uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) return ret; } +uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, + uint32_t arg10, uint32_t arg11, uint32_t n) +{ + uint64_t ret; + uint32_t result0, result1; + + int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && + ((arg10 & 0xffff) == 0x8000) && (n == 1); + int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && + ((arg11 & 0xffff) == 0x8000) && (n == 1); + if (sc1) { + result1 = 0x7fffffff; + } else { + result1 = (((uint32_t)(arg00 * arg10)) << n); + } + if (sc0) { + result0 = 0x7fffffff; + } else { + result0 = (((uint32_t)(arg01 * arg11)) << n); + } + ret = (((uint64_t)result1 << 32)) | result0; + return ret; +} + +uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01, + uint32_t arg10, uint32_t arg11, uint32_t n) +{ + uint64_t ret; + int64_t result0, result1; + + int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && + ((arg10 & 0xffff) == 0x8000) && (n == 1); + int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && + ((arg11 & 0xffff) == 0x8000) && (n == 1); + + if (sc1) { + result1 = 0x7fffffff; + } else { + result1 = (((int32_t)arg00 * (int32_t)arg10) << n); + } + if (sc0) { + result0 = 0x7fffffff; + } else { + result0 = (((int32_t)arg01 * (int32_t)arg11) << n); + } + ret = (result1 + result0); + ret = ret << 16; + return ret; +} +uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01, + uint32_t arg10, uint32_t arg11, uint32_t n) +{ + uint32_t result0, result1; + + int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && + ((arg10 & 0xffff) == 0x8000) && (n == 1); + int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && + ((arg11 & 0xffff) == 0x8000) && (n == 1); + + if (sc1) { + result1 = 0x7fffffff; + } else { + result1 = ((arg00 * arg10) << n) + 0x8000; + } + if (sc0) { + result0 = 0x7fffffff; + } else { + result0 = ((arg01 * arg11) << n) + 0x8000; + } + return (result1 & 0xffff0000) | (result0 >> 16); +} + /* 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 bd35c299cf..dbcf87e383 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -124,6 +124,64 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, tcg_temp_free_i32(helper_tmp); \ } while (0) +#define GEN_HELPER_LL(name, ret, arg0, arg1, n) do { \ + TCGv arg00 = tcg_temp_new(); \ + TCGv arg01 = tcg_temp_new(); \ + TCGv arg11 = tcg_temp_new(); \ + tcg_gen_sari_tl(arg00, arg0, 16); \ + tcg_gen_ext16s_tl(arg01, arg0); \ + tcg_gen_ext16s_tl(arg11, arg1); \ + gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \ + tcg_temp_free(arg00); \ + tcg_temp_free(arg01); \ + tcg_temp_free(arg11); \ +} while (0) + +#define GEN_HELPER_LU(name, ret, arg0, arg1, n) do { \ + TCGv arg00 = tcg_temp_new(); \ + TCGv arg01 = tcg_temp_new(); \ + TCGv arg10 = tcg_temp_new(); \ + TCGv arg11 = tcg_temp_new(); \ + tcg_gen_sari_tl(arg00, arg0, 16); \ + tcg_gen_ext16s_tl(arg01, arg0); \ + tcg_gen_sari_tl(arg11, arg1, 16); \ + tcg_gen_ext16s_tl(arg10, arg1); \ + gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \ + tcg_temp_free(arg00); \ + tcg_temp_free(arg01); \ + tcg_temp_free(arg10); \ + tcg_temp_free(arg11); \ +} while (0) + +#define GEN_HELPER_UL(name, ret, arg0, arg1, n) do { \ + TCGv arg00 = tcg_temp_new(); \ + TCGv arg01 = tcg_temp_new(); \ + TCGv arg10 = tcg_temp_new(); \ + TCGv arg11 = tcg_temp_new(); \ + tcg_gen_sari_tl(arg00, arg0, 16); \ + tcg_gen_ext16s_tl(arg01, arg0); \ + tcg_gen_sari_tl(arg10, arg1, 16); \ + tcg_gen_ext16s_tl(arg11, arg1); \ + gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \ + tcg_temp_free(arg00); \ + tcg_temp_free(arg01); \ + tcg_temp_free(arg10); \ + tcg_temp_free(arg11); \ +} while (0) + +#define GEN_HELPER_UU(name, ret, arg0, arg1, n) do { \ + TCGv arg00 = tcg_temp_new(); \ + TCGv arg01 = tcg_temp_new(); \ + TCGv arg11 = tcg_temp_new(); \ + tcg_gen_sari_tl(arg01, arg0, 16); \ + tcg_gen_ext16s_tl(arg00, arg0); \ + tcg_gen_sari_tl(arg11, arg1, 16); \ + gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \ + tcg_temp_free(arg00); \ + tcg_temp_free(arg01); \ + tcg_temp_free(arg11); \ +} while (0) + #define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF)) #define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \ ((offset & 0x0fffff) << 1)) @@ -1406,6 +1464,36 @@ gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2) tcg_temp_free_i64(ret); } +static void gen_calc_usb_mul_h(TCGv arg_low, TCGv arg_high) +{ + TCGv temp = tcg_temp_new(); + /* calc AV bit */ + tcg_gen_add_tl(temp, arg_low, arg_low); + tcg_gen_xor_tl(temp, temp, arg_low); + tcg_gen_add_tl(cpu_PSW_AV, arg_high, arg_high); + tcg_gen_xor_tl(cpu_PSW_AV, cpu_PSW_AV, arg_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_gen_movi_tl(cpu_PSW_V, 0); + tcg_temp_free(temp); +} + +static void gen_calc_usb_mulr_h(TCGv arg) +{ + TCGv temp = tcg_temp_new(); + /* calc AV bit */ + tcg_gen_add_tl(temp, arg, arg); + tcg_gen_xor_tl(temp, temp, arg); + tcg_gen_shli_tl(cpu_PSW_AV, temp, 16); + 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); + /* clear V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + tcg_temp_free(temp); +} + /* helpers for generating program flow micro-ops */ static inline void gen_save_pc(target_ulong pc) @@ -4585,6 +4673,111 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) } } +/* RR1 Format */ +static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + + int r1, r2, r3; + TCGv n; + TCGv_i64 temp64; + + r1 = MASK_OP_RR1_S1(ctx->opcode); + r2 = MASK_OP_RR1_S2(ctx->opcode); + r3 = MASK_OP_RR1_D(ctx->opcode); + n = tcg_const_i32(MASK_OP_RR1_N(ctx->opcode)); + op2 = MASK_OP_RR1_OP2(ctx->opcode); + + switch (op2) { + case OPC2_32_RR1_MUL_H_32_LL: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_LL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MUL_H_32_LU: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_LU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MUL_H_32_UL: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_UL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MUL_H_32_UU: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_UU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MULM_H_64_LL: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_LL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + /* reset V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* reset AV bit */ + tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MULM_H_64_LU: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_LU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + /* reset V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* reset AV bit */ + tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MULM_H_64_UL: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_UL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + /* reset V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* reset AV bit */ + tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V); + tcg_temp_free_i64(temp64); + break; + case OPC2_32_RR1_MULM_H_64_UU: + temp64 = tcg_temp_new_i64(); + GEN_HELPER_UU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n); + tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64); + /* reset V bit */ + tcg_gen_movi_tl(cpu_PSW_V, 0); + /* reset AV bit */ + tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V); + tcg_temp_free_i64(temp64); + + break; + case OPC2_32_RR1_MULR_H_16_LL: + GEN_HELPER_LL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n); + gen_calc_usb_mulr_h(cpu_gpr_d[r3]); + break; + case OPC2_32_RR1_MULR_H_16_LU: + GEN_HELPER_LU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n); + gen_calc_usb_mulr_h(cpu_gpr_d[r3]); + break; + case OPC2_32_RR1_MULR_H_16_UL: + GEN_HELPER_UL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n); + gen_calc_usb_mulr_h(cpu_gpr_d[r3]); + break; + case OPC2_32_RR1_MULR_H_16_UU: + GEN_HELPER_UU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n); + gen_calc_usb_mulr_h(cpu_gpr_d[r3]); + break; + } + tcg_temp_free(n); +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -4838,6 +5031,10 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR_DIVIDE: decode_rr_divide(env, ctx); break; +/* RR1 Format */ + case OPCM_32_RR1_MUL: + decode_rr1_mul(env, ctx); + break; } }