Hi Everyone, Please find attached a patch which fixes handling in QEMU PPC e500v1 for efscmp* instructions. This was the cause of over 400 FAILs for this CPU while running GCC testsuite, which have been fixed.
Value for Condition Registers (CR) being set in QEMU was different from the value observed on hardware. I have not managed to find a documentation describing the behaviour of e500 cores for these instructions. However, the behaviour on MPC8548-CDS target was observed by dumping registers to stdout, while running executables from uboot. These instructions are used by GCC only when compiling for te500v1 multilib; hence no effect on other PPC CPUs (603, 7400 etc.) A comparison of GCC v5.2.0 testsuite results summary (number of FAILs) is as follows: CPU = te500v1 without patch: 699 with patch: 193 CPU = e500v2 without patch: 225 with patch: 225 Is this OK to commit? Comments and suggestions are welcome. Thanks, Talha Imran
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c index b67ebca..752c552 100644 --- a/target-ppc/fpu_helper.c +++ b/target-ppc/fpu_helper.c @@ -1400,7 +1400,7 @@ static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2) u1.l = op1; u2.l = op2; - return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0; + return float32_lt(u1.f, u2.f, &env->vec_status) ? 6 : 0; } static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2) @@ -1409,7 +1409,7 @@ static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2) u1.l = op1; u2.l = op2; - return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4; + return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 6; } static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2) @@ -1418,7 +1418,7 @@ static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2) u1.l = op1; u2.l = op2; - return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0; + return float32_eq(u1.f, u2.f, &env->vec_status) ? 6 : 0; } static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2) @@ -1442,7 +1442,7 @@ static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2) #define HELPER_SINGLE_SPE_CMP(name) \ uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ { \ - return e##name(env, op1, op2) << 2; \ + return e##name(env, op1, op2); \ } /* efststlt */ HELPER_SINGLE_SPE_CMP(fststlt);