Topic
  • 3 replies
  • Latest Post - ‏2014-08-12T13:08:55Z by Bill_Buros
PowerLinuxFAQ
PowerLinuxFAQ
18 Posts

Pinned topic PPC code to divide 128bit / 64bit ?

‏2014-08-12T13:00:06Z |

A customer was asking me for PPC ASM divide code.
They are looking for a routine which supports:
        signed 128bit divided-by signed 64bit  = signed 64bit

Does someone by chance has such a routine already?
Or is there a place where one can find cook book examples for this?

  • Bill_Buros
    Bill_Buros
    169 Posts

    Re: PPC code to divide 128bit / 64bit ?

    ‏2014-08-12T13:02:36Z  

    From Julian Wang.. 

    See Hank Warren's (IBMer) book --- Hacker's Delight.  In particular, with extended divide instructions available since POWER7.

  • Bill_Buros
    Bill_Buros
    169 Posts

    Re: PPC code to divide 128bit / 64bit ?

    ‏2014-08-12T13:04:48Z  

    From Adhemerval Zanella

    Depending of customer constraints, there is no need for an specific ASM for such thing:

    GCC implements signed and unsigned 128 bits for some time. The example:

    ---

    #include <stdio.h>
    #include <stdint.h>

    #include <gmp.h>

    typedef __int128_t  int128_t;
    typedef __uint128_t uint128_t;

    int64_t divide (int128_t x, int64_t y)
    {
      return x / y;
    }

    #define UINT128_CONST(A, B) \
      (((uint128_t) (A ## ULL) << 64) | (B ## ULL))

    void
    divide_int128 (void)
    {
      int128_t x = UINT128_CONST (0xa5e225dddddddddf, 0x6666666666aaee66);
      int64_t  y = 0xf6666666666aaee6;

      int64_t  r = divide (x, y);
      printf ("%s: 0x%016LX\n", __FUNCTION__, r);
    }

    void
    divide_mpn (void)
    {
      MP_INT x;
      MP_INT y;
      MP_INT r;

      mpz_init_set_str (&x, "0xa5e225dddddddddf6666666666aaee66", 16);
      mpz_init_set_str (&y,                 "0xf6666666666aaee6", 16);
      mpz_init (&r);

      mpz_div (&r, &x, &y);
      int64_t rs =  mpz_get_si (&r);
      printf ("%s: 0x%016LX\n", __FUNCTION__, rs);
    }

    int main ()
    {
      divide_int128 ();
      divide_mpn ();
      return 0;
    }

    ---

    Shows:

    $ ./divide
    divide_int128: 0xF1BB902E65D7DDAA
    divide_mpn   : 0xF1BB902E65D7DDAA

    ---

    On both x86_64 and ppc64.  And the function is implemented in libgcc, which is linked statically and it won't tamper any customer code with GPL [1].

    Also, if you check both x86 and powerpc '__divti3' implementation it is quite complex, even by using divwe* instructions.  I would suggest you to first try to use GCC supported builtin and runtime, profile and then if 'divti3' is showing in profile, try to manually tune it.

    [1] https://www.gnu.org/licenses/gcc-exception-faq.html

    Updated on 2014-08-12T13:08:06Z at 2014-08-12T13:08:06Z by Bill_Buros
  • Bill_Buros
    Bill_Buros
    169 Posts

    Re: PPC code to divide 128bit / 64bit ?

    ‏2014-08-12T13:08:55Z  

    From Steve Munroe

    The PowerISA-2.06 (P7) and 2.07 (p8) section 3.3.8.1 includes a program note in the description of Divide Word Extended [Unsigned]. The same algorithm can be applied to a 128-bit by 64-bit divide by substituting doubleword ops for word ops in the example.

    Also with a newer compiler (AT-7.0) you should be able to divide a [unsigned] __int128 by a [unsigned] long and get a [unsigned] long result. The compiler generates the correct code for you.