source: mainline/kernel/genarch/src/softint/division.c@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was 7fe9c5b, checked in by Jakub Jermar <jakub@…>, 18 years ago

Minor cleanup of softint.

  • Property mode set to 100644
File size: 4.5 KB
RevLine 
[47c83bc]1/*
[df4ed85]2 * Copyright (c) 2006 Josef Cejka
[47c83bc]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
[06e1e95]29/** @addtogroup genarch
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[9b2729c]35#include <genarch/softint/division.h>
[47c83bc]36
[7fe9c5b]37#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
38#define SGN(x) ((x) >= 0 ? 1 : 0)
[47c83bc]39
[7fe9c5b]40static unsigned int divandmod32(unsigned int a, unsigned int b,
41 unsigned int *remainder)
[47c83bc]42{
43 unsigned int result;
[9b2729c]44 int steps = sizeof(unsigned int) * 8;
[47c83bc]45
46 *remainder = 0;
47 result = 0;
48
49 if (b == 0) {
50 /* FIXME: division by zero */
51 return 0;
52 }
53
[7fe9c5b]54 if (a < b) {
[47c83bc]55 *remainder = a;
56 return 0;
57 }
58
[7fe9c5b]59 for (; steps > 0; steps--) {
[47c83bc]60 /* shift one bit to remainder */
[7fe9c5b]61 *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
[47c83bc]62 result <<= 1;
63
64 if (*remainder >= b) {
[7fe9c5b]65 *remainder -= b;
66 result |= 0x1;
[47c83bc]67 }
[9b2729c]68 a <<= 1;
[47c83bc]69 }
70
71 return result;
72}
73
74
[7fe9c5b]75static unsigned long long divandmod64(unsigned long long a,
76 unsigned long long b, unsigned long long *remainder)
[47c83bc]77{
[280a27e]78 unsigned long long result;
79 int steps = sizeof(unsigned long long) * 8;
[47c83bc]80
81 *remainder = 0;
82 result = 0;
83
84 if (b == 0) {
85 /* FIXME: division by zero */
86 return 0;
87 }
88
[7fe9c5b]89 if (a < b) {
[47c83bc]90 *remainder = a;
91 return 0;
92 }
93
[7fe9c5b]94 for (; steps > 0; steps--) {
[47c83bc]95 /* shift one bit to remainder */
[7fe9c5b]96 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
[47c83bc]97 result <<= 1;
98
99 if (*remainder >= b) {
[7fe9c5b]100 *remainder -= b;
101 result |= 0x1;
[47c83bc]102 }
[9b2729c]103 a <<= 1;
[47c83bc]104 }
105
106 return result;
107}
108
109/* 32bit integer division */
110int __divsi3(int a, int b)
111{
112 unsigned int rem;
113 int result;
114
[7fe9c5b]115 result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
[47c83bc]116
[7fe9c5b]117 if (SGN(a) == SGN(b))
118 return result;
[47c83bc]119 return -result;
120}
121
122/* 64bit integer division */
[280a27e]123long long __divdi3(long long a, long long b)
[47c83bc]124{
[280a27e]125 unsigned long long rem;
126 long long result;
[47c83bc]127
[7fe9c5b]128 result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[47c83bc]129
[7fe9c5b]130 if (SGN(a) == SGN(b))
131 return result;
[47c83bc]132 return -result;
133}
134
135/* 32bit unsigned integer division */
136unsigned int __udivsi3(unsigned int a, unsigned int b)
137{
138 unsigned int rem;
139 return divandmod32(a, b, &rem);
140}
141
142/* 64bit unsigned integer division */
[280a27e]143unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
[47c83bc]144{
[280a27e]145 unsigned long long rem;
[47c83bc]146 return divandmod64(a, b, &rem);
147}
148
149/* 32bit remainder of the signed division */
150int __modsi3(int a, int b)
151{
152 unsigned int rem;
153 divandmod32(a, b, &rem);
154
[9b2729c]155 /* if divident is negative, remainder must be too */
[47c83bc]156 if (!(SGN(a))) {
[7fe9c5b]157 return -((int) rem);
[47c83bc]158 }
159
[7fe9c5b]160 return (int) rem;
[47c83bc]161}
162
163/* 64bit remainder of the signed division */
[280a27e]164long long __moddi3(long long a,long long b)
[47c83bc]165{
[280a27e]166 unsigned long long rem;
[47c83bc]167 divandmod64(a, b, &rem);
168
[9b2729c]169 /* if divident is negative, remainder must be too */
[47c83bc]170 if (!(SGN(a))) {
[7fe9c5b]171 return -((long long) rem);
[47c83bc]172 }
173
[7fe9c5b]174 return (long long) rem;
[47c83bc]175}
176
177/* 32bit remainder of the unsigned division */
178unsigned int __umodsi3(unsigned int a, unsigned int b)
179{
180 unsigned int rem;
181 divandmod32(a, b, &rem);
182 return rem;
183}
184
185/* 64bit remainder of the unsigned division */
[280a27e]186unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
[47c83bc]187{
[280a27e]188 unsigned long long rem;
[47c83bc]189 divandmod64(a, b, &rem);
190 return rem;
191}
192
[7fe9c5b]193unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
194 unsigned long long *c)
[47c83bc]195{
196 return divandmod64(a, b, c);
197}
198
[06e1e95]199/** @}
[b45c443]200 */
Note: See TracBrowser for help on using the repository browser.