Commit 74637406 authored by Aurelien Jarno's avatar Aurelien Jarno
Browse files

target-ppc: convert arithmetic functions to TCG



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

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5590 c046a42c-6fe2-441c-8c8c-71466251a162
parent 8d71247e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -8,6 +8,12 @@ DEF_HELPER(uint32_t, helper_fcmpu, (void))
DEF_HELPER(uint32_t, helper_load_cr, (void))
DEF_HELPER(void, helper_store_cr, (target_ulong, uint32_t))

#if defined(TARGET_PPC64)
DEF_HELPER(uint64_t, helper_mulhd, (uint64_t, uint64_t))
DEF_HELPER(uint64_t, helper_mulhdu, (uint64_t, uint64_t))
DEF_HELPER(uint64_t, helper_mulldo, (uint64_t, uint64_t))
#endif

DEF_HELPER(target_ulong, helper_cntlzw, (target_ulong t))
DEF_HELPER(target_ulong, helper_popcntb, (target_ulong val))
DEF_HELPER(target_ulong, helper_sraw, (target_ulong, target_ulong))
+0 −398
Original line number Diff line number Diff line
@@ -354,404 +354,6 @@ void OPPROTO op_check_addo_64 (void)
}
#endif

/* add carrying */
void OPPROTO op_check_addc (void)
{
    if (likely((uint32_t)T0 >= (uint32_t)T2)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_check_addc_64 (void)
{
    if (likely((uint64_t)T0 >= (uint64_t)T2)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
    RETURN();
}
#endif

/* add extended */
void OPPROTO op_adde (void)
{
    do_adde();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_adde_64 (void)
{
    do_adde_64();
    RETURN();
}
#endif

/* add to minus one extended */
void OPPROTO op_add_me (void)
{
    T0 += xer_ca + (-1);
    if (likely((uint32_t)T1 != 0))
        env->xer |= (1 << XER_CA);
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_add_me_64 (void)
{
    T0 += xer_ca + (-1);
    if (likely((uint64_t)T1 != 0))
        env->xer |= (1 << XER_CA);
    RETURN();
}
#endif

void OPPROTO op_addmeo (void)
{
    do_addmeo();
    RETURN();
}

void OPPROTO op_addmeo_64 (void)
{
    do_addmeo();
    RETURN();
}

/* add to zero extended */
void OPPROTO op_add_ze (void)
{
    T0 += xer_ca;
    RETURN();
}

/* divide word */
void OPPROTO op_divw (void)
{
    if (unlikely(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
                 (int32_t)T1 == 0)) {
        T0 = (int32_t)(UINT32_MAX * ((uint32_t)T0 >> 31));
    } else {
        T0 = (int32_t)T0 / (int32_t)T1;
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_divd (void)
{
    if (unlikely(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
                 (int64_t)T1 == 0)) {
        T0 = (int64_t)(UINT64_MAX * ((uint64_t)T0 >> 63));
    } else {
        T0 = (int64_t)T0 / (int64_t)T1;
    }
    RETURN();
}
#endif

void OPPROTO op_divwo (void)
{
    do_divwo();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_divdo (void)
{
    do_divdo();
    RETURN();
}
#endif

/* divide word unsigned */
void OPPROTO op_divwu (void)
{
    if (unlikely(T1 == 0)) {
        T0 = 0;
    } else {
        T0 = (uint32_t)T0 / (uint32_t)T1;
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_divdu (void)
{
    if (unlikely(T1 == 0)) {
        T0 = 0;
    } else {
        T0 /= T1;
    }
    RETURN();
}
#endif

void OPPROTO op_divwuo (void)
{
    do_divwuo();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_divduo (void)
{
    do_divduo();
    RETURN();
}
#endif

/* multiply high word */
void OPPROTO op_mulhw (void)
{
    T0 = ((int64_t)((int32_t)T0) * (int64_t)((int32_t)T1)) >> 32;
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_mulhd (void)
{
    uint64_t tl, th;

    muls64(&tl, &th, T0, T1);
    T0 = th;
    RETURN();
}
#endif

/* multiply high word unsigned */
void OPPROTO op_mulhwu (void)
{
    T0 = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1) >> 32;
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_mulhdu (void)
{
    uint64_t tl, th;

    mulu64(&tl, &th, T0, T1);
    T0 = th;
    RETURN();
}
#endif

/* multiply low immediate */
void OPPROTO op_mulli (void)
{
    T0 = ((int32_t)T0 * (int32_t)PARAM1);
    RETURN();
}

/* multiply low word */
void OPPROTO op_mullw (void)
{
#if defined(TARGET_PPC64)
    T0 = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1;
#else
    T0 = (int32_t)(T0 * T1);
#endif
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_mulld (void)
{
    T0 *= T1;
    RETURN();
}
#endif

void OPPROTO op_mullwo (void)
{
    do_mullwo();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_mulldo (void)
{
    do_mulldo();
    RETURN();
}
#endif

/* negate */
void OPPROTO op_neg (void)
{
    if (likely(T0 != INT32_MIN)) {
        T0 = -(int32_t)T0;
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_neg_64 (void)
{
    if (likely(T0 != INT64_MIN)) {
        T0 = -(int64_t)T0;
    }
    RETURN();
}
#endif

void OPPROTO op_nego (void)
{
    do_nego();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_nego_64 (void)
{
    do_nego_64();
    RETURN();
}
#endif

/* subtract from carrying */
void OPPROTO op_check_subfc (void)
{
    if (likely((uint32_t)T0 > (uint32_t)T1)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_check_subfc_64 (void)
{
    if (likely((uint64_t)T0 > (uint64_t)T1)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
    RETURN();
}
#endif

/* subtract from extended */
void OPPROTO op_subfe (void)
{
    do_subfe();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfe_64 (void)
{
    do_subfe_64();
    RETURN();
}
#endif

/* subtract from immediate carrying */
void OPPROTO op_subfic (void)
{
    T0 = (int32_t)PARAM1 + ~T0 + 1;
    if ((uint32_t)T0 <= (uint32_t)PARAM1) {
        env->xer |= (1 << XER_CA);
    } else {
        env->xer &= ~(1 << XER_CA);
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfic_64 (void)
{
    T0 = (int64_t)PARAM1 + ~T0 + 1;
    if ((uint64_t)T0 <= (uint64_t)PARAM1) {
        env->xer |= (1 << XER_CA);
    } else {
        env->xer &= ~(1 << XER_CA);
    }
    RETURN();
}
#endif

/* subtract from minus one extended */
void OPPROTO op_subfme (void)
{
    T0 = ~T0 + xer_ca - 1;
    if (likely((uint32_t)T0 != UINT32_MAX))
        env->xer |= (1 << XER_CA);
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfme_64 (void)
{
    T0 = ~T0 + xer_ca - 1;
    if (likely((uint64_t)T0 != UINT64_MAX))
        env->xer |= (1 << XER_CA);
    RETURN();
}
#endif

void OPPROTO op_subfmeo (void)
{
    do_subfmeo();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfmeo_64 (void)
{
    do_subfmeo_64();
    RETURN();
}
#endif

/* subtract from zero extended */
void OPPROTO op_subfze (void)
{
    T1 = ~T0;
    T0 = T1 + xer_ca;
    if ((uint32_t)T0 < (uint32_t)T1) {
        env->xer |= (1 << XER_CA);
    } else {
        env->xer &= ~(1 << XER_CA);
    }
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfze_64 (void)
{
    T1 = ~T0;
    T0 = T1 + xer_ca;
    if ((uint64_t)T0 < (uint64_t)T1) {
        env->xer |= (1 << XER_CA);
    } else {
        env->xer &= ~(1 << XER_CA);
    }
    RETURN();
}
#endif

void OPPROTO op_subfzeo (void)
{
    do_subfzeo();
    RETURN();
}

#if defined(TARGET_PPC64)
void OPPROTO op_subfzeo_64 (void)
{
    do_subfzeo_64();
    RETURN();
}
#endif

/***                             Integer shift                             ***/
void OPPROTO op_srli_T1 (void)
{
+13 −232
Original line number Diff line number Diff line
@@ -113,258 +113,39 @@ void ppc_store_dump_spr (int sprn, target_ulong val)

/*****************************************************************************/
/* Fixed point operations helpers */
void do_adde (void)
{
    T2 = T0;
    T0 += T1 + xer_ca;
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
}

#if defined(TARGET_PPC64)
void do_adde_64 (void)
{
    T2 = T0;
    T0 += T1 + xer_ca;
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
}
#endif

void do_addmeo (void)
{
    int ov;
    T1 = T0;
    T0 += xer_ca + (-1);
    ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint32_t)T1 != 0))
        env->xer |= (1 << XER_CA);
}

#if defined(TARGET_PPC64)
void do_addmeo_64 (void)
{
    int ov;
    T1 = T0;
    T0 += xer_ca + (-1);
    ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint64_t)T1 != 0))
        env->xer |= (1 << XER_CA);
}
#endif

void do_divwo (void)
{
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
                 (int32_t)T1 == 0))) {
        env->xer &= ~(1 << XER_OV);
        T0 = (int32_t)T0 / (int32_t)T1;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
    }
}

#if defined(TARGET_PPC64)
void do_divdo (void)
{
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
                 (int64_t)T1 == 0))) {
        env->xer &= ~(1 << XER_OV);
        T0 = (int64_t)T0 / (int64_t)T1;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
        T0 = UINT64_MAX * ((uint64_t)T0 >> 63);
    }
}
#endif

void do_divwuo (void)
/* multiply high word */
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
{
    if (likely((uint32_t)T1 != 0)) {
        env->xer &= ~(1 << XER_OV);
        T0 = (uint32_t)T0 / (uint32_t)T1;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
        T0 = 0;
    }
}
    uint64_t tl, th;

#if defined(TARGET_PPC64)
void do_divduo (void)
{
    if (likely((uint64_t)T1 != 0)) {
        env->xer &= ~(1 << XER_OV);
        T0 = (uint64_t)T0 / (uint64_t)T1;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
        T0 = 0;
    }
    muls64(&tl, &th, arg1, arg2);
    return th;
}
#endif

void do_mullwo (void)
/* multiply high word unsigned */
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
{
    int64_t res = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1;
    uint64_t tl, th;

    if (likely((int32_t)res == res)) {
        env->xer &= ~(1 << XER_OV);
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    }
    T0 = (int32_t)res;
    mulu64(&tl, &th, arg1, arg2);
    return th;
}

#if defined(TARGET_PPC64)
void do_mulldo (void)
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
{
    int64_t th;
    uint64_t tl;

    muls64(&tl, (uint64_t *)&th, T0, T1);
    T0 = (int64_t)tl;
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
    /* If th != 0 && th != -1, then we had an overflow */
    if (likely((uint64_t)(th + 1) <= 1)) {
        env->xer &= ~(1 << XER_OV);
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    }
}
#endif

void do_nego (void)
{
    if (likely((int32_t)T0 != INT32_MIN)) {
        env->xer &= ~(1 << XER_OV);
        T0 = -(int32_t)T0;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    }
}

#if defined(TARGET_PPC64)
void do_nego_64 (void)
{
    if (likely((int64_t)T0 != INT64_MIN)) {
        env->xer &= ~(1 << XER_OV);
        T0 = -(int64_t)T0;
    } else {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    }
}
#endif

void do_subfe (void)
{
    T0 = T1 + ~T0 + xer_ca;
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
}

#if defined(TARGET_PPC64)
void do_subfe_64 (void)
{
    T0 = T1 + ~T0 + xer_ca;
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
}
#endif

void do_subfmeo (void)
{
    int ov;
    T1 = T0;
    T0 = ~T0 + xer_ca - 1;
    ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint32_t)T1 != UINT32_MAX))
        env->xer |= (1 << XER_CA);
}

#if defined(TARGET_PPC64)
void do_subfmeo_64 (void)
{
    int ov;
    T1 = T0;
    T0 = ~T0 + xer_ca - 1;
    ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint64_t)T1 != UINT64_MAX))
        env->xer |= (1 << XER_CA);
}
#endif

void do_subfzeo (void)
{
    int ov;
    T1 = T0;
    T0 = ~T0 + xer_ca;
    ov = (((uint32_t)~T1 ^ UINT32_MAX) &
          ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
}

#if defined(TARGET_PPC64)
void do_subfzeo_64 (void)
{
    int ov;
    T1 = T0;
    T0 = ~T0 + xer_ca;
    ov = (((uint64_t)~T1 ^  UINT64_MAX) &
          ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
    if (ov) {
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
    } else {
        env->xer &= ~(1 << XER_OV);
    }
    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
        env->xer &= ~(1 << XER_CA);
    } else {
        env->xer |= (1 << XER_CA);
    }
    return (int64_t)tl;
}
#endif

+0 −32
Original line number Diff line number Diff line
@@ -61,38 +61,6 @@ void do_store_fpscr (uint32_t mask);
target_ulong ppc_load_dump_spr (int sprn);
void ppc_store_dump_spr (int sprn, target_ulong val);

/* Integer arithmetic helpers */
void do_adde (void);
void do_addmeo (void);
void do_divwo (void);
void do_divwuo (void);
void do_mullwo (void);
void do_nego (void);
void do_subfe (void);
void do_subfmeo (void);
void do_subfzeo (void);
void do_cntlzw (void);
#if defined(TARGET_PPC64)
void do_cntlzd (void);
#endif
void do_sraw (void);
#if defined(TARGET_PPC64)
void do_adde_64 (void);
void do_addmeo_64 (void);
void do_divdo (void);
void do_divduo (void);
void do_mulldo (void);
void do_nego_64 (void);
void do_subfe_64 (void);
void do_subfmeo_64 (void);
void do_subfzeo_64 (void);
void do_srad (void);
#endif
void do_popcntb (void);
#if defined(TARGET_PPC64)
void do_popcntb_64 (void);
#endif

/* Floating-point arithmetic helpers */
void do_compute_fprf (int set_class);
#ifdef CONFIG_SOFTFLOAT
+523 −351

File changed.

Preview size limit exceeded, changes collapsed.