Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-25 Thread Tom Musta

On 10/24/2013 5:10 PM, Peter Maydell wrote:

Can't you use the min and max softfloat functions? Those are
there specifically because the corner cases mean you can't
implement them using the comparisons. (For instance for
the example you quote of max(-0.0, +0.0) they return +0.0
as you require.)


I tried this but didn't have much luck getting results to match
the P7 hardware.  Unfortunately, I don't recall the details.
Let me try this approach again.






Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-25 Thread Peter Maydell
On 25 October 2013 14:52, Tom Musta tommu...@gmail.com wrote:
 On 10/24/2013 5:10 PM, Peter Maydell wrote:

 Can't you use the min and max softfloat functions? Those are
 there specifically because the corner cases mean you can't
 implement them using the comparisons. (For instance for
 the example you quote of max(-0.0, +0.0) they return +0.0
 as you require.)

 I tried this but didn't have much luck getting results to match
 the P7 hardware.  Unfortunately, I don't recall the details.
 Let me try this approach again.

The functions are supposed to match the IEEE mandated min/max
behaviour, and I tested the ARM instructions that use them,
so unless the PPC chip designers have gone rather off-piste
they ought to work :-) (It can happen, though, IIRC x86 has
some rather weird non-IEEE min/max insns.)

-- PMM



[Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-24 Thread Tom Musta

This patch adds the VSX floating point maximum and minimum
instructions:

  - xsmaxdp, xvmaxdp, xvmaxsp
  - xsmindp, xvmindp, xvminsp

Because of the Power ISA definitions of maximum and minimum
on various boundary cases, the standard softfloat comparison
routines (e.g. float64_lt) do not work as well as one might
think.  Therefore specific routines for comparing 64 and 32
bit floating point numbers are implemented in the PowerPC
helper code.

Signed-off-by: Tom Musta tommu...@gmail.com
---
 target-ppc/fpu_helper.c |  162 +++
 target-ppc/helper.h |6 ++
 target-ppc/translate.c  |   12 
 3 files changed, 180 insertions(+), 0 deletions(-)

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 0373913..29b27ce 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -2323,3 +2323,165 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) 
 \

 VSX_SCALAR_CMP(xscmpodp, 1)
 VSX_SCALAR_CMP(xscmpudp, 0)
