linux/arch/mn10300/include/asm/div64.h
<<
>>
Prefs
   1/* MN10300 64-bit division
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11#ifndef _ASM_DIV64
  12#define _ASM_DIV64
  13
  14#include <linux/types.h>
  15
  16extern void ____unhandled_size_in_do_div___(void);
  17
  18/*
  19 * divide n by base, leaving the result in n and returning the remainder
  20 * - we can do this quite efficiently on the MN10300 by cascading the divides
  21 *   through the MDR register
  22 */
  23#define do_div(n, base)                                                 \
  24({                                                                      \
  25        unsigned __rem = 0;                                             \
  26        if (sizeof(n) <= 4) {                                           \
  27                asm("mov        %1,mdr  \n"                             \
  28                    "divu       %2,%0   \n"                             \
  29                    "mov        mdr,%1  \n"                             \
  30                    : "+r"(n), "=d"(__rem)                              \
  31                    : "r"(base), "1"(__rem)                             \
  32                    : "cc"                                              \
  33                    );                                                  \
  34        } else if (sizeof(n) <= 8) {                                    \
  35                union {                                                 \
  36                        unsigned long long l;                           \
  37                        u32 w[2];                                       \
  38                } __quot;                                               \
  39                __quot.l = n;                                           \
  40                asm("mov        %0,mdr  \n"     /* MDR = 0 */           \
  41                    "divu       %3,%1   \n"                             \
  42                    /* __quot.MSL = __div.MSL / base, */                \
  43                    /* MDR = MDR:__div.MSL % base */                    \
  44                    "divu       %3,%2   \n"                             \
  45                    /* __quot.LSL = MDR:__div.LSL / base, */            \
  46                    /* MDR = MDR:__div.LSL % base */                    \
  47                    "mov        mdr,%0  \n"                             \
  48                    : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \
  49                    : "r"(base), "0"(__rem), "1"(__quot.w[1]),          \
  50                      "2"(__quot.w[0])                                  \
  51                    : "cc"                                              \
  52                    );                                                  \
  53                n = __quot.l;                                           \
  54        } else {                                                        \
  55                ____unhandled_size_in_do_div___();                      \
  56        }                                                               \
  57        __rem;                                                          \
  58})
  59
  60/*
  61 * do an unsigned 32-bit multiply and divide with intermediate 64-bit product
  62 * so as not to lose accuracy
  63 * - we use the MDR register to hold the MSW of the product
  64 */
  65static inline __attribute__((const))
  66unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
  67{
  68        unsigned result;
  69
  70        asm("mulu       %2,%0   \n"     /* MDR:val = val*mult */
  71            "divu       %3,%0   \n"     /* val = MDR:val/div;
  72                                         * MDR = MDR:val%div */
  73            : "=r"(result)
  74            : "0"(val), "ir"(mult), "r"(div)
  75            : "cc"
  76            );
  77
  78        return result;
  79}
  80
  81/*
  82 * do a signed 32-bit multiply and divide with intermediate 64-bit product so
  83 * as not to lose accuracy
  84 * - we use the MDR register to hold the MSW of the product
  85 */
  86static inline __attribute__((const))
  87signed __muldiv64s(signed val, signed mult, signed div)
  88{
  89        signed result;
  90
  91        asm("mul        %2,%0   \n"     /* MDR:val = val*mult */
  92            "div        %3,%0   \n"     /* val = MDR:val/div;
  93                                         * MDR = MDR:val%div */
  94            : "=r"(result)
  95            : "0"(val), "ir"(mult), "r"(div)
  96            : "cc"
  97            );
  98
  99        return result;
 100}
 101
 102#endif /* _ASM_DIV64 */
 103