summaryrefslogtreecommitdiff
path: root/target-tricore/translate.c
diff options
context:
space:
mode:
authorBastian Koppelmann <kbastian@mail.uni-paderborn.de>2015-02-25 11:55:52 +0000
committerBastian Koppelmann <kbastian@mail.uni-paderborn.de>2015-03-16 15:44:48 +0000
commit068fac77c81b5d227903d0b7ecd108edff4eb0eb (patch)
tree52042b0430e1bfa0f9f41bc1652c0645985167ca /target-tricore/translate.c
parent62e47b2e6d17020b78a676e086bf98cfeba595b7 (diff)
downloadqemu-068fac77c81b5d227903d0b7ecd108edff4eb0eb.tar.gz
target-tricore: Add instructions of RRR1 opcode format, which have 0xe3 as first opcode
Add helpers helper_subadr_h/_ssov which subs one halfword and adds one halfword, rounds / and saturates each half word independently. Add microcode helper functions: * gen_msubad_h/ads_h: multiply two halfwords left justified and sub from the first one word and add the second one word / and saturate each resulting word independetly. * gen_msubadm_h/adms_h: multiply two halfwords in q-format left justified and sub from the first one word and add to the second one word / and saturate each resulting word independetly. * gen_msubadr32_h/32s_h: multiply two halfwords in q-format left justified and sub from the first one word and add to the second one word, round both results / and saturate each resulting word independetly. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Diffstat (limited to 'target-tricore/translate.c')
-rw-r--r--target-tricore/translate.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 01890b9203..525b236b5b 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -2171,6 +2171,206 @@ gen_msubs64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
tcg_temp_free(temp);
}
+static inline void
+gen_msubad_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
+ TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv temp2 = tcg_temp_new();
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_extr_i64_i32(temp, temp2, temp64);
+ gen_addsub64_h(ret_low, ret_high, r1_low, r1_high, temp, temp2,
+ tcg_gen_add_tl, tcg_gen_sub_tl);
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ tcg_temp_free_i64(temp64);
+}
+
+static inline void
+gen_msubadm_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
+ TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+ TCGv_i64 temp64_2 = tcg_temp_new_i64();
+ TCGv_i64 temp64_3 = tcg_temp_new_i64();
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_concat_i32_i64(temp64_3, r1_low, r1_high);
+ tcg_gen_sari_i64(temp64_2, temp64, 32); /* high */
+ tcg_gen_ext32s_i64(temp64, temp64); /* low */
+ tcg_gen_sub_i64(temp64, temp64_2, temp64);
+ tcg_gen_shli_i64(temp64, temp64, 16);
+
+ gen_sub64_d(temp64_2, temp64_3, temp64);
+ /* write back result */
+ tcg_gen_extr_i64_i32(ret_low, ret_high, temp64_2);
+
+ tcg_temp_free(temp);
+ tcg_temp_free_i64(temp64);
+ tcg_temp_free_i64(temp64_2);
+ tcg_temp_free_i64(temp64_3);
+}
+
+static inline void
+gen_msubadr32_h(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv temp2 = tcg_temp_new();
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_andi_tl(temp2, r1, 0xffff0000);
+ tcg_gen_shli_tl(temp, r1, 16);
+ gen_helper_subadr_h(ret, cpu_env, temp64, temp, temp2);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ tcg_temp_free_i64(temp64);
+}
+
+static inline void
+gen_msubads_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
+ TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv temp2 = tcg_temp_new();
+ TCGv temp3 = tcg_temp_new();
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_extr_i64_i32(temp, temp2, temp64);
+ gen_adds(ret_low, r1_low, temp);
+ tcg_gen_mov_tl(temp, cpu_PSW_V);
+ tcg_gen_mov_tl(temp3, cpu_PSW_AV);
+ gen_subs(ret_high, r1_high, temp2);
+ /* combine v bits */
+ tcg_gen_or_tl(cpu_PSW_V, cpu_PSW_V, temp);
+ /* combine av bits */
+ tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp3);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ tcg_temp_free(temp3);
+ tcg_temp_free_i64(temp64);
+}
+
+static inline void
+gen_msubadms_h(TCGv ret_low, TCGv ret_high, TCGv r1_low, TCGv r1_high, TCGv r2,
+ TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+ TCGv_i64 temp64_2 = tcg_temp_new_i64();
+
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_sari_i64(temp64_2, temp64, 32); /* high */
+ tcg_gen_ext32s_i64(temp64, temp64); /* low */
+ tcg_gen_sub_i64(temp64, temp64_2, temp64);
+ tcg_gen_shli_i64(temp64, temp64, 16);
+ tcg_gen_concat_i32_i64(temp64_2, r1_low, r1_high);
+
+ gen_helper_sub64_ssov(temp64, cpu_env, temp64_2, temp64);
+ tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
+
+ tcg_temp_free(temp);
+ tcg_temp_free_i64(temp64);
+ tcg_temp_free_i64(temp64_2);
+}
+
+static inline void
+gen_msubadr32s_h(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n, uint32_t mode)
+{
+ TCGv temp = tcg_const_i32(n);
+ TCGv temp2 = tcg_temp_new();
+ TCGv_i64 temp64 = tcg_temp_new_i64();
+ switch (mode) {
+ case MODE_LL:
+ GEN_HELPER_LL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_LU:
+ GEN_HELPER_LU(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UL:
+ GEN_HELPER_UL(mul_h, temp64, r2, r3, temp);
+ break;
+ case MODE_UU:
+ GEN_HELPER_UU(mul_h, temp64, r2, r3, temp);
+ break;
+ }
+ tcg_gen_andi_tl(temp2, r1, 0xffff0000);
+ tcg_gen_shli_tl(temp, r1, 16);
+ gen_helper_subadr_h_ssov(ret, cpu_env, temp64, temp, temp2);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ tcg_temp_free_i64(temp64);
+}
+
static inline void gen_abs(TCGv ret, TCGv r1)
{
TCGv temp = tcg_temp_new();
@@ -7259,6 +7459,130 @@ static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
tcg_temp_free(temp2);
}
+static void decode_rrr1_msubad_h(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ uint32_t r1, r2, r3, r4, n;
+
+ op2 = MASK_OP_RRR1_OP2(ctx->opcode);
+ r1 = MASK_OP_RRR1_S1(ctx->opcode);
+ r2 = MASK_OP_RRR1_S2(ctx->opcode);
+ r3 = MASK_OP_RRR1_S3(ctx->opcode);
+ r4 = MASK_OP_RRR1_D(ctx->opcode);
+ n = MASK_OP_RRR1_N(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RRR1_MSUBAD_H_32_LL:
+ gen_msubad_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2], n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBAD_H_32_LU:
+ gen_msubad_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2], n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBAD_H_32_UL:
+ gen_msubad_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2], n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBAD_H_32_UU:
+ gen_msubad_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2], n, MODE_UU);
+ break;
+ case OPC2_32_RRR1_MSUBADS_H_32_LL:
+ gen_msubads_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBADS_H_32_LU:
+ gen_msubads_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBADS_H_32_UL:
+ gen_msubads_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBADS_H_32_UU:
+ gen_msubads_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UU);
+ break;
+ case OPC2_32_RRR1_MSUBADM_H_64_LL:
+ gen_msubadm_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBADM_H_64_LU:
+ gen_msubadm_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBADM_H_64_UL:
+ gen_msubadm_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBADM_H_64_UU:
+ gen_msubadm_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UU);
+ break;
+ case OPC2_32_RRR1_MSUBADMS_H_64_LL:
+ gen_msubadms_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBADMS_H_64_LU:
+ gen_msubadms_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBADMS_H_64_UL:
+ gen_msubadms_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBADMS_H_64_UU:
+ gen_msubadms_h(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
+ cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
+ n, MODE_UU);
+ break;
+ case OPC2_32_RRR1_MSUBADR_H_16_LL:
+ gen_msubadr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBADR_H_16_LU:
+ gen_msubadr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBADR_H_16_UL:
+ gen_msubadr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBADR_H_16_UU:
+ gen_msubadr32_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_UU);
+ break;
+ case OPC2_32_RRR1_MSUBADRS_H_16_LL:
+ gen_msubadr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_LL);
+ break;
+ case OPC2_32_RRR1_MSUBADRS_H_16_LU:
+ gen_msubadr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_LU);
+ break;
+ case OPC2_32_RRR1_MSUBADRS_H_16_UL:
+ gen_msubadr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_UL);
+ break;
+ case OPC2_32_RRR1_MSUBADRS_H_16_UU:
+ gen_msubadr32s_h(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], n, MODE_UU);
+ break;
+ }
+}
+
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
{
int op1;
@@ -7571,6 +7895,9 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPCM_32_RRR1_MSUB_Q:
decode_rrr1_msubq_h(env, ctx);
break;
+ case OPCM_32_RRR1_MSUBAD_H:
+ decode_rrr1_msubad_h(env, ctx);
+ break;
}
}