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 #include <picolibc.h>
19
20 #define divnorm(num, den, sign) \
21 { \
22 if (num < 0) \
23 { \
24 num = -num; \
25 sign = 1; \
26 } \
27 else \
28 { \
29 sign = 0; \
30 } \
31 \
32 if (den < 0) \
33 { \
34 den = - den; \
35 sign = 1 - sign; \
36 } \
37 }
38
39
40
41
42
43 unsigned long
divmodsi4(int modwanted,unsigned long num,unsigned long den)44 divmodsi4(int modwanted, unsigned long num, unsigned long den)
45 {
46 long int bit = 1;
47 long int res = 0;
48 long prevden;
49 while (den < num && bit && !(den & (1L<<31)))
50 {
51 den <<=1;
52 bit <<=1;
53 }
54 while (bit)
55 {
56 if (num >= den)
57 {
58 num -= den;
59 res |= bit;
60 }
61 bit >>=1;
62 den >>=1;
63 }
64 if (modwanted) return num;
65 return res;
66 }
67
68
69 #define exitdiv(sign, res) if (sign) { res = - res;} return res;
70
71 long
__modsi3(long numerator,long denominator)72 __modsi3 (long numerator, long denominator)
73 {
74 int sign = 0;
75 long dividend;
76 long modul;
77
78
79 if (numerator < 0)
80 {
81 numerator = -numerator;
82 sign = 1;
83 }
84 if (denominator < 0)
85 {
86 denominator = -denominator;
87 }
88
89 modul = divmodsi4 (1, numerator, denominator);
90 if (sign)
91 return - modul;
92 return modul;
93 }
94
95
96 long
__divsi3(long numerator,long denominator)97 __divsi3 (long numerator, long denominator)
98 {
99 int sign;
100 long dividend;
101 long modul;
102 divnorm (numerator, denominator, sign);
103
104 dividend = divmodsi4 (0, numerator, denominator);
105 exitdiv (sign, dividend);
106 }
107
108 long
__umodsi3(unsigned long numerator,unsigned long denominator)109 __umodsi3 (unsigned long numerator, unsigned long denominator)
110 {
111 long dividend;
112 long modul;
113
114 modul= divmodsi4 (1, numerator, denominator);
115 return modul;
116 }
117
118 long
__udivsi3(unsigned long numerator,unsigned long denominator)119 __udivsi3 (unsigned long numerator, unsigned long denominator)
120 {
121 int sign;
122 long dividend;
123 long modul;
124 dividend = divmodsi4 (0, numerator, denominator);
125 return dividend;
126 }
127
128
129
130
131
132
133 #include <picolibc.h>
134
135 #ifdef TEST
136
137
138
main()139 main ()
140 {
141 long int i, j, k, m;
142 for (i = -10000; i < 10000; i += 8)
143 {
144 for (j = -10000; j < 10000; j += 11)
145 {
146 k = i / j;
147 m = __divsi3 (i, j);
148 if (k != m)
149 printf ("fail %d %d %d %d\n", i, j, k, m);
150 }
151 }
152 }
153
154 #endif
155