xref: /openbmc/linux/arch/m68k/lib/muldi3.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
198d655a6SGreg Ungerer /* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
298d655a6SGreg Ungerer 			   gcc-2.7.2.3/longlong.h which is: */
398d655a6SGreg Ungerer /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
498d655a6SGreg Ungerer 
598d655a6SGreg Ungerer This file is part of GNU CC.
698d655a6SGreg Ungerer 
798d655a6SGreg Ungerer GNU CC is free software; you can redistribute it and/or modify
898d655a6SGreg Ungerer it under the terms of the GNU General Public License as published by
998d655a6SGreg Ungerer the Free Software Foundation; either version 2, or (at your option)
1098d655a6SGreg Ungerer any later version.
1198d655a6SGreg Ungerer 
1298d655a6SGreg Ungerer GNU CC is distributed in the hope that it will be useful,
1398d655a6SGreg Ungerer but WITHOUT ANY WARRANTY; without even the implied warranty of
1498d655a6SGreg Ungerer MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15d6410efaSGeert Uytterhoeven GNU General Public License for more details. */
1698d655a6SGreg Ungerer 
17d13ffb56SAl Viro #include <linux/compiler.h>
18d13ffb56SAl Viro #include <linux/export.h>
19d13ffb56SAl Viro 
205df58f3aSGeert Uytterhoeven #ifdef CONFIG_CPU_HAS_NO_MULDIV64
2198d655a6SGreg Ungerer 
2298d655a6SGreg Ungerer #define SI_TYPE_SIZE 32
2398d655a6SGreg Ungerer #define __BITS4 (SI_TYPE_SIZE / 4)
2498d655a6SGreg Ungerer #define __ll_B (1L << (SI_TYPE_SIZE / 2))
2598d655a6SGreg Ungerer #define __ll_lowpart(t) ((USItype) (t) % __ll_B)
2698d655a6SGreg Ungerer #define __ll_highpart(t) ((USItype) (t) / __ll_B)
2798d655a6SGreg Ungerer 
2898d655a6SGreg Ungerer #define umul_ppmm(w1, w0, u, v)						\
2998d655a6SGreg Ungerer   do {									\
3098d655a6SGreg Ungerer     USItype __x0, __x1, __x2, __x3;					\
3198d655a6SGreg Ungerer     USItype __ul, __vl, __uh, __vh;					\
3298d655a6SGreg Ungerer 									\
3398d655a6SGreg Ungerer     __ul = __ll_lowpart (u);						\
3498d655a6SGreg Ungerer     __uh = __ll_highpart (u);						\
3598d655a6SGreg Ungerer     __vl = __ll_lowpart (v);						\
3698d655a6SGreg Ungerer     __vh = __ll_highpart (v);						\
3798d655a6SGreg Ungerer 									\
3898d655a6SGreg Ungerer     __x0 = (USItype) __ul * __vl;					\
3998d655a6SGreg Ungerer     __x1 = (USItype) __ul * __vh;					\
4098d655a6SGreg Ungerer     __x2 = (USItype) __uh * __vl;					\
4198d655a6SGreg Ungerer     __x3 = (USItype) __uh * __vh;					\
4298d655a6SGreg Ungerer 									\
4398d655a6SGreg Ungerer     __x1 += __ll_highpart (__x0);/* this can't give carry */		\
4498d655a6SGreg Ungerer     __x1 += __x2;		/* but this indeed can */		\
4598d655a6SGreg Ungerer     if (__x1 < __x2)		/* did we get it? */			\
4698d655a6SGreg Ungerer       __x3 += __ll_B;		/* yes, add it in the proper pos. */	\
4798d655a6SGreg Ungerer 									\
4898d655a6SGreg Ungerer     (w1) = __x3 + __ll_highpart (__x1);					\
4998d655a6SGreg Ungerer     (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
5098d655a6SGreg Ungerer   } while (0)
5198d655a6SGreg Ungerer 
52734c3ce3SGreg Ungerer #else
53734c3ce3SGreg Ungerer 
54734c3ce3SGreg Ungerer #define umul_ppmm(w1, w0, u, v) \
55734c3ce3SGreg Ungerer   __asm__ ("mulu%.l %3,%1:%0"						\
56734c3ce3SGreg Ungerer            : "=d" ((USItype)(w0)),					\
57734c3ce3SGreg Ungerer              "=d" ((USItype)(w1))					\
58734c3ce3SGreg Ungerer            : "%0" ((USItype)(u)),					\
59734c3ce3SGreg Ungerer              "dmi" ((USItype)(v)))
60734c3ce3SGreg Ungerer 
6166d857b0SGreg Ungerer #endif
6298d655a6SGreg Ungerer 
6398d655a6SGreg Ungerer #define __umulsidi3(u, v) \
6498d655a6SGreg Ungerer   ({DIunion __w;							\
6598d655a6SGreg Ungerer     umul_ppmm (__w.s.high, __w.s.low, u, v);				\
6698d655a6SGreg Ungerer     __w.ll; })
6798d655a6SGreg Ungerer 
68849de0cdSGideon Israel Dsouza typedef 	 int SItype	__mode(SI);
69849de0cdSGideon Israel Dsouza typedef unsigned int USItype	__mode(SI);
70849de0cdSGideon Israel Dsouza typedef		 int DItype	__mode(DI);
71849de0cdSGideon Israel Dsouza typedef int word_type           __mode(__word__);
7298d655a6SGreg Ungerer 
7398d655a6SGreg Ungerer struct DIstruct {SItype high, low;};
7498d655a6SGreg Ungerer 
7598d655a6SGreg Ungerer typedef union
7698d655a6SGreg Ungerer {
7798d655a6SGreg Ungerer   struct DIstruct s;
7898d655a6SGreg Ungerer   DItype ll;
7998d655a6SGreg Ungerer } DIunion;
8098d655a6SGreg Ungerer 
8198d655a6SGreg Ungerer DItype
__muldi3(DItype u,DItype v)8298d655a6SGreg Ungerer __muldi3 (DItype u, DItype v)
8398d655a6SGreg Ungerer {
8498d655a6SGreg Ungerer   DIunion w;
8598d655a6SGreg Ungerer   DIunion uu, vv;
8698d655a6SGreg Ungerer 
87*6621cb4aSGeert Uytterhoeven   uu.ll = u;
8898d655a6SGreg Ungerer   vv.ll = v;
8998d655a6SGreg Ungerer 
9098d655a6SGreg Ungerer   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
9198d655a6SGreg Ungerer   w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
9298d655a6SGreg Ungerer 	       + (USItype) uu.s.high * (USItype) vv.s.low);
9398d655a6SGreg Ungerer 
9498d655a6SGreg Ungerer   return w.ll;
9598d655a6SGreg Ungerer }
96d13ffb56SAl Viro EXPORT_SYMBOL(__muldi3);
97