+
+#define float64_snan_to_qnan(x) ((x) | 0x0008ul)
+
+static int compare_float64(float64 a, float64 b)
+{
+uint64_t asgn = a  0x8000ul;
+uint64_t bsgn = b  0x8000ul;
+
+if (asgn != bsgn) {
+return asgn ? -1 : 1;
+}
+
+uint64_t aexp = (a  0x7FF0ul)  (64-12);
+uint64_t bexp = (b  0x7FF0ul)  (64-12);
+
+if (aexp  bexp) {
+return asgn ? 1 : -1;
+} else if (aexp  bexp) {
+return asgn ? -1 : 1;
+} else {
+uint64_t afrac = a  0x000Ful;
+uint64_t bfrac = b  0x000Ful;
+
+if (afrac  bfrac) {
+return asgn ? 1 : -1;
+} else if (afrac  bfrac) {
+return asgn ? -1 : 1;
+} else {
+return 0;
+}
+}
+}
+
+#define float32_snan_to_qnan(x) ((x) | 0x0040)
+
+static int compare_float32(float32 a, float32 b)
+{
+uint64_t asgn = a  0x8000;
+uint64_t bsgn = b  0x8000;
+
+if (asgn != bsgn) {
+return asgn ? -1 : 1;
+}
+
+uint64_t aexp = (a  0x7FC0)  (32-9);
+uint64_t bexp = (b  0x7FF0)  (32-9);
+
+if (aexp  bexp) {
+return asgn ? 1 : -1;
+} else if (aexp  bexp) {
+return asgn ? -1 : 1;
+} else {
+uint64_t afrac = a  0x007F;
+uint64_t bfrac = b  0x007F;
+
+if (afrac  bfrac) {
+return asgn ? 1 : -1;
+} else if (afrac  bfrac) {
+return asgn ? -1 : 1;
+} else {
+return 0;
+}
+}
+}
+
+/* VSX_MAX - VSX floating point maximum
+ *   op- instruction mnemonic
+ *   nels  - number of elements (1, 2 or 4)
+ *   tp- type (float32 or float64)
+ *   fld   - vsr_t field (f32 or f64)
+ */
+#define VSX_MAX(op, nels, tp, fld)\
+void helper_##op(CPUPPCState *env, uint32_t opcode)   \
+{ \
+ppc_vsr_t xt, xa, xb; \
+int i;\
+  \
+getVSR(xA(opcode), xa, env); \
+getVSR(xB(opcode), xb, env); \
+getVSR(xT(opcode), xt, env); \
+  \
+for (i = 0; i  nels; i++) {  \
+if (unlikely(tp##_is_any_nan(xa.fld[i]) ||\
+ tp##_is_any_nan(xb.fld[i]))) {   \
+if (tp##_is_signaling_nan(xa.fld[i])) {   \
+xt.fld[i] = tp##_snan_to_qnan(xa.fld[i]); \
+fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);\
+} else if (tp##_is_signaling_nan(xb.fld[i])) {\
+xt.fld[i] = tp##_snan_to_qnan(xb.fld[i]); \
+fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);\
+} else if (tp##_is_quiet_nan(xb.fld[i])) {\
+xt.fld[i] = xa.fld[i];\
+} else { /* XA is QNaN */ \
+xt.fld[i] = xb.fld[i];\
+} \
+} else if (unlikely(tp##_is_infinity(xa.fld[i]))) {   \
+xt.fld[i] = tp##_is_neg(xa.fld[i]) ? xb.fld[i] : xa.fld[i];   \
+} else if (unlikely(tp##_is_infinity(xb.fld[i]))) {   \
+

Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-24 Thread Richard Henderson
On 10/24/2013 09:26 AM, Tom Musta wrote:
 Because of the Power ISA definitions of maximum and minimum
 on various boundary cases, the standard softfloat comparison
 routines (e.g. float64_lt) do not work as well as one might
 think.  Therefore specific routines for comparing 64 and 32
 bit floating point numbers are implemented in the PowerPC
 helper code.

Really?  All I see in the document is fp, used both here
in the minmax insn and in the cmp insn.

If the softfloat compare isn't good enough for minmax, how
can it be good enough for cmp?


r~



Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-24 Thread Tom Musta

On 10/24/2013 3:45 PM, Richard Henderson wrote:

On 10/24/2013 09:26 AM, Tom Musta wrote:

Because of the Power ISA definitions of maximum and minimum
on various boundary cases, the standard softfloat comparison
routines (e.g. float64_lt) do not work as well as one might
think.  Therefore specific routines for comparing 64 and 32
bit floating point numbers are implemented in the PowerPC
helper code.


Really?  All I see in the document is fp, used both here
in the minmax insn and in the cmp insn.

If the softfloat compare isn't good enough for minmax, how
can it be good enough for cmp?


Example:

The ISA is very explicit that max(-0.0, +0.0) = +0.0.

But the comparison operations (and instructions) both consider
-0.0 == +0.0.  Because of this, I do not see how it is possible
to implement max using float*_eq, float*_lt and float*_le.

See, for example, table 58 (Actions for xsmaxdp) on p. 369 of the
V2.06 ISA.




Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-24 Thread Richard Henderson
On 10/24/2013 02:07 PM, Tom Musta wrote:
 
 See, for example, table 58 (Actions for xsmaxdp) on p. 369 of the
 V2.06 ISA.

Bah, I typoed my search in the document and looked at the Altivec insn, which
is only one letter different, and doesn't have the same guarantees.

Reviewed-by: Richard Henderson r...@twiddle.net


r~



Re: [Qemu-devel] [PATCH 15/19] Add VSX xmax/xmin Instructions

2013-10-24 Thread Peter Maydell
On 24 October 2013 17:26, Tom Musta tommu...@gmail.com wrote:
 This patch adds the VSX floating point maximum and minimum
 instructions:

   - xsmaxdp, xvmaxdp, xvmaxsp
   - xsmindp, xvmindp, xvminsp

 Because of the Power ISA definitions of maximum and minimum
 on various boundary cases, the standard softfloat comparison
 routines (e.g. float64_lt) do not work as well as one might
 think.  Therefore specific routines for comparing 64 and 32
 bit floating point numbers are implemented in the PowerPC
 helper code.

Can't you use the min and max softfloat functions? Those are
there specifically because the corner cases mean you can't
implement them using the comparisons. (For instance for
the example you quote of max(-0.0, +0.0) they return +0.0
as you require.)

thanks
-- PMM