1 /*
2 Copyright (c) 1990 The Regents of the University of California.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms are permitted
6 provided that the above copyright notice and this paragraph are
7 duplicated in all such forms and that any documentation,
8 and/or other materials related to such
9 distribution and use acknowledge that the software was developed
10 by the University of California, Berkeley. The name of the
11 University may not be used to endorse or promote products derived
12 from this software without specific prior written permission.
13 THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 #define divnorm(num, den, sign) \
19 { \
20 if (num < 0) \
21 { \
22 num = -num; \
23 sign = 1; \
24 } \
25 else \
26 { \
27 sign = 0; \
28 } \
29 \
30 if (den < 0) \
31 { \
32 den = - den; \
33 sign = 1 - sign; \
34 } \
35 }
36
37
38
39
40
41 static unsigned long
divmodsi4(int modwanted,unsigned long num,unsigned long den)42 divmodsi4(int modwanted, unsigned long num, unsigned long den)
43 {
44 long int bit = 1;
45 long int res = 0;
46 long prevden;
47 while (den < num && bit && !(den & (1L<<31)))
48 {
49 den <<=1;
50 bit <<=1;
51 }
52 while (bit)
53 {
54 if (num >= den)
55 {
56 num -= den;
57 res |= bit;
58 }
59 bit >>=1;
60 den >>=1;
61 }
62 if (modwanted) return num;
63 return res;
64 }
65
66
67 #define exitdiv(sign, res) if (sign) { res = - res;} return res;
68
69 long
__modsi3(long numerator,long denominator)70 __modsi3 (long numerator, long denominator)
71 {
72 int sign = 0;
73 long dividend;
74 long modul;
75
76
77 if (numerator < 0)
78 {
79 numerator = -numerator;
80 sign = 1;
81 }
82 if (denominator < 0)
83 {
84 denominator = -denominator;
85 }
86
87 modul = divmodsi4 (1, numerator, denominator);
88 if (sign)
89 return - modul;
90 return modul;
91 }
92
93
94 long
__divsi3(long numerator,long denominator)95 __divsi3 (long numerator, long denominator)
96 {
97 int sign;
98 long dividend;
99 long modul;
100 divnorm (numerator, denominator, sign);
101
102 dividend = divmodsi4 (0, numerator, denominator);
103 exitdiv (sign, dividend);
104 }
105
106 long
__umodsi3(unsigned long numerator,unsigned long denominator)107 __umodsi3 (unsigned long numerator, unsigned long denominator)
108 {
109 long dividend;
110 long modul;
111
112 modul= divmodsi4 (1, numerator, denominator);
113 return modul;
114 }
115
116 long
__udivsi3(unsigned long numerator,unsigned long denominator)117 __udivsi3 (unsigned long numerator, unsigned long denominator)
118 {
119 int sign;
120 long dividend;
121 long modul;
122 dividend = divmodsi4 (0, numerator, denominator);
123 return dividend;
124 }
125
126
127
128
129
130
131 #ifdef TEST
132
133
134
main()135 main ()
136 {
137 long int i, j, k, m;
138 for (i = -10000; i < 10000; i += 8)
139 {
140 for (j = -10000; j < 10000; j += 11)
141 {
142 k = i / j;
143 m = __divsi3 (i, j);
144 if (k != m)
145 printf ("fail %d %d %d %d\n", i, j, k, m);
146 }
147 }
148 }
149
150 #endif
151