Subversion Repositories HelenOS

Rev

Rev 1888 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Josef Cejka
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup genarch
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <genarch/softint/division.h>
  36.  
  37. #define ABSVAL(x) ( (x) > 0 ? (x) : -(x))
  38. #define SGN(x) ( (x) >= 0 ? 1 : 0 )
  39.                      
  40. static unsigned int divandmod32(unsigned int a, unsigned int b, unsigned int *remainder)
  41. {
  42.     unsigned int result;
  43.     int steps = sizeof(unsigned int) * 8;
  44.    
  45.     *remainder = 0;
  46.     result = 0;
  47.    
  48.     if (b == 0) {
  49.         /* FIXME: division by zero */
  50.         return 0;
  51.     }
  52.    
  53.     if ( a < b) {
  54.         *remainder = a;
  55.         return 0;
  56.     }
  57.  
  58.     for ( ; steps > 0; steps--) {
  59.         /* shift one bit to remainder */
  60.         *remainder = ( (*remainder) << 1) | (( a >> 31) & 0x1);
  61.         result <<= 1;
  62.        
  63.         if (*remainder >= b) {
  64.                 *remainder -= b;
  65.                 result |= 0x1;
  66.         }
  67.         a <<= 1;
  68.     }
  69.  
  70.     return result;
  71. }
  72.  
  73.  
  74. static unsigned long long divandmod64(unsigned long long a, unsigned long long b, unsigned long long *remainder)
  75. {
  76.     unsigned long long result;
  77.     int steps = sizeof(unsigned long long) * 8;
  78.    
  79.     *remainder = 0;
  80.     result = 0;
  81.    
  82.     if (b == 0) {
  83.         /* FIXME: division by zero */
  84.         return 0;
  85.     }
  86.    
  87.     if ( a < b) {
  88.         *remainder = a;
  89.         return 0;
  90.     }
  91.  
  92.     for ( ; steps > 0; steps--) {
  93.         /* shift one bit to remainder */
  94.         *remainder = ( (*remainder) << 1) | ((a >> 63) & 0x1);
  95.         result <<= 1;
  96.        
  97.         if (*remainder >= b) {
  98.                 *remainder -= b;
  99.                 result |= 0x1;
  100.         }
  101.         a <<= 1;
  102.     }
  103.  
  104.     return result;
  105. }
  106.  
  107. /* 32bit integer division */
  108. int __divsi3(int a, int b)
  109. {
  110.     unsigned int rem;
  111.     int result;
  112.    
  113.     result = (int)divandmod32(ABSVAL(a), ABSVAL(b), &rem);
  114.  
  115.     if ( SGN(a) == SGN(b)) return result;
  116.     return -result;
  117. }
  118.  
  119. /* 64bit integer division */
  120. long long __divdi3(long long a, long long b)
  121. {
  122.     unsigned long long rem;
  123.     long long result;
  124.    
  125.     result = (long long)divandmod64(ABSVAL(a), ABSVAL(b), &rem);
  126.  
  127.     if ( SGN(a) == SGN(b)) return result;
  128.     return -result;
  129. }
  130.  
  131. /* 32bit unsigned integer division */
  132. unsigned int __udivsi3(unsigned int a, unsigned int b)
  133. {
  134.     unsigned int rem;
  135.     return divandmod32(a, b, &rem);
  136. }
  137.  
  138. /* 64bit unsigned integer division */
  139. unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
  140. {
  141.     unsigned long long  rem;
  142.     return divandmod64(a, b, &rem);
  143. }
  144.  
  145. /* 32bit remainder of the signed division */
  146. int __modsi3(int a, int b)
  147. {
  148.     unsigned int rem;
  149.     divandmod32(a, b, &rem);
  150.    
  151.     /* if divident is negative, remainder must be too */
  152.     if (!(SGN(a))) {
  153.         return -((int)rem);
  154.     }
  155.    
  156.     return (int)rem;
  157. }
  158.  
  159. /* 64bit remainder of the signed division */
  160. long long __moddi3(long long a,long  long b)
  161. {
  162.     unsigned long long rem;
  163.     divandmod64(a, b, &rem);
  164.    
  165.     /* if divident is negative, remainder must be too */
  166.     if (!(SGN(a))) {
  167.         return -((long long)rem);
  168.     }
  169.    
  170.     return (long long)rem;
  171. }
  172.  
  173. /* 32bit remainder of the unsigned division */
  174. unsigned int __umodsi3(unsigned int a, unsigned int b)
  175. {
  176.     unsigned int rem;
  177.     divandmod32(a, b, &rem);
  178.     return rem;
  179. }
  180.  
  181. /* 64bit remainder of the unsigned division */
  182. unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
  183. {
  184.     unsigned long long rem;
  185.     divandmod64(a, b, &rem);
  186.     return rem;
  187. }
  188.  
  189. unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b, unsigned long long *c)
  190. {
  191.     return divandmod64(a, b, c);
  192. }
  193.  
  194. /** @}
  195.  */
  196.