Kernel/armv7 - Fixing/breaking things
[tpg/acess2.git] / Kernel / arch / armv7 / lib.c
1 /*
2  * Acess2 ARM7 Port
3  *
4  * lib.c - Library Functions
5  */
6 #include <acess.h>
7
8 // === PROTOTYPES ===
9 Uint64  __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem);
10 Uint32  __divmod32(Uint32 Num, Uint32 Den, Uint32 *Rem);
11 Uint64  __udivdi3(Uint64 Num, Uint64 Den);
12 Uint64  __umoddi3(Uint64 Num, Uint64 Den);
13 Uint32  __udivsi3(Uint32 Num, Uint32 Den);
14 Uint32  __umodsi3(Uint32 Num, Uint32 Den);
15 Sint32  __divsi3(Sint32 Num, Sint32 Den);
16 Sint32  __modsi3(Sint32 Num, Sint32 Den);
17
18 // === CODE ===
19 void *memcpy(void *_dest, const void *_src, size_t _length)
20 {
21         Uint32  *dst;
22         const Uint32    *src;
23         Uint8   *dst8 = _dest;
24         const Uint8     *src8 = _src;
25
26         // Handle small copies / Non-aligned
27         if( _length < 4 || ((tVAddr)_dest & 3) != ((tVAddr)_src & 3) )
28         {
29                 for( ; _length--; dst8++,src8++ )
30                         *dst8 = *src8;
31                 return _dest;
32         }
33
34         // Force alignment
35         while( (tVAddr)dst8 & 3 ) *dst8 ++ = *src8++;
36         dst = (void *)dst8;     src = (void *)src8;
37
38         // DWORD copies
39         for( ; _length > 3; _length -= 4)
40                 *dst++ = *src++;
41
42         // Trailing bytes
43         dst8 = (void*)dst;      src8 = (void*)src;
44         for( ; _length; _length -- )
45                 *dst8 ++ = *src8 ++;
46         
47         return _dest;
48 }
49
50 int memcmp(const void *_m1, const void *_m2, size_t _length)
51 {
52         const Uint32    *m1, *m2;
53         const Uint8     *m1_8 = _m1, *m2_8 = _m2;
54
55         // Handle small copies / Non-aligned
56         if( _length < 4 || ((tVAddr)_m1 & 3) != ((tVAddr)_m1 & 3) )
57         {
58                 for( ; _length--; m1_8++,m2_8++ ) {
59                         if(*m1_8 != *m2_8)      return *m1_8 - *m2_8;
60                 }
61                 return 0;
62         }
63
64         // Force alignment
65         for( ; (tVAddr)m1_8 & 3; m1_8 ++, m2_8 ++) {
66                 if(*m1_8 != *m2_8)      return *m1_8 - *m2_8;
67         }
68         m1 = (void *)m1_8;      m2 = (void *)m2_8;
69
70         // DWORD copies
71         for( ; _length > 3; _length -= 4, m1++, m2++)
72                 if(*m1 != *m2)  return *m1 - *m2;
73
74         // Trailing bytes
75         m1_8 = (void*)m1;       m2_8 = (void*)m2;
76         for( ; _length; _length --, m1_8++, m2_8++ )
77                 if(*m1_8 != *m2_8)      return *m1_8 - *m2_8;
78         
79         return 0;
80 }
81
82 void *memset(void *_dest, int _value, size_t _length)
83 {
84         Uint32  *dst, val32;
85         Uint8   *dst8 = _dest;
86
87         _value = (Uint8)_value;
88
89         // Handle small copies / Non-aligned
90         if( _length < 4 )
91         {
92                 for( ; _length--; dst8++ )
93                         *dst8 = _value;
94                 return _dest;
95         }
96
97         val32 = _value;
98         val32 |= val32 << 8;
99         val32 |= val32 << 16;
100         
101         // Force alignment
102         while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value;
103         dst = (void *)dst8;
104
105         // DWORD copies
106         for( ; _length > 3; _length -= 4)
107                 *dst++ = val32;
108
109         // Trailing bytes
110         dst8 = (void*)dst;
111         for( ; _length; _length -- )
112                 *dst8 ++ = _value;
113         
114         return _dest;
115 }
116
117 // Divide
118 // - Find what power of two times Den is > Num
119 // - Iterate down in bit significance
120 //  > If the `N` value is greater than `D`, we can set this bit
121 #define DEF_DIVMOD(s) Uint##s __divmod##s(Uint##s N, Uint##s D, Uint##s*Rem){\
122         Uint##s ret=0,add=1;\
123         while(N>=D&&add) {D<<=1;add<<=1;}\
124         while(add>1){\
125                 add>>=1;D>>=1;\
126                 if(N>=D){ret+=add;N-=D;}\
127         }\
128         if(Rem)*Rem = N;\
129         return ret;\
130 }
131
132 DEF_DIVMOD(64)
133 DEF_DIVMOD(32)
134
135
136 Uint64 DivMod64U(Uint64 Num, Uint64 Den, Uint64 *Rem)
137 {
138         Uint64  ret;
139         if(Den == 0)    return 0;       // TODO: #div0
140         if(Num == 0) {
141                 if(Rem) *Rem = 0;
142                 return 0;
143         }
144         if(Den == 1) {
145                 if(Rem) *Rem = 0;
146                 return Num;
147         }
148         if(Den == 2) {
149                 if(Rem) *Rem = Num & 1;
150                 return Num >> 1;
151         }
152         if(Den == 16) {
153                 if(Rem) *Rem = Num & 0xF;
154                 return Num >> 4;
155         }
156         if(Den == 32) {
157                 if(Rem) *Rem = Num & 0x1F;
158                 return Num >> 5;
159         }
160         if(Den == 0x1000) {
161                 if(Rem) *Rem = Num & 0xFFF;
162                 return Num >> 12;
163         }
164
165         ret = __divmod64(Num, Den, Rem);
166         return ret;
167 }
168
169 // Unsigned Divide 64-bit Integer
170 Uint64 __udivdi3(Uint64 Num, Uint64 Den)
171 {
172         return DivMod64U(Num, Den, NULL);
173 }
174
175 // Unsigned Modulus 64-bit Integer
176 Uint64 __umoddi3(Uint64 Num, Uint64 Den)
177 {
178         Uint64  ret = 0;
179         DivMod64U(Num, Den, &ret);
180         return ret;
181 }
182
183 Uint32 __udivsi3(Uint32 Num, Uint32 Den)
184 {
185         return __divmod32(Num, Den, NULL);
186 }
187
188 Uint32 __umodsi3(Uint32 Num, Uint32 Den)
189 {
190         Uint32  rem;
191         __divmod32(Num, Den, &rem);
192         return rem;
193 }
194
195 static inline Sint32 DivMod32S(Sint32 Num, Sint32 Den, Sint32 *Rem)
196 {
197         Sint32  ret = 1;
198         if( Num < 0 ) {
199                 ret = -ret;
200                 Num = -Num;
201         }
202         if( Den < 0 ) {
203                 ret = -ret;
204                 Den = -Den;
205         }
206         if(ret < 0)
207                 ret = -__divmod32(Num, Den, (Uint32*)Rem);
208         else
209                 ret = __divmod32(Num, Den, (Uint32*)Rem);
210         return ret;
211 }
212
213 Sint32 __divsi3(Sint32 Num, Sint32 Den)
214 {
215         return DivMod32S(Num, Den, NULL);
216 }
217
218 Sint32 __modsi3(Sint32 Num, Sint32 Den)
219 {
220         Sint32  rem;
221         DivMod32S(Num, Den, &rem);
222         return rem;
223 }

UCC git Repository :: git.ucc.asn.au