diff options
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 73bfbc1..e003761 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -5214,8 +5214,11 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, int opc2, int opc3, int ra, int rb, int rt, int Rc) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[ra]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]); + TCGv t0, t1; + + t0 = tcg_temp_local_new(TCG_TYPE_TL); + t1 = tcg_temp_local_new(TCG_TYPE_TL); + switch (opc3 & 0x0D) { case 0x05: /* macchw - macchw. - macchwo - macchwo. */ @@ -5223,13 +5226,17 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */ /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */ /* mulchw - mulchw. */ - gen_op_405_mulchw(); + tcg_gen_ext16s_tl(t0, cpu_gpr[ra]); + tcg_gen_sari_tl(t1, cpu_gpr[rb], 16); + tcg_gen_ext16s_tl(t1, t1); break; case 0x04: /* macchwu - macchwu. - macchwuo - macchwuo. */ /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */ /* mulchwu - mulchwu. */ - gen_op_405_mulchwu(); + tcg_gen_ext16u_tl(t0, cpu_gpr[ra]); + tcg_gen_shri_tl(t1, cpu_gpr[rb], 16); + tcg_gen_ext16u_tl(t1, t1); break; case 0x01: /* machhw - machhw. - machhwo - machhwo. */ @@ -5237,13 +5244,19 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */ /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */ /* mulhhw - mulhhw. */ - gen_op_405_mulhhw(); + tcg_gen_sari_tl(t0, cpu_gpr[ra], 16); + tcg_gen_ext16s_tl(t0, t0); + tcg_gen_sari_tl(t1, cpu_gpr[rb], 16); + tcg_gen_ext16s_tl(t1, t1); break; case 0x00: /* machhwu - machhwu. - machhwuo - machhwuo. */ /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */ /* mulhhwu - mulhhwu. */ - gen_op_405_mulhhwu(); + tcg_gen_shri_tl(t0, cpu_gpr[ra], 16); + tcg_gen_ext16u_tl(t0, t0); + tcg_gen_shri_tl(t1, cpu_gpr[rb], 16); + tcg_gen_ext16u_tl(t1, t1); break; case 0x0D: /* maclhw - maclhw. - maclhwo - maclhwo. */ @@ -5251,43 +5264,70 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */ /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */ /* mullhw - mullhw. */ - gen_op_405_mullhw(); + tcg_gen_ext16s_tl(t0, cpu_gpr[ra]); + tcg_gen_ext16s_tl(t1, cpu_gpr[rb]); break; case 0x0C: /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */ /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */ /* mullhwu - mullhwu. */ - gen_op_405_mullhwu(); + tcg_gen_ext16u_tl(t0, cpu_gpr[ra]); + tcg_gen_ext16u_tl(t1, cpu_gpr[rb]); break; } - if (opc2 & 0x02) { - /* nmultiply-and-accumulate (0x0E) */ - tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); - } if (opc2 & 0x04) { - /* (n)multiply-and-accumulate (0x0C - 0x0E) */ - tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rt]); - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); - gen_op_405_add_T0_T2(); - } - if (opc3 & 0x10) { - /* Check overflow */ - if (opc3 & 0x01) - gen_op_check_addo(); - else - gen_op_405_check_ovu(); - } - if (opc3 & 0x02) { - /* Saturate */ - if (opc3 & 0x01) - gen_op_405_check_sat(); - else - gen_op_405_check_satu(); + /* (n)multiply-and-accumulate (0x0C / 0x0E) */ + tcg_gen_mul_tl(t1, t0, t1); + if (opc2 & 0x02) { + /* nmultiply-and-accumulate (0x0E) */ + tcg_gen_sub_tl(t0, cpu_gpr[rt], t1); + } else { + /* multiply-and-accumulate (0x0C) */ + tcg_gen_add_tl(t0, cpu_gpr[rt], t1); + } + + if (opc3 & 0x12) { + /* Check overflow and/or saturate */ + int l1 = gen_new_label(); + + if (opc3 & 0x10) { + /* Start with XER OV disabled, the most likely case */ + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV)); + } + if (opc3 & 0x01) { + /* Signed */ + tcg_gen_xor_tl(t1, cpu_gpr[rt], t1); + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); + tcg_gen_xor_tl(t1, cpu_gpr[rt], t0); + tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); + if (opc3 & 0x02) { + /* Saturate */ + tcg_gen_sari_tl(t0, cpu_gpr[rt], 31); + tcg_gen_xori_tl(t0, t0, 0x7fffffff); + } + } else { + /* Unsigned */ + tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1); + if (opc3 & 0x02) { + /* Saturate */ + tcg_gen_movi_tl(t0, UINT32_MAX); + } + } + if (opc3 & 0x10) { + /* Check overflow */ + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO)); + } + gen_set_label(l1); + tcg_gen_mov_tl(cpu_gpr[rt], t0); + } + } else { + tcg_gen_mul_tl(cpu_gpr[rt], t0, t1); } - tcg_gen_mov_tl(cpu_gpr[rt], cpu_T[0]); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc) != 0) { /* Update Rc0 */ - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rt]); } } |