uboot/lib_blackfin/muldi3.c
<<
>>
Prefs
   1/*
   2 * U-boot - muldi3.c contains routines for mult and div
   3 *
   4 * Copyright (c) 2005-2007 Analog Devices Inc.
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  22 * MA 02110-1301 USA
  23 */
  24
  25/* Generic function got from GNU gcc package, libgcc2.c */
  26#ifndef SI_TYPE_SIZE
  27#define SI_TYPE_SIZE 32
  28#endif
  29#define __ll_B (1L << (SI_TYPE_SIZE / 2))
  30#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
  31#define __ll_highpart(t) ((USItype) (t) / __ll_B)
  32#define BITS_PER_UNIT 8
  33
  34#if !defined (umul_ppmm)
  35#define umul_ppmm(w1, w0, u, v)                                         \
  36do {                                                                    \
  37        USItype __x0, __x1, __x2, __x3;                                 \
  38        USItype __ul, __vl, __uh, __vh;                                 \
  39                                                                        \
  40        __ul = __ll_lowpart (u);                                        \
  41        __uh = __ll_highpart (u);                                       \
  42        __vl = __ll_lowpart (v);                                        \
  43        __vh = __ll_highpart (v);                                       \
  44                                                                        \
  45        __x0 = (USItype) __ul * __vl;                                   \
  46        __x1 = (USItype) __ul * __vh;                                   \
  47        __x2 = (USItype) __uh * __vl;                                   \
  48        __x3 = (USItype) __uh * __vh;                                   \
  49                                                                        \
  50        __x1 += __ll_highpart (__x0);/* this can't give carry */        \
  51        __x1 += __x2;   /* but this indeed can */                       \
  52        if (__x1 < __x2)        /* did we get it? */                    \
  53                __x3 += __ll_B; /* yes, add it in the proper pos. */    \
  54                                                                        \
  55        (w1) = __x3 + __ll_highpart (__x1);                             \
  56        (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);      \
  57} while (0)
  58#endif
  59
  60#if !defined (__umulsidi3)
  61#define __umulsidi3(u, v)                                               \
  62        ({DIunion __w;                                                  \
  63        umul_ppmm (__w.s.high, __w.s.low, u, v);                        \
  64        __w.ll; })
  65#endif
  66
  67typedef unsigned int USItype __attribute__ ((mode(SI)));
  68typedef int SItype __attribute__ ((mode(SI)));
  69typedef int DItype __attribute__ ((mode(DI)));
  70typedef int word_type __attribute__ ((mode(__word__)));
  71
  72struct DIstruct {
  73        SItype low, high;
  74};
  75typedef union {
  76        struct DIstruct s;
  77        DItype ll;
  78} DIunion;
  79
  80DItype __muldi3(DItype u, DItype v)
  81{
  82        DIunion w;
  83        DIunion uu, vv;
  84
  85        uu.ll = u, vv.ll = v;
  86        /*  panic("kernel panic for __muldi3"); */
  87        w.ll = __umulsidi3(uu.s.low, vv.s.low);
  88        w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
  89                     + (USItype) uu.s.high * (USItype) vv.s.low);
  90
  91        return w.ll;
  92}
  93