LCOV - code coverage report
Current view: top level - arch/arm/include/asm - div64.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 15 17 88.2 %
Date: 2020-09-30 20:25:40 Functions: 2 2 100.0 %
Branches: 4 6 66.7 %

           Branch data     Line data    Source code
       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                 :            : 
      25                 :            : #ifdef __ARMEB__
      26                 :            : #define __xh "r0"
      27                 :            : #define __xl "r1"
      28                 :            : #else
      29                 :            : #define __xl "r0"
      30                 :            : #define __xh "r1"
      31                 :            : #endif
      32                 :            : 
      33                 :    1548165 : static inline uint32_t __div64_32(uint64_t *n, uint32_t base)
      34                 :            : {
      35                 :    1548165 :         register unsigned int __base      asm("r4") = base;
      36                 :    1548165 :         register unsigned long long __n   asm("r0") = *n;
      37                 :            :         register unsigned long long __res asm("r2");
      38                 :            :         register unsigned int __rem       asm(__xh);
      39                 :    1548165 :         asm(    __asmeq("%0", __xh)
      40                 :            :                 __asmeq("%1", "r2")
      41                 :            :                 __asmeq("%2", "r0")
      42                 :            :                 __asmeq("%3", "r4")
      43                 :            :                 "bl        __do_div64"
      44                 :            :                 : "=r" (__rem), "=r" (__res)
      45                 :            :                 : "r" (__n), "r" (__base)
      46                 :            :                 : "ip", "lr", "cc");
      47                 :    1548165 :         *n = __res;
      48                 :    1548165 :         return __rem;
      49                 :            : }
      50                 :            : #define __div64_32 __div64_32
      51                 :            : 
      52                 :            : #if !defined(CONFIG_AEABI)
      53                 :            : 
      54                 :            : /*
      55                 :            :  * In OABI configurations, some uses of the do_div function
      56                 :            :  * cause gcc to run out of registers. To work around that,
      57                 :            :  * we can force the use of the out-of-line version for
      58                 :            :  * configurations that build a OABI kernel.
      59                 :            :  */
      60                 :            : #define do_div(n, base) __div64_32(&(n), base)
      61                 :            : 
      62                 :            : #else
      63                 :            : 
      64                 :            : /*
      65                 :            :  * gcc versions earlier than 4.0 are simply too problematic for the
      66                 :            :  * __div64_const32() code in asm-generic/div64.h. First there is
      67                 :            :  * gcc PR 15089 that tend to trig on more complex constructs, spurious
      68                 :            :  * .global __udivsi3 are inserted even if none of those symbols are
      69                 :            :  * referenced in the generated code, and those gcc versions are not able
      70                 :            :  * to do constant propagation on long long values anyway.
      71                 :            :  */
      72                 :            : 
      73                 :            : #define __div64_const32_is_OK (__GNUC__ >= 4)
      74                 :            : 
      75                 :    4070102 : static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
      76                 :            : {
      77                 :            :         unsigned long long res;
      78                 :    4070102 :         register unsigned int tmp asm("ip") = 0;
      79                 :            : 
      80         [ +  + ]:    4070102 :         if (!bias) {
      81                 :    2960856 :                 asm (   "umull     %Q0, %R0, %Q1, %Q2\n\t"
      82                 :            :                         "mov       %Q0, #0"
      83                 :            :                         : "=&r" (res)
      84                 :            :                         : "r" (m), "r" (n)
      85                 :            :                         : "cc");
      86         [ -  + ]:    1109246 :         } else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
      87                 :            :                 res = m;
      88                 :          0 :                 asm (   "umlal     %Q0, %R0, %Q1, %Q2\n\t"
      89                 :            :                         "mov       %Q0, #0"
      90                 :            :                         : "+&r" (res)
      91                 :            :                         : "r" (m), "r" (n)
      92                 :            :                         : "cc");
      93                 :            :         } else {
      94                 :    1109246 :                 asm (   "umull     %Q0, %R0, %Q2, %Q3\n\t"
      95                 :            :                         "cmn       %Q0, %Q2\n\t"
      96                 :            :                         "adcs      %R0, %R0, %R2\n\t"
      97                 :            :                         "adc       %Q0, %1, #0"
      98                 :            :                         : "=&r" (res), "+&r" (tmp)
      99                 :            :                         : "r" (m), "r" (n)
     100                 :            :                         : "cc");
     101                 :            :         }
     102                 :            : 
     103         [ -  + ]:    4070102 :         if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
     104                 :          0 :                 asm (   "umlal     %R0, %Q0, %R1, %Q2\n\t"
     105                 :            :                         "umlal     %R0, %Q0, %Q1, %R2\n\t"
     106                 :            :                         "mov       %R0, #0\n\t"
     107                 :            :                         "umlal     %Q0, %R0, %R1, %R2"
     108                 :            :                         : "+&r" (res)
     109                 :            :                         : "r" (m), "r" (n)
     110                 :            :                         : "cc");
     111                 :            :         } else {
     112                 :    4070102 :                 asm (   "umlal     %R0, %Q0, %R2, %Q3\n\t"
     113                 :            :                         "umlal     %R0, %1, %Q2, %R3\n\t"
     114                 :            :                         "mov       %R0, #0\n\t"
     115                 :            :                         "adds      %Q0, %1, %Q0\n\t"
     116                 :            :                         "adc       %R0, %R0, #0\n\t"
     117                 :            :                         "umlal     %Q0, %R0, %R2, %R3"
     118                 :            :                         : "+&r" (res), "+&r" (tmp)
     119                 :            :                         : "r" (m), "r" (n)
     120                 :            :                         : "cc");
     121                 :            :         }
     122                 :            : 
     123                 :    4070102 :         return res;
     124                 :            : }
     125                 :            : #define __arch_xprod_64 __arch_xprod_64
     126                 :            : 
     127                 :            : #include <asm-generic/div64.h>
     128                 :            : 
     129                 :            : #endif
     130                 :            : 
     131                 :            : #endif

Generated by: LCOV version 1.14