uboot/arch/microblaze/lib/muldi3.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * U-Boot - muldi3.c contains routines for mult and div
   4 *
   5 */
   6
   7/* Generic function got from GNU gcc package, libgcc2.c */
   8#ifndef SI_TYPE_SIZE
   9#define SI_TYPE_SIZE 32
  10#endif
  11#define __ll_B (1L << (SI_TYPE_SIZE / 2))
  12#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
  13#define __ll_highpart(t) ((USItype) (t) / __ll_B)
  14#define BITS_PER_UNIT 8
  15
  16#if !defined(umul_ppmm)
  17#define umul_ppmm(w1, w0, u, v)                                         \
  18        do {                                                            \
  19        USItype __x0, __x1, __x2, __x3;                                 \
  20        USItype __ul, __vl, __uh, __vh;                                 \
  21                                                                        \
  22                __ul = __ll_lowpart(u);                                 \
  23                __uh = __ll_highpart(u);                                \
  24                __vl = __ll_lowpart(v);                                 \
  25                __vh = __ll_highpart(v);                                \
  26                                                                        \
  27        __x0 = (USItype) __ul * __vl;                                   \
  28        __x1 = (USItype) __ul * __vh;                                   \
  29        __x2 = (USItype) __uh * __vl;                                   \
  30        __x3 = (USItype) __uh * __vh;                                   \
  31                                                                        \
  32                __x1 += __ll_highpart(__x0); /* this can't give carry */\
  33                __x1 += __x2; /* but this indeed can */                 \
  34                if (__x1 < __x2) /* did we get it? */                   \
  35                __x3 += __ll_B; /* yes, add it in the proper pos. */    \
  36                                                                        \
  37                (w1) = __x3 + __ll_highpart(__x1);                      \
  38                (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
  39        } while (0)
  40#endif
  41
  42#if !defined(__umulsidi3)
  43#define __umulsidi3(u, v)                                               \
  44        ({DIunion __w;                                                  \
  45        umul_ppmm(__w.s.high, __w.s.low, u, v);         \
  46        __w.ll; })
  47#endif
  48
  49typedef unsigned int USItype __attribute__ ((mode(SI)));
  50typedef int SItype __attribute__ ((mode(SI)));
  51typedef int DItype __attribute__ ((mode(DI)));
  52typedef int word_type __attribute__ ((mode(__word__)));
  53
  54struct DIstruct {
  55        SItype low, high;
  56};
  57typedef union {
  58        struct DIstruct s;
  59        DItype ll;
  60} DIunion;
  61
  62DItype __muldi3(DItype u, DItype v)
  63{
  64        DIunion w;
  65        DIunion uu, vv;
  66
  67        uu.ll = u, vv.ll = v;
  68        /*  panic("kernel panic for __muldi3"); */
  69        w.ll = __umulsidi3(uu.s.low, vv.s.low);
  70        w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
  71                     + (USItype) uu.s.high * (USItype) vv.s.low);
  72
  73        return w.ll;
  74}
  75