aboutsummaryrefslogtreecommitdiff
path: root/target-tricore
diff options
context:
space:
mode:
authorBastian Koppelmann <kbastian@mail.uni-paderborn.de>2014-12-12 16:55:34 +0000
committerBastian Koppelmann <kbastian@mail.uni-paderborn.de>2014-12-21 18:35:49 +0000
commit9655b9328a566116c198c52792775a0641d56915 (patch)
treedf2a52e29295cefed48c31b2bb885da26789d8d0 /target-tricore
parent436d63ff3e3f87cda3e8df35827a40093cc17430 (diff)
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 <kbastian@mail.uni-paderborn.de> Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-tricore')
-rw-r--r--target-tricore/helper.h4
-rw-r--r--target-tricore/op_helper.c72
-rw-r--r--target-tricore/translate.c197
3 files changed, 273 insertions, 0 deletions
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;
}
}