Optimize PowerPC overflow flag computation in most useful cases.
Use the same routines to check overflow for addo, subfo and PowerPC 405 multiply and add cases. Fix carry reset in addme(o) and subfme(o) cases. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3574 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
a76dc35afd
commit
c3e10c7b43
@ -191,6 +191,12 @@ void OPPROTO op_move_T2_T0 (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_moven_T2_T0 (void)
|
||||
{
|
||||
T2 = ~T0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Generate exceptions */
|
||||
void OPPROTO op_raise_exception_err (void)
|
||||
{
|
||||
@ -847,26 +853,18 @@ void OPPROTO op_add (void)
|
||||
|
||||
void OPPROTO op_check_addo (void)
|
||||
{
|
||||
if (likely(!(((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
|
||||
((uint32_t)T2 ^ (uint32_t)T0) & (1UL << 31)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
|
||||
((uint32_t)T2 ^ (uint32_t)T0)) >> 31;
|
||||
xer_so |= xer_ov;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
void OPPROTO op_check_addo_64 (void)
|
||||
{
|
||||
if (likely(!(((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
|
||||
((uint64_t)T2 ^ (uint64_t)T0) & (1ULL << 63)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
|
||||
((uint64_t)T2 ^ (uint64_t)T0)) >> 63;
|
||||
xer_so |= xer_ov;
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
@ -922,6 +920,8 @@ void OPPROTO op_add_me (void)
|
||||
T0 += xer_ca + (-1);
|
||||
if (likely((uint32_t)T1 != 0))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
@ -931,6 +931,8 @@ void OPPROTO op_add_me_64 (void)
|
||||
T0 += xer_ca + (-1);
|
||||
if (likely((uint64_t)T1 != 0))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
@ -1142,32 +1144,6 @@ void OPPROTO op_subf (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_check_subfo (void)
|
||||
{
|
||||
if (likely(!(((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
|
||||
((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
void OPPROTO op_check_subfo_64 (void)
|
||||
{
|
||||
if (likely(!(((uint64_t)(~T2) ^ (uint64_t)T1 ^ UINT64_MAX) &
|
||||
((uint64_t)(~T2) ^ (uint64_t)T0) & (1ULL << 63)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* subtract from carrying */
|
||||
void OPPROTO op_check_subfc (void)
|
||||
{
|
||||
@ -1235,8 +1211,10 @@ void OPPROTO op_subfic_64 (void)
|
||||
void OPPROTO op_subfme (void)
|
||||
{
|
||||
T0 = ~T0 + xer_ca - 1;
|
||||
if (likely((uint32_t)T0 != (uint32_t)-1))
|
||||
if (likely((uint32_t)T0 != UINT32_MAX))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
@ -1244,8 +1222,10 @@ void OPPROTO op_subfme (void)
|
||||
void OPPROTO op_subfme_64 (void)
|
||||
{
|
||||
T0 = ~T0 + xer_ca - 1;
|
||||
if (likely((uint64_t)T0 != (uint64_t)-1))
|
||||
if (likely((uint64_t)T0 != UINT64_MAX))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
@ -2528,12 +2508,6 @@ void OPPROTO op_405_mullhwu (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_405_check_ov (void)
|
||||
{
|
||||
do_405_check_ov();
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_405_check_sat (void)
|
||||
{
|
||||
do_405_check_sat();
|
||||
|
@ -151,15 +151,12 @@ void do_addmeo (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 += xer_ca + (-1);
|
||||
if (likely(!((uint32_t)T1 &
|
||||
((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
|
||||
xer_so |= xer_ov;
|
||||
if (likely(T1 != 0))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
@ -167,15 +164,12 @@ void do_addmeo_64 (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 += xer_ca + (-1);
|
||||
if (likely(!((uint64_t)T1 &
|
||||
((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
|
||||
xer_so |= xer_ov;
|
||||
if (likely(T1 != 0))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -316,15 +310,12 @@ void do_subfmeo (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 = ~T0 + xer_ca - 1;
|
||||
if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
|
||||
(1UL << 31)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
|
||||
xer_so |= xer_ov;
|
||||
if (likely((uint32_t)T1 != UINT32_MAX))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
@ -332,15 +323,12 @@ void do_subfmeo_64 (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 = ~T0 + xer_ca - 1;
|
||||
if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
|
||||
(1ULL << 63)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
|
||||
xer_so |= xer_ov;
|
||||
if (likely((uint64_t)T1 != UINT64_MAX))
|
||||
xer_ca = 1;
|
||||
else
|
||||
xer_ca = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -348,13 +336,9 @@ void do_subfzeo (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 = ~T0 + xer_ca;
|
||||
if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
|
||||
((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
|
||||
((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
|
||||
xer_so |= xer_ov;
|
||||
if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
|
||||
xer_ca = 0;
|
||||
} else {
|
||||
@ -367,13 +351,9 @@ void do_subfzeo_64 (void)
|
||||
{
|
||||
T1 = T0;
|
||||
T0 = ~T0 + xer_ca;
|
||||
if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
|
||||
((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
xer_ov = (((uint64_t)~T1 ^ UINT64_MAX) &
|
||||
((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
|
||||
xer_so |= xer_ov;
|
||||
if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
|
||||
xer_ca = 0;
|
||||
} else {
|
||||
@ -1755,17 +1735,6 @@ void do_op_602_mfrom (void)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Embedded PowerPC specific helpers */
|
||||
void do_405_check_ov (void)
|
||||
{
|
||||
if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
|
||||
!(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
|
||||
xer_ov = 0;
|
||||
} else {
|
||||
xer_ov = 1;
|
||||
xer_so = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void do_405_check_sat (void)
|
||||
{
|
||||
if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
|
||||
|
@ -182,7 +182,6 @@ void do_440_tlbwe (int word);
|
||||
#endif
|
||||
|
||||
/* PowerPC 4xx specific helpers */
|
||||
void do_405_check_ov (void);
|
||||
void do_405_check_sat (void);
|
||||
void do_load_dcr (void);
|
||||
void do_store_dcr (void);
|
||||
|
@ -888,17 +888,17 @@ GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
|
||||
/* subf subf. subfo subfo. */
|
||||
static always_inline void gen_op_subfo (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subf();
|
||||
gen_op_check_subfo();
|
||||
gen_op_check_addo();
|
||||
}
|
||||
#if defined(TARGET_PPC64)
|
||||
#define gen_op_subf_64 gen_op_subf
|
||||
static always_inline void gen_op_subfo_64 (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subf();
|
||||
gen_op_check_subfo_64();
|
||||
gen_op_check_addo_64();
|
||||
}
|
||||
#endif
|
||||
GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
|
||||
@ -910,10 +910,10 @@ static always_inline void gen_op_subfc (void)
|
||||
}
|
||||
static always_inline void gen_op_subfco (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subf();
|
||||
gen_op_check_subfc();
|
||||
gen_op_check_subfo();
|
||||
gen_op_check_addo();
|
||||
}
|
||||
#if defined(TARGET_PPC64)
|
||||
static always_inline void gen_op_subfc_64 (void)
|
||||
@ -923,27 +923,27 @@ static always_inline void gen_op_subfc_64 (void)
|
||||
}
|
||||
static always_inline void gen_op_subfco_64 (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subf();
|
||||
gen_op_check_subfc_64();
|
||||
gen_op_check_subfo_64();
|
||||
gen_op_check_addo_64();
|
||||
}
|
||||
#endif
|
||||
GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
|
||||
/* subfe subfe. subfeo subfeo. */
|
||||
static always_inline void gen_op_subfeo (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subfe();
|
||||
gen_op_check_subfo();
|
||||
gen_op_check_addo();
|
||||
}
|
||||
#if defined(TARGET_PPC64)
|
||||
#define gen_op_subfe_64 gen_op_subfe
|
||||
static always_inline void gen_op_subfeo_64 (void)
|
||||
{
|
||||
gen_op_move_T2_T0();
|
||||
gen_op_moven_T2_T0();
|
||||
gen_op_subfe_64();
|
||||
gen_op_check_subfo_64();
|
||||
gen_op_check_addo_64();
|
||||
}
|
||||
#endif
|
||||
GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
|
||||
@ -5116,7 +5116,7 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
|
||||
if (opc3 & 0x10) {
|
||||
/* Check overflow */
|
||||
if (opc3 & 0x01)
|
||||
gen_op_405_check_ov();
|
||||
gen_op_check_addo();
|
||||
else
|
||||
gen_op_405_check_ovu();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user