target-ppc: convert 405 MAC instructions to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5591 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aurel32 2008-11-01 00:54:23 +00:00
parent 7463740644
commit 182608d44c
4 changed files with 72 additions and 140 deletions

View File

@ -326,34 +326,6 @@ void OPPROTO op_store_fpscr (void)
RETURN();
}
/*** Integer arithmetic ***/
/* add */
void OPPROTO op_check_addo (void)
{
int ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
((uint32_t)T2 ^ (uint32_t)T0)) >> 31;
if (ov) {
env->xer |= (1 << XER_OV) | (1 << XER_SO);
} else {
env->xer &= ~(1 << XER_OV);
}
RETURN();
}
#if defined(TARGET_PPC64)
void OPPROTO op_check_addo_64 (void)
{
int ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
((uint64_t)T2 ^ (uint64_t)T0)) >> 63;
if (ov) {
env->xer |= (1 << XER_OV) | (1 << XER_SO);
} else {
env->xer &= ~(1 << XER_OV);
}
RETURN();
}
#endif
/*** Integer shift ***/
void OPPROTO op_srli_T1 (void)
{
@ -1062,73 +1034,6 @@ void OPPROTO op_602_mfrom (void)
#endif
/* PowerPC 4xx specific micro-ops */
void OPPROTO op_405_add_T0_T2 (void)
{
T0 = (int32_t)T0 + (int32_t)T2;
RETURN();
}
void OPPROTO op_405_mulchw (void)
{
T0 = ((int16_t)T0) * ((int16_t)(T1 >> 16));
RETURN();
}
void OPPROTO op_405_mulchwu (void)
{
T0 = ((uint16_t)T0) * ((uint16_t)(T1 >> 16));
RETURN();
}
void OPPROTO op_405_mulhhw (void)
{
T0 = ((int16_t)(T0 >> 16)) * ((int16_t)(T1 >> 16));
RETURN();
}
void OPPROTO op_405_mulhhwu (void)
{
T0 = ((uint16_t)(T0 >> 16)) * ((uint16_t)(T1 >> 16));
RETURN();
}
void OPPROTO op_405_mullhw (void)
{
T0 = ((int16_t)T0) * ((int16_t)T1);
RETURN();
}
void OPPROTO op_405_mullhwu (void)
{
T0 = ((uint16_t)T0) * ((uint16_t)T1);
RETURN();
}
void OPPROTO op_405_check_sat (void)
{
do_405_check_sat();
RETURN();
}
void OPPROTO op_405_check_ovu (void)
{
if (likely(T0 >= T2)) {
env->xer &= ~(1 << XER_OV);
} else {
env->xer |= (1 << XER_OV) | (1 << XER_SO);
}
RETURN();
}
void OPPROTO op_405_check_satu (void)
{
if (unlikely(T0 < T2)) {
/* Saturate result */
T0 = UINT32_MAX;
}
RETURN();
}
void OPPROTO op_load_dcr (void)
{
do_load_dcr();

View File

@ -1510,18 +1510,6 @@ void do_op_602_mfrom (void)
/*****************************************************************************/
/* Embedded PowerPC specific helpers */
void do_405_check_sat (void)
{
if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
!(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
/* Saturate result */
if (T2 >> 31) {
T0 = INT32_MIN;
} else {
T0 = INT32_MAX;
}
}
}
/* XXX: to be improved to check access rights when in user-mode */
void do_load_dcr (void)

View File

@ -144,7 +144,6 @@ void do_440_tlbwe (int word);
#endif
/* PowerPC 4xx specific helpers */
void do_405_check_sat (void);
void do_load_dcr (void);
void do_store_dcr (void);
#if !defined(CONFIG_USER_ONLY)

View File

@ -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();
/* (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);
}
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();
}
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]);
}
}