提交 74637406 编写于 作者: A aurel32

target-ppc: convert arithmetic functions to TCG

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

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5590 c046a42c-6fe2-441c-8c8c-71466251a162
上级 8d71247e
......@@ -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))
......
......@@ -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)
{
......
......@@ -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
......
......@@ -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
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册