162306a36Sopenharmony_ci/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 262306a36Sopenharmony_ci gcc-2.7.2.3/longlong.h which is: */ 362306a36Sopenharmony_ci/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciThis file is part of GNU CC. 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciGNU CC is free software; you can redistribute it and/or modify 862306a36Sopenharmony_ciit under the terms of the GNU General Public License as published by 962306a36Sopenharmony_cithe Free Software Foundation; either version 2, or (at your option) 1062306a36Sopenharmony_ciany later version. 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciGNU CC is distributed in the hope that it will be useful, 1362306a36Sopenharmony_cibut WITHOUT ANY WARRANTY; without even the implied warranty of 1462306a36Sopenharmony_ciMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1562306a36Sopenharmony_ciGNU General Public License for more details. */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/compiler.h> 1862306a36Sopenharmony_ci#include <linux/export.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_NO_MULDIV64 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define SI_TYPE_SIZE 32 2362306a36Sopenharmony_ci#define __BITS4 (SI_TYPE_SIZE / 4) 2462306a36Sopenharmony_ci#define __ll_B (1L << (SI_TYPE_SIZE / 2)) 2562306a36Sopenharmony_ci#define __ll_lowpart(t) ((USItype) (t) % __ll_B) 2662306a36Sopenharmony_ci#define __ll_highpart(t) ((USItype) (t) / __ll_B) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define umul_ppmm(w1, w0, u, v) \ 2962306a36Sopenharmony_ci do { \ 3062306a36Sopenharmony_ci USItype __x0, __x1, __x2, __x3; \ 3162306a36Sopenharmony_ci USItype __ul, __vl, __uh, __vh; \ 3262306a36Sopenharmony_ci \ 3362306a36Sopenharmony_ci __ul = __ll_lowpart (u); \ 3462306a36Sopenharmony_ci __uh = __ll_highpart (u); \ 3562306a36Sopenharmony_ci __vl = __ll_lowpart (v); \ 3662306a36Sopenharmony_ci __vh = __ll_highpart (v); \ 3762306a36Sopenharmony_ci \ 3862306a36Sopenharmony_ci __x0 = (USItype) __ul * __vl; \ 3962306a36Sopenharmony_ci __x1 = (USItype) __ul * __vh; \ 4062306a36Sopenharmony_ci __x2 = (USItype) __uh * __vl; \ 4162306a36Sopenharmony_ci __x3 = (USItype) __uh * __vh; \ 4262306a36Sopenharmony_ci \ 4362306a36Sopenharmony_ci __x1 += __ll_highpart (__x0);/* this can't give carry */ \ 4462306a36Sopenharmony_ci __x1 += __x2; /* but this indeed can */ \ 4562306a36Sopenharmony_ci if (__x1 < __x2) /* did we get it? */ \ 4662306a36Sopenharmony_ci __x3 += __ll_B; /* yes, add it in the proper pos. */ \ 4762306a36Sopenharmony_ci \ 4862306a36Sopenharmony_ci (w1) = __x3 + __ll_highpart (__x1); \ 4962306a36Sopenharmony_ci (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ 5062306a36Sopenharmony_ci } while (0) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#else 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define umul_ppmm(w1, w0, u, v) \ 5562306a36Sopenharmony_ci __asm__ ("mulu%.l %3,%1:%0" \ 5662306a36Sopenharmony_ci : "=d" ((USItype)(w0)), \ 5762306a36Sopenharmony_ci "=d" ((USItype)(w1)) \ 5862306a36Sopenharmony_ci : "%0" ((USItype)(u)), \ 5962306a36Sopenharmony_ci "dmi" ((USItype)(v))) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#endif 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define __umulsidi3(u, v) \ 6462306a36Sopenharmony_ci ({DIunion __w; \ 6562306a36Sopenharmony_ci umul_ppmm (__w.s.high, __w.s.low, u, v); \ 6662306a36Sopenharmony_ci __w.ll; }) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_citypedef int SItype __mode(SI); 6962306a36Sopenharmony_citypedef unsigned int USItype __mode(SI); 7062306a36Sopenharmony_citypedef int DItype __mode(DI); 7162306a36Sopenharmony_citypedef int word_type __mode(__word__); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct DIstruct {SItype high, low;}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_citypedef union 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct DIstruct s; 7862306a36Sopenharmony_ci DItype ll; 7962306a36Sopenharmony_ci} DIunion; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciDItype 8262306a36Sopenharmony_ci__muldi3 (DItype u, DItype v) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci DIunion w; 8562306a36Sopenharmony_ci DIunion uu, vv; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci uu.ll = u; 8862306a36Sopenharmony_ci vv.ll = v; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci w.ll = __umulsidi3 (uu.s.low, vv.s.low); 9162306a36Sopenharmony_ci w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high 9262306a36Sopenharmony_ci + (USItype) uu.s.high * (USItype) vv.s.low); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return w.ll; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ciEXPORT_SYMBOL(__muldi3); 97