2 * These functions implement bitfield and bitmap operations for any possible CPU
3 * Used instead of m68k asm functions in asmsupport.s file.
6 #include <exec/types.h>
9 #include <aros/macros.h>
10 #include <aros/asmcall.h>
12 #define AROS_BE2LONG(x) x
13 #define AROS_LONG2BE(x) x
17 #include "asmsupport.h"
21 static inline LONG
frs(ULONG mask
)
26 asm volatile("bsf %1, %0":"=r"(bit
):"rm"(mask
));
32 static inline LONG
frs(ULONG mask
)
39 for (bit
= 32; (mask
& 1) != 1; bit
--)
46 /* Finds last set bit in /data/ starting at /bitoffset/. This function
47 considers the MSB to be the first bit. */
48 static inline WORD
bfflo(ULONG data
, WORD bitoffset
)
50 ULONG mask
= 0xffffffff << (31-bitoffset
);
52 return data
== 0 ? -1 : frs(data
)-1;
55 /* Finds last zero bit in /data/ starting at /bitoffset/. This function
56 considers the MSB to be the first bit. */
57 static inline WORD
bfflz(ULONG data
, WORD bitoffset
)
59 return bfflo(~data
, bitoffset
);
62 /* Sets /bits/ bits starting from /bitoffset/ in /data/.
63 /bits/ must be between 1 and 32. */
64 static inline ULONG
bfset(ULONG data
, WORD bitoffset
, WORD bits
)
66 ULONG mask
= ~((1 << (32 - bits
)) - 1);
71 /* Clears /bits/ bits starting from /bitoffset/ in /data/.
72 /bits/ must be between 1 and 32. */
73 static inline ULONG
bfclr(ULONG data
, WORD bitoffset
, WORD bits
)
75 ULONG mask
= ~((1 << (32 - bits
)) - 1);
82 ULONG
const w
= v
- ((v
>> 1) & 0x55555555); // temp
83 ULONG
const x
= (w
& 0x33333333) + ((w
>> 2) & 0x33333333); // temp
84 ULONG
const c
= (((x
+ (x
>> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; // count
94 LONG
bmflo(ULONG
*bitmap
, LONG bitoffset
)
100 longoffset
= (bitoffset
) >> 5;
104 bitoffset
= bitoffset
& 0x1F;
106 if (bitoffset
!= 0) {
107 if ((bit
= bfflo(AROS_BE2LONG(*scan
), bitoffset
)) >= 0) {
108 return (bit
+ ((scan
- bitmap
) << 5));
114 while (longs
-- >= 0) {
117 return (bfflo(AROS_BE2LONG(*scan
),31) + ((scan
- bitmap
) << 5));
124 LONG
bmflz(ULONG
*bitmap
, LONG bitoffset
)
126 ULONG
*scan
= bitmap
;
130 longoffset
= (bitoffset
) >> 5;
134 bitoffset
= bitoffset
& 0x1F;
136 if (bitoffset
!= 0) {
137 if ((bit
= bfflz(AROS_BE2LONG(*scan
), bitoffset
)) >= 0) {
138 return (bit
+ ((scan
- bitmap
) << 5));
144 while (longs
-- >= 0) {
145 if (*scan
-- != 0xFFFFFFFF) {
147 return (bfflz(AROS_BE2LONG(*scan
),31) + ((scan
- bitmap
) << 5));
154 /* This function finds the first set bit in a region of memory starting
155 with /bitoffset/. The region of memory is /longs/ longs long. It
156 returns the bitoffset of the first set bit it finds. */
158 LONG
bmffo(ULONG
*bitmap
, LONG longs
, LONG bitoffset
)
160 ULONG
*scan
= bitmap
;
161 ULONG err
= 32*longs
;
164 longoffset
= bitoffset
>> 5;
168 bitoffset
= bitoffset
& 0x1F;
170 if (bitoffset
!= 0) {
171 if ((bit
= bfffo(AROS_BE2LONG(*scan
), bitoffset
)) < 32) {
172 return (bit
+ ((scan
- bitmap
) << 5));
178 while (longs
-- > 0) {
181 return (bfffo(AROS_BE2LONG(*scan
),0) + ((scan
- bitmap
) << 5));
188 /* This function finds the first unset bit in a region of memory starting
189 with /bitoffset/. The region of memory is /longs/ longs long. It
190 returns the bitoffset of the first unset bit it finds. */
192 LONG
bmffz(ULONG
*bitmap
, LONG longs
, LONG bitoffset
)
194 ULONG
*scan
= bitmap
;
195 ULONG err
= 32*longs
;
198 longoffset
= bitoffset
>> 5;
202 bitoffset
= bitoffset
& 0x1F;
204 if (bitoffset
!= 0) {
205 if ((bit
= bfffz(AROS_BE2LONG(*scan
), bitoffset
)) < 32) {
206 return (bit
+ ((scan
- bitmap
) << 5));
212 while (longs
-- > 0) {
213 if (*scan
++ != 0xFFFFFFFF) {
215 return (bfffz(AROS_BE2LONG(*scan
),0) + ((scan
- bitmap
) << 5));
222 /* This function clears /bits/ bits in a region of memory starting
223 with /bitoffset/. The region of memory is /longs/ longs long. If
224 the region of memory is too small to clear /bits/ bits then this
225 function exits after having cleared all bits till the end of the
226 memory region. In any case it returns the number of bits which
227 were actually cleared. */
229 LONG
bmclr(ULONG
*bitmap
, LONG longs
, LONG bitoffset
, LONG bits
)
231 ULONG
*scan
= bitmap
;
235 longoffset
= bitoffset
>> 5;
239 bitoffset
= bitoffset
& 0x1F;
241 if (bitoffset
!= 0) {
243 *scan
= AROS_LONG2BE(bfclr(AROS_BE2LONG(*scan
), bitoffset
, bits
));
245 *scan
= AROS_LONG2BE(bfclr(AROS_BE2LONG(*scan
), bitoffset
, 32));
249 bits
-= 32 - bitoffset
;
252 while (bits
> 0 && longs
-- > 0) {
256 *scan
= AROS_LONG2BE(bfclr(AROS_BE2LONG(*scan
), 0, bits
));
264 return (orgbits
- bits
);
267 /* This function sets /bits/ bits in a region of memory starting
268 with /bitoffset/. The region of memory is /longs/ longs long. If
269 the region of memory is too small to set /bits/ bits then this
270 function exits after having set all bits till the end of the
271 memory region. In any case it returns the number of bits which
272 were actually set. */
274 LONG
bmset(ULONG
*bitmap
, LONG longs
, LONG bitoffset
, LONG bits
)
276 ULONG
*scan
= bitmap
;
280 longoffset
= bitoffset
>> 5;
284 bitoffset
= bitoffset
& 0x1F;
286 if (bitoffset
!= 0) {
288 *scan
= AROS_LONG2BE(bfset(AROS_BE2LONG(*scan
), bitoffset
, bits
));
290 *scan
= AROS_LONG2BE(bfset(AROS_BE2LONG(*scan
), bitoffset
, 32));
294 bits
-= 32 - bitoffset
;
297 while (bits
> 0 && longs
-- > 0) {
299 *scan
++ = 0xFFFFFFFF;
301 *scan
= AROS_LONG2BE(bfset(AROS_BE2LONG(*scan
), 0, bits
));
309 return (orgbits
- bits
);
312 BOOL
bmtsto(ULONG
*bitmap
, LONG bitoffset
, LONG bits
)
314 LONG longoffset
= bitoffset
>> 5;
315 ULONG
*scan
= bitmap
;
323 if ((bits
+ bitoffset
) < 32)
325 mask
= (0xffffffff >> bitoffset
) & (0xffffffff << (32 - (bits
+bitoffset
)));
330 mask
= (0xffffffff >> bitoffset
);
331 bits
-= (32-bitoffset
);
334 if ((mask
& AROS_BE2LONG(*scan
)) != mask
)
348 mask
= 0xffffffff << (32-bits
);
351 if ((mask
& AROS_BE2LONG(*scan
)) != mask
)
359 BOOL
bmtstz(ULONG
*bitmap
, LONG bitoffset
, LONG bits
)
361 LONG longoffset
= bitoffset
>> 5;
362 ULONG
*scan
= bitmap
;
370 if ((bits
+ bitoffset
) < 32)
372 mask
= (0xffffffff >> bitoffset
) & (0xffffffff << (32 - (bits
+bitoffset
)));
377 mask
= (0xffffffff >> bitoffset
);
378 bits
-= (32-bitoffset
);
380 if ((mask
& AROS_BE2LONG(*scan
)) != 0)
394 mask
= 0xffffffff << (32-bits
);
397 if ((mask
& AROS_BE2LONG(*scan
)) != 0)
405 ULONG
bmcnto(ULONG
*bitmap
, LONG bitoffset
, LONG bits
)
407 LONG longoffset
= bitoffset
>> 5;
408 ULONG
*scan
= bitmap
;
417 if ((bits
+ bitoffset
) < 32)
419 mask
= (0xffffffff >> bitoffset
) & (0xffffffff << (32 - (bits
+bitoffset
)));
424 mask
= (0xffffffff >> bitoffset
);
425 bits
-= (32-bitoffset
);
427 count
+= bfcnto(AROS_BE2LONG(*scan
) & mask
);
440 mask
= 0xffffffff << (32-bits
);
443 count
+= bfcnto(AROS_BE2LONG(*scan
) & mask
);
450 ULONG
bmcntz(ULONG
*bitmap
, LONG bitoffset
, LONG bits
)
452 LONG longoffset
= bitoffset
>> 5;
453 ULONG
*scan
= bitmap
;
462 if ((bits
+ bitoffset
) < 32)
464 mask
= ~((0xffffffff >> bitoffset
) & (0xffffffff << (32 - (bits
+bitoffset
))));
469 mask
= ~(0xffffffff >> bitoffset
);
470 bits
-= (32-bitoffset
);
473 count
+= bfcntz(AROS_BE2LONG(*scan
) | mask
);
486 mask
= ~(0xffffffff << (32-bits
));
490 count
+= bfcntz(AROS_BE2LONG(*scan
) | mask
);
497 ULONG
CALCCHECKSUM(ULONG blocksize
, ULONG
*block
)
510 sum
+= (ULONG
)BE2L(*block
++);
511 sum
+= (ULONG
)BE2L(*block
++);
512 sum
+= (ULONG
)BE2L(*block
++);
513 sum
+= (ULONG
)BE2L(*block
++);