~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/include/asm/div64.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef __ASM_ARM_DIV64
  3 #define __ASM_ARM_DIV64
  4 
  5 #include <linux/types.h>
  6 #include <asm/compiler.h>
  7 
  8 /*
  9  * The semantics of __div64_32() are:
 10  *
 11  * uint32_t __div64_32(uint64_t *n, uint32_t base)
 12  * {
 13  *      uint32_t remainder = *n % base;
 14  *      *n = *n / base;
 15  *      return remainder;
 16  * }
 17  *
 18  * In other words, a 64-bit dividend with a 32-bit divisor producing
 19  * a 64-bit result and a 32-bit remainder.  To accomplish this optimally
 20  * we override the generic version in lib/div64.c to call our __do_div64
 21  * assembly implementation with completely non standard calling convention
 22  * for arguments and results (beware).
 23  */
 24 static inline uint32_t __div64_32(uint64_t *n, uint32_t base)
 25 {
 26         register unsigned int __base      asm("r4") = base;
 27         register unsigned long long __n   asm("r0") = *n;
 28         register unsigned long long __res asm("r2");
 29         unsigned int __rem;
 30         asm(    __asmeq("%0", "r0")
 31                 __asmeq("%1", "r2")
 32                 __asmeq("%2", "r4")
 33                 "bl     __do_div64"
 34                 : "+r" (__n), "=r" (__res)
 35                 : "r" (__base)
 36                 : "ip", "lr", "cc");
 37         __rem = __n >> 32;
 38         *n = __res;
 39         return __rem;
 40 }
 41 #define __div64_32 __div64_32
 42 
 43 #if !defined(CONFIG_AEABI)
 44 
 45 /*
 46  * In OABI configurations, some uses of the do_div function
 47  * cause gcc to run out of registers. To work around that,
 48  * we can force the use of the out-of-line version for
 49  * configurations that build a OABI kernel.
 50  */
 51 #define do_div(n, base) __div64_32(&(n), base)
 52 
 53 #else
 54 
 55 static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
 56 {
 57         unsigned long long res;
 58         register unsigned int tmp asm("ip") = 0;
 59 
 60         if (!bias) {
 61                 asm (   "umull  %Q0, %R0, %Q1, %Q2\n\t"
 62                         "mov    %Q0, #0"
 63                         : "=&r" (res)
 64                         : "r" (m), "r" (n)
 65                         : "cc");
 66         } else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
 67                 res = m;
 68                 asm (   "umlal  %Q0, %R0, %Q1, %Q2\n\t"
 69                         "mov    %Q0, #0"
 70                         : "+&r" (res)
 71                         : "r" (m), "r" (n)
 72                         : "cc");
 73         } else {
 74                 asm (   "umull  %Q0, %R0, %Q2, %Q3\n\t"
 75                         "cmn    %Q0, %Q2\n\t"
 76                         "adcs   %R0, %R0, %R2\n\t"
 77                         "adc    %Q0, %1, #0"
 78                         : "=&r" (res), "+&r" (tmp)
 79                         : "r" (m), "r" (n)
 80                         : "cc");
 81         }
 82 
 83         if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
 84                 asm (   "umlal  %R0, %Q0, %R1, %Q2\n\t"
 85                         "umlal  %R0, %Q0, %Q1, %R2\n\t"
 86                         "mov    %R0, #0\n\t"
 87                         "umlal  %Q0, %R0, %R1, %R2"
 88                         : "+&r" (res)
 89                         : "r" (m), "r" (n)
 90                         : "cc");
 91         } else {
 92                 asm (   "umlal  %R0, %Q0, %R2, %Q3\n\t"
 93                         "umlal  %R0, %1, %Q2, %R3\n\t"
 94                         "mov    %R0, #0\n\t"
 95                         "adds   %Q0, %1, %Q0\n\t"
 96                         "adc    %R0, %R0, #0\n\t"
 97                         "umlal  %Q0, %R0, %R2, %R3"
 98                         : "+&r" (res), "+&r" (tmp)
 99                         : "r" (m), "r" (n)
100                         : "cc");
101         }
102 
103         return res;
104 }
105 #define __arch_xprod_64 __arch_xprod_64
106 
107 #include <asm-generic/div64.h>
108 
109 #endif
110 
111 #endif
112 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php