https://bugs.kde.org/show_bug.cgi?id=386945

--- Comment #14 from Julian Seward <jsew...@acm.org> ---
Here's a program that computes the CR.{LT,GT,EQ} bits after "cmplw"
using just AND, OR, XOR, NOT, SUB, SHL and SHR.  For "cmplw" (the
only case tested here so far), it produces the same results as the
hardware.

Since we have exact V-bit interpretations of all of the abovementioned
operations (in mc_translate.c), we should be able to mechanically
derive an exact V-bit interpretation of Iop_CmpORD32U.  If we do
the same for Iop_CmpORD64U and their signed equivalents, we'll be
along way along the road to getting these false-positive problems
with POWER condition codes fixed.

Performance will probably be pretty horrible.  But I am hoping that
there will be a lot of duplicated expressions in the resulting V-bit
DAG, so if those are commoned up it might not be quite so bad.

------------------------

#include <stdio.h>
#include <assert.h>

typedef  unsigned int  UInt;


__attribute__((noinline))
UInt h_CmpORD32U ( UInt x, UInt y )
{
   UInt res;
   __asm__ __volatile__(
   ""      "cmplw 0, %1, %2"
   "\n\t"  "mfcr  %0"
   : /*OUT*/ "=r"(res) : /*IN*/ "r"(x), "r"(y) : /*TRASH*/ "cc", "memory"
   );
   return (res >> 28) & 0xF;
}

__attribute__((noinline))
UInt s_CmpORD32U ( UInt x, UInt y )
{
#if 0
   if (x < y) return 8;
   if (x > y) return 4;
   return 2;
#else
   /*     x-y unsignedly overflows
      ==> x < y 
   */
   UInt x_minus_y_UO = (~x & y) | ((~(x ^ y)) & (x-y));
   x_minus_y_UO >>= 31;

   UInt y_minus_x_UO = (~y & x) | ((~(y ^ x)) & (y-x));
   y_minus_x_UO >>= 31;

   //UInt res = (x_minus_y_UO << 3) | (y_minus_x_UO << 2);
   //if (res == 0) res = 2;

   UInt x_eq_y = (x_minus_y_UO | y_minus_x_UO) ^ 1;
   UInt res = (x_minus_y_UO << 3) | (y_minus_x_UO << 2) | (x_eq_y << 1);

   return res;
#endif
}

const UInt vals[] = 
   { 0x0,
     0x1,
     0x2,

     0x3ffffffeU,
     0x3fffffffU,
     0x40000000U,
     0x40000001U,
     0x40000002U,

     0x7ffffffeU,
     0x7fffffffU,
     0x80000000U,
     0x80000001U,
     0x80000002U,

     0xbffffffeU,
     0xbfffffffU,
     0xc0000000U,
     0xc0000001U,
     0xc0000002U,

     0xfffffffdU,
     0xfffffffeU,
     0xffffffffU
   };

int main ( void )
{
   UInt xi, yi;
   const UInt nElem = sizeof(vals) / sizeof(vals[0]);
   for (xi = 0; xi < nElem; xi++) {
      for (yi = 0; yi < nElem; yi++) {
         UInt x = vals[xi];
         UInt y = vals[yi];
         UInt resHU = h_CmpORD32U(x, y);
         UInt resSU = s_CmpORD32U(x, y);
         printf("%08x %08x -> %02x %02x\n", x, y, resHU, resSU);
         assert(resHU == resSU);
      }
   }
   return 0;
}

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to