utils/bits.3: Basically rewrite it, filling in the missing things.
[mLib] / utils / bits.3
CommitLineData
b6b9d458 1.\" -*-nroff-*-
fbf20b5b 2.TH bits 3 "20 June 1999" "Straylight/Edgeware" "mLib utilities library"
a9779382
MW
3.ie t \{\
4. ds ss \s8\u
5. ds se \d\s0
6.\}
7.el \{\
8. ds ss ^
9. ds se
10.\}
b6b9d458 11.SH NAME
12bits \- portable bit manipulation macros
a9779382
MW
13.\" octet
14.\" uint16
15.\" uint24
16.\" uint32
17.\" uint64
18.\" kludge64
19.\"
20.\" MASK_8
21.\" MASK_16
22.\" MASK_16_L
23.\" MASK_16_B
24.\" MASK_24
25.\" MASK_24_L
26.\" MASK_24_B
27.\" MASK_32
28.\" MASK_32_L
29.\" MASK_32_B
30.\" MASK_64
31.\" MASK_64_L
32.\" MASK_64_B
33.\"
34.\" SZ_8
35.\" SZ_16
36.\" SZ_16_L
37.\" SZ_16_B
38.\" SZ_24
39.\" SZ_24_L
40.\" SZ_24_B
41.\" SZ_32
42.\" SZ_32_L
43.\" SZ_32_B
44.\" SZ_64
45.\" SZ_64_L
46.\" SZ_64_B
47.\"
48.\" TY_8
49.\" TY_16
50.\" TY_16_L
51.\" TY_16_B
52.\" TY_24
53.\" TY_24_L
54.\" TY_24_B
55.\" TY_32
56.\" TY_32_L
57.\" TY_32_B
58.\" TY_64
59.\" TY_64_L
60.\" TY_64_B
61.\"
62.\" DOUINTSZ
63.\" DOUINTCONV
64.\"
08da152e 65.\" @U8
66.\" @U16
a9779382 67.\" @U24
08da152e 68.\" @U32
a9779382
MW
69.\" @U64
70.\" @U64_
08da152e 71.\"
72.\" @LSL8
73.\" @LSR8
74.\" @LSL16
75.\" @LSR16
a9779382
MW
76.\" @LSL24
77.\" @LSR24
08da152e 78.\" @LSL32
79.\" @LSR32
a9779382
MW
80.\" @LSL64
81.\" @LSR64
82.\" @LSL64_
83.\" @LSR64_
08da152e 84.\"
85.\" @ROL8
86.\" @ROR8
87.\" @ROL16
88.\" @ROR16
a9779382
MW
89.\" @ROL24
90.\" @ROR24
91.\" @ROL32
08da152e 92.\" @ROL32
a9779382
MW
93.\" @ROL64
94.\" @ROR64
95.\" @ROL64_
96.\" @ROR64_
08da152e 97.\"
98.\" @GETBYTE
99.\" @PUTBYTE
100.\"
101.\" @LOAD8
102.\" @STORE8
103.\"
104.\" @LOAD16_L
105.\" @LOAD16_B
106.\" @LOAD16
107.\" @STORE16_L
108.\" @STORE16_B
109.\" @STORE16
110.\"
a9779382
MW
111.\" @LOAD24_L
112.\" @LOAD24_B
113.\" @LOAD24
114.\" @STORE24_L
115.\" @STORE24_B
116.\" @STORE24
117.\"
08da152e 118.\" @LOAD32_L
119.\" @LOAD32_B
120.\" @LOAD32
121.\" @STORE32_L
122.\" @STORE32_B
123.\" @STORE32
124.\"
a9779382
MW
125.\" @LOAD64_L
126.\" @LOAD64_B
127.\" @LOAD64
128.\" @STORE64_L
129.\" @STORE64_B
130.\" @STORE64
131.\"
132.\" @LOAD64_L_
133.\" @LOAD64_B_
134.\" @LOAD64_
135.\" @STORE64_L_
136.\" @STORE64_B_
137.\" @STORE64_
138.\"
139.\" @SET64
140.\" @X64
141.\" @ASSIGN64
142.\" @HI64
143.\" @LO64
144.\" @GET64
145.\" @AND64
146.\" @OR64
147.\" @XOR64
148.\" @CPL64
149.\" @ADD64
150.\" @SUB64
151.\" @CMP64
152.\" @ZERO64
b6b9d458 153.SH SYNOPSIS
154.nf
155.B "#include <mLib/bits.h>"
156
a9779382
MW
157.BR "typedef " ... " octet;"
158.BR "typedef " ... " uint16;"
159.BR "typedef " ... " uint24;"
160.BR "typedef " ... " uint32;"
161.BR "typedef " ... " uint64;"
162.BR "typedef " ... " kludge64;"
163
164.BI "#define TY_" we " " type
165.BI "#define SZ_" we " \fR..."
166.BI "#define MASK_" we " \fR..."
b6b9d458 167
a9779382
MW
168.BI "#define DOUINTSZ(" f ") \fR..."
169.BI "#define DOUINTCONV(" f ") \fR..."
b6b9d458 170
a9779382 171.IB type " U" w ( v );
b6b9d458 172
a9779382
MW
173.IB type " LSL" w ( type " " v ", int " s );
174.IB type " LSR" w ( type " " v ", int " s );
175.IB type " ROL" w ( type " " v ", int " s );
176.IB type " ROR" w ( type " " v ", int " s );
b6b9d458 177
a9779382
MW
178.BI "octet GETBYTE(void *" p ", size_t " o );
179.BI "void PUTBYTE(void *" p ", size_t " o ", octet " v );
b6b9d458 180
a9779382
MW
181.IB type " LOAD" we "(void *" p );
182.BI "void STORE" we "(void *" p ", " type " " v );
b6b9d458 183
a9779382
MW
184.BI "void SET64(kludge64 &" d ", uint32 " h ", uint32 " l );
185.BI "kludge64 X64(" hexh ", " hexl );
186.BI "void ASSIGN64(kludge64 &" d ", " x );
187.BI "uint32 HI64(kludge64" x );
188.BI "uint32 LO64(kludge64" x );
189.IB ty " GET64(" ty ", kludge64 " x );
190.BI "void AND64(kludge64 &" d ", kludge64 " x ", kludge64 " y );
191.BI "void OR64(kludge64 &" d ", kludge64 " x ", kludge64 " y );
192.BI "void XOR64(kludge64 &" d ", kludge64 " x ", kludge64 " y );
193.BI "void CPL64(kludge64 &" d ", kludge64 " x );
194.BI "void ADD64(kludge64 &" d ", kludge64 " x ", kludge64 " y );
195.BI "void SUB64(kludge64 &" d ", kludge64 " x ", kludge64 " y );
196.BI "int CMP64(kludge64 " x ", " op ", kludge64 " y );
197.BI "int ZERO64(kludge64 " x );
b6b9d458 198.fi
199.SH DESCRIPTION
200The header file
201.B <mLib/bits.h>
202contains a number of useful definitions for portably dealing with bit-
a9779382
MW
203and byte-level manipulation of larger quantities. The various macros
204and types are named fairly systematically.
205.PP
206The header provides utilities for working with 64-bit quantities, but a
20764-bit integer type is not guaranteed to exist under C89 rules. This
208header takes two approaches. Firstly, if a 64-bit type is found, the
209header defines the macro
210.B HAVE_UINT64
211and defines the various
212.RB ... 64
213macros as described below. Secondly, it unconditionally defines a type
214.B kludge64
215and a family of macros for working with them. See below for details.
216.
217.SS "Type definitions"
218A number of types are defined.
b6b9d458 219.TP
220.B octet
221Equivalent to
222.BR "unsigned char" .
223This is intended to be used when a character array is used to represent
224the octets of some external data format. Note that on some
225architectures the
226.B "unsigned char"
227type may occupy more than 8 bits.
228.TP
229.B uint16
230Equivalent to
231.BR "unsigned short" .
232Intended to be used when a 16-bit value is required. This type is
233always capable of representing any 16-bit unsigned value, but the actual
234type may be wider than 16 bits and will require masking.
235.TP
a9779382
MW
236.B uint24
237Equivalent to some (architecture-dependent) standard type. Capable of
238representing any unsigned 24-bit value, although the the actual type may
239be wider than 24 bits.
240.TP
b6b9d458 241.B uint32
242Equivalent to some (architecture-dependent) standard type. Capable of
243representing any unsigned 32-bit value, although the the actual type may
244be wider than 32 bits.
a9779382
MW
245pp.TP
246.B uint64
247Equivalent to some (architecture-dependent) standard type, if it exists.
248Capable of representing any unsigned 64-bit value, although the the
249actual type may be wider than 64 bits.
250.
251.SS "Size/endianness suffixes"
252Let
253.I w
254be one of the size suffixes: 8, 16, 24, 32, and (if available) 64.
255Furthermore, let
256.I we
257be one of the size-and-endian suffixes
258.IR w ,
259or, where
260.IR w \~>\~8,
261.IB w _L
262or
263.IB w _B \fR,
264where
265.RB ` _L '
266denotes little-endian (Intel, VAX) representation, and
267.RB ` _B '
268denotes big-endian (IBM, network) representation; omitting an explicit
269suffix gives big-endian order by default, since this is most common in
270portable data formats.
b6b9d458 271.PP
a9779382
MW
272The macro invocation
273.BI DOUINTSZ( f )
274invokes a given macro
275.I f
276repeatedly, as
277.IB f ( w )
278for each size suffix
279.I w
280listed above.
b6b9d458 281.PP
a9779382
MW
282The macro invocation
283.BI DOUINTCONV( f )
284invokes a given macro
285.I f
286repeatedly, as
287.IR f ( w ", " we ", " suff )
b6b9d458 288where
a9779382
MW
289.I we
290ranges over size-and-endian suffixes as described above,
291.I w
292is just the corresponding bit width, as an integer, and
293.I suff
294is a suffix
295.IR w ,
296.IB w l\fR,
b6b9d458 297or
a9779382
MW
298.IB w b\fR,
299suitable for a C function name.
b6b9d458 300.PP
a9779382
MW
301These macros are intended to be used to define families of related
302functions.
303.
304.SS "Utility macros"
305For each size-and-endian suffix
306.IR we ,
307the following macros are defined.
308.TP
309.BI TY_ we
310A synonym for the appropriate one of the types
311.BR octet ,
312.BR uint32 ,
313etc.\& listed above.
314.TP
315.BI SZ_ we
316The number of octets needed to represent a value of the corresponding
317type; i.e., this is
318.IR w /8.
319.TP
320.BI MASK_ we
321The largest integer representable in the corresponding type; i.e., this
322is
323.RI 2\*(ss w \*(se\~\-\~1.
324.PP
325(Note that the endianness suffix is irrelevant in the above
326definitions.)
327.PP
328For each size suffix
329.IR w ,
330the macro invocation
331.BI U w ( x )
332coerces an integer
333.I x
334to the appropriate type; specifically, it returns the smallest
335nonnegative integer congruent to
336.I x
337(modulo
338.RI 2\*(ss w \*(se).
339.
340.SS "Shift and rotate"
341For each size suffix
342.IR w ,
343the macro invocations
344.BI LSL w ( x ", " n )
b6b9d458 345and
a9779382
MW
346.BI LSR w ( x ", " n )
347shift a
348.IR w -bit
349quantity
350.I x
351left or right, respectively, by
b6b9d458 352.I n
a9779382
MW
353places; if
354.IR n \~\(>=\~ w
355then
356.I n
357is reduced modulo
358.IR w .
359(This behaviour is unfortunate, but (a) it's what a number of CPUs
360provide natively, and (b) it's a cheap way to prevent undefined
361behaviour.) Similarly,
362.BI ROL w ( x ", " n )
b6b9d458 363and
a9779382
MW
364.BI ROR w ( x ", " n )
365rotate a
366.IR w -bit
367quantity
368.I x
369left or right, respectively, by
b6b9d458 370.I n
a9779382
MW
371places.
372.
373.SS "Load and store"
374The macro invocation
375.BI GETBYTE( p ", " o )
376returns the
377.IR o th
378octet following the address
379.IR p .
380Conversely,
381.BI PUTBYTE( p ", " o ", " v)
382stores
383.I
384v in the
385.IR o th
386byte following the address
387.IR p .
388These macros always operate on byte offsets regardless of the type of
389the pointer
390.IR p .
391.PP
392For each size-and-endian suffix
393.IR we ,
394the macro invocation
395.BI LOAD we ( p )
396loads and returns a value in the corresponding format at address
397.IR p ;
398similarly,
399.BI STORE we ( p ", " x )
400stores the value
401.I x
402at address
403.I p
404in the corresponding format.
405.
406.SS "64-bit support"
407For portability to environments without native 64-bit integers, the
408structure
409.B kludge64
410is defined. If the target platform is known to have an unsigned 64-bit
411integer type, then this structure merely encapsulates a native integer,
412and a decent optimizing compiler can be expected to handle this exactly
413as if it were the native type. Otherwise, it contains two 32-bit halves
414which are processed the hard way.
415.PP
416For each of the above macros with a suffix
417.BR 64 ,
418.BR 64_L ,
b6b9d458 419or
a9779382
MW
420.BR 64_B ,
421an additional `kludge' macro is defined, whose name has an additional
422final underscore; e.g., the kludge macro corresponding to
423.B ROR64
424is
425.BR ROR64_ ;
426and that corresponding to
427.B LOAD64_L
428is
429.BR LOAD64_L_ .
430If the original macro would have
431.I returned
432a value of type
433.BR uint64 ,
434then the kludge macro has an additional first argument, denoted
435.IR d ,
436which should be an lvalue of type
437.BR kludge64 ,
438and the kludge macro will store its result in
439.IR d .
440The kludge macro's remaining arguments are the same as the original
441macro, except that where the original macro accepts an argument of type
442.BR uint64 ,
443the kludge macro accepts an argument of type
444.B kludge64
445instead.
446.PP
447Finally, a number of additional macros are provided, to make working
448with
449.B kludge64
450somewhat less awful.
451.TP
452.BI SET64( d ", " h ", " l )
453Set the high 32 bits of
454.I d
455to be
456.IR h ,
457and the low 32 bits to be
458.IR l .
459Both
460.I h
461and
462.I l
463may be arbitrary integers.
464.TP
465.BI X64( hexh ", " hexl )
466Expands to an initializer for an object of type
467.B kludge64
468where
469.I hexh
470and
471.I hexl
472encode the high and low 32-bit halves in hexadecimal, without any
473.B 0x
474prefix.
475.TP
476.BI ASSIGN( d ", " x )
477Make
478.I d
479be a copy of the
480.B kludge64
481.IR x .
482.TP
483.BI HI64( x )
484Return the high 32 bits of
485.IR x .
486.TP
487.BI LO64( x )
488Return the low 32 bits of
489.IR x .
490.TP
491.BI GET64( t ", " x )
492Return the value of
493.I x
494as a value of type
495.IR t .
496If
497.I t
498is an unsigned integer type, then the value will be truncated to fit as
499necessary; if
500.I t
501is a signed integer type, then the behaviour is undefined if the value
502of
503.I x
504is too large.
505.TP
506.BI AND64( d ", " x ", " y )
507Set
508.I d
509to be the bitwise-and of the two
510.B kludge64
511arguments
512.I x
b6b9d458 513and
a9779382
MW
514.IR y .
515.TP
516.BI OR64( d ", " x ", " y )
517Set
518.I d
519to be the bitwise-or of the two
520.B kludge64
521arguments
522.I x
523and
524.IR y .
525.TP
526.BI XOR64( d ", " x ", " y )
527Set
528.I d
529to be the bitwise-exclusive-or of the two
530.B kludge64
531arguments
532.I x
533and
534.IR y .
535.TP
536.BI CPL64( d ", " x )
537Set
538.I d
539to be the bitwise complement of the
540.B kludge64
541argument
542.IR x .
543.TP
544.BI ADD64( d ", " x ", " y )
545Set
546.I d
547to be the sum of the two
548.B kludge64
549arguments
550.I x
551and
552.IR y .
553.TP
554.BI SUB64( d ", " x ", " y )
555Set
556.I d
557to be the difference of the two
558.B kludge64
559arguments
560.I x
561and
562.IR y .
563.TP
564.BI CMP64( x ", " op ", " y )
565Here,
566.I x
567and
568.I y
569should be arguments of type
570.B kludge64
571and
572.I op
573should be one of the relational operators
574.BR == ,
575.BR < ,
576.BR <= ,
577.BR > ,
578or
579.B >=
580\(en
581.I not
582.BR !=.
583Evaluates nonzero if
584.IR x \~ op \~ y .
585.TP
586.BI ZERO64( x )
587Evaluates nonzero if the
588.B kludge64
589argument
590.I x
591is exactly zero.
08da152e 592.SH "SEE ALSO"
593.BR mLib (3).
b6b9d458 594.SH AUTHOR
9b5ac6ff 595Mark Wooding, <mdw@distorted.org.uk>
b6b9d458 596