division.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Josef Cejka
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <genarch/softint/division.h>
00036 
00037 #define ABSVAL(x) ( (x) > 0 ? (x) : -(x))
00038 #define SGN(x) ( (x) >= 0 ? 1 : 0 )
00039                                       
00040 static unsigned int divandmod32(unsigned int a, unsigned int b, unsigned int *remainder)
00041 {
00042         unsigned int result;
00043         int steps = sizeof(unsigned int) * 8; 
00044         
00045         *remainder = 0;
00046         result = 0;
00047         
00048         if (b == 0) {
00049                 /* FIXME: division by zero */
00050                 return 0;
00051         }
00052         
00053         if ( a < b) {
00054                 *remainder = a;
00055                 return 0;
00056         }
00057 
00058         for ( ; steps > 0; steps--) {
00059                 /* shift one bit to remainder */
00060                 *remainder = ( (*remainder) << 1) | (( a >> 31) & 0x1);
00061                 result <<= 1;
00062                 
00063                 if (*remainder >= b) {
00064                                 *remainder -= b;
00065                                 result |= 0x1;
00066                 }
00067                 a <<= 1;
00068         }
00069 
00070         return result;
00071 }
00072 
00073 
00074 static unsigned long long divandmod64(unsigned long long a, unsigned long long b, unsigned long long *remainder)
00075 {
00076         unsigned long long result;
00077         int steps = sizeof(unsigned long long) * 8; 
00078         
00079         *remainder = 0;
00080         result = 0;
00081         
00082         if (b == 0) {
00083                 /* FIXME: division by zero */
00084                 return 0;
00085         }
00086         
00087         if ( a < b) {
00088                 *remainder = a;
00089                 return 0;
00090         }
00091 
00092         for ( ; steps > 0; steps--) {
00093                 /* shift one bit to remainder */
00094                 *remainder = ( (*remainder) << 1) | ((a >> 63) & 0x1);
00095                 result <<= 1;
00096                 
00097                 if (*remainder >= b) {
00098                                 *remainder -= b;
00099                                 result |= 0x1;
00100                 }
00101                 a <<= 1;
00102         }
00103 
00104         return result;
00105 }
00106 
00107 /* 32bit integer division */
00108 int __divsi3(int a, int b) 
00109 {
00110         unsigned int rem;
00111         int result;
00112         
00113         result = (int)divandmod32(ABSVAL(a), ABSVAL(b), &rem);
00114 
00115         if ( SGN(a) == SGN(b)) return result;
00116         return -result;
00117 }
00118 
00119 /* 64bit integer division */
00120 long long __divdi3(long long a, long long b) 
00121 {
00122         unsigned long long rem;
00123         long long result;
00124         
00125         result = (long long)divandmod64(ABSVAL(a), ABSVAL(b), &rem);
00126 
00127         if ( SGN(a) == SGN(b)) return result;
00128         return -result;
00129 }
00130 
00131 /* 32bit unsigned integer division */
00132 unsigned int __udivsi3(unsigned int a, unsigned int b)
00133 {
00134         unsigned int rem;
00135         return divandmod32(a, b, &rem);
00136 }
00137 
00138 /* 64bit unsigned integer division */
00139 unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
00140 {
00141         unsigned long long  rem;
00142         return divandmod64(a, b, &rem);
00143 }
00144 
00145 /* 32bit remainder of the signed division */
00146 int __modsi3(int a, int b)
00147 {
00148         unsigned int rem;
00149         divandmod32(a, b, &rem);
00150         
00151         /* if divident is negative, remainder must be too */
00152         if (!(SGN(a))) {
00153                 return -((int)rem);
00154         }
00155         
00156         return (int)rem;
00157 }
00158 
00159 /* 64bit remainder of the signed division */
00160 long long __moddi3(long long a,long  long b)
00161 {
00162         unsigned long long rem;
00163         divandmod64(a, b, &rem);
00164         
00165         /* if divident is negative, remainder must be too */
00166         if (!(SGN(a))) {
00167                 return -((long long)rem);
00168         }
00169         
00170         return (long long)rem;
00171 }
00172 
00173 /* 32bit remainder of the unsigned division */
00174 unsigned int __umodsi3(unsigned int a, unsigned int b)
00175 {
00176         unsigned int rem;
00177         divandmod32(a, b, &rem);
00178         return rem;
00179 }
00180 
00181 /* 64bit remainder of the unsigned division */
00182 unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
00183 {
00184         unsigned long long rem;
00185         divandmod64(a, b, &rem);
00186         return rem;
00187 }
00188 
00189 unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b, unsigned long long *c)
00190 {
00191         return divandmod64(a, b, c);
00192 }
00193 
00194 
00195 

Generated on Sun Jun 18 17:17:04 2006 for HelenOS Kernel (ppc32) by  doxygen 1.4.6