| 1 | .\" -*-nroff-*- |
| 2 | .TH bits 3 "20 June 1999" "Straylight/Edgeware" "mLib utilities library" |
| 3 | .ie t \{\ |
| 4 | . ds ss \s8\u |
| 5 | . ds se \d\s0 |
| 6 | .\} |
| 7 | .el \{\ |
| 8 | . ds ss ^ |
| 9 | . ds se |
| 10 | .\} |
| 11 | .SH NAME |
| 12 | bits \- portable bit manipulation macros |
| 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 | .\" |
| 65 | .\" @U8 |
| 66 | .\" @U16 |
| 67 | .\" @U24 |
| 68 | .\" @U32 |
| 69 | .\" @U64 |
| 70 | .\" @U64_ |
| 71 | .\" |
| 72 | .\" @LSL8 |
| 73 | .\" @LSR8 |
| 74 | .\" @LSL16 |
| 75 | .\" @LSR16 |
| 76 | .\" @LSL24 |
| 77 | .\" @LSR24 |
| 78 | .\" @LSL32 |
| 79 | .\" @LSR32 |
| 80 | .\" @LSL64 |
| 81 | .\" @LSR64 |
| 82 | .\" @LSL64_ |
| 83 | .\" @LSR64_ |
| 84 | .\" |
| 85 | .\" @ROL8 |
| 86 | .\" @ROR8 |
| 87 | .\" @ROL16 |
| 88 | .\" @ROR16 |
| 89 | .\" @ROL24 |
| 90 | .\" @ROR24 |
| 91 | .\" @ROL32 |
| 92 | .\" @ROL32 |
| 93 | .\" @ROL64 |
| 94 | .\" @ROR64 |
| 95 | .\" @ROL64_ |
| 96 | .\" @ROR64_ |
| 97 | .\" |
| 98 | .\" ENDSWAP16 |
| 99 | .\" ENDSWAP32 |
| 100 | .\" ENDSWAP64 |
| 101 | .\" |
| 102 | .\" BTOH16 |
| 103 | .\" LTOH16 |
| 104 | .\" HTOB16 |
| 105 | .\" HTOL16 |
| 106 | .\" BTOH32 |
| 107 | .\" LTOH32 |
| 108 | .\" HTOB32 |
| 109 | .\" HTOL32 |
| 110 | .\" BTOH64 |
| 111 | .\" LTOH64 |
| 112 | .\" HTOB64 |
| 113 | .\" HTOL64 |
| 114 | .\" |
| 115 | .\" RAW8 |
| 116 | .\" RAW16 |
| 117 | .\" RAW32 |
| 118 | .\" RAW64 |
| 119 | .\" |
| 120 | .\" @GETBYTE |
| 121 | .\" @PUTBYTE |
| 122 | .\" |
| 123 | .\" @LOAD8 |
| 124 | .\" @STORE8 |
| 125 | .\" |
| 126 | .\" @LOAD16_L |
| 127 | .\" @LOAD16_B |
| 128 | .\" @LOAD16 |
| 129 | .\" @STORE16_L |
| 130 | .\" @STORE16_B |
| 131 | .\" @STORE16 |
| 132 | .\" |
| 133 | .\" @LOAD24_L |
| 134 | .\" @LOAD24_B |
| 135 | .\" @LOAD24 |
| 136 | .\" @STORE24_L |
| 137 | .\" @STORE24_B |
| 138 | .\" @STORE24 |
| 139 | .\" |
| 140 | .\" @LOAD32_L |
| 141 | .\" @LOAD32_B |
| 142 | .\" @LOAD32 |
| 143 | .\" @STORE32_L |
| 144 | .\" @STORE32_B |
| 145 | .\" @STORE32 |
| 146 | .\" |
| 147 | .\" @LOAD64_L |
| 148 | .\" @LOAD64_B |
| 149 | .\" @LOAD64 |
| 150 | .\" @STORE64_L |
| 151 | .\" @STORE64_B |
| 152 | .\" @STORE64 |
| 153 | .\" |
| 154 | .\" @LOAD64_L_ |
| 155 | .\" @LOAD64_B_ |
| 156 | .\" @LOAD64_ |
| 157 | .\" @STORE64_L_ |
| 158 | .\" @STORE64_B_ |
| 159 | .\" @STORE64_ |
| 160 | .\" |
| 161 | .\" @SET64 |
| 162 | .\" @X64 |
| 163 | .\" @ASSIGN64 |
| 164 | .\" @HI64 |
| 165 | .\" @LO64 |
| 166 | .\" @GET64 |
| 167 | .\" @AND64 |
| 168 | .\" @OR64 |
| 169 | .\" @XOR64 |
| 170 | .\" @CPL64 |
| 171 | .\" @ADD64 |
| 172 | .\" @SUB64 |
| 173 | .\" @CMP64 |
| 174 | .\" @ZERO64 |
| 175 | .SH SYNOPSIS |
| 176 | .nf |
| 177 | .B "#include <mLib/bits.h>" |
| 178 | |
| 179 | .BR "typedef " ... " octet;" |
| 180 | .BR "typedef " ... " uint16;" |
| 181 | .BR "typedef " ... " uint24;" |
| 182 | .BR "typedef " ... " uint32;" |
| 183 | .BR "typedef " ... " uint64;" |
| 184 | .BR "typedef " ... " kludge64;" |
| 185 | |
| 186 | .BI "#define TY_" we " " type |
| 187 | .BI "#define SZ_" we " \fR..." |
| 188 | .BI "#define MASK_" we " \fR..." |
| 189 | |
| 190 | .BI "#define DOUINTSZ(" f ") \fR..." |
| 191 | .BI "#define DOUINTCONV(" f ") \fR..." |
| 192 | |
| 193 | .IB type " U" w ( v ); |
| 194 | |
| 195 | .IB type " LSL" w ( type " " v ", int " s ); |
| 196 | .IB type " LSR" w ( type " " v ", int " s ); |
| 197 | .IB type " ROL" w ( type " " v ", int " s ); |
| 198 | .IB type " ROR" w ( type " " v ", int " s ); |
| 199 | |
| 200 | .BI "octet GETBYTE(void *" p ", size_t " o ); |
| 201 | .BI "void PUTBYTE(void *" p ", size_t " o ", octet " v ); |
| 202 | |
| 203 | .IB type " LOAD" we "(void *" p ); |
| 204 | .BI "void STORE" we "(void *" p ", " type " " v ); |
| 205 | |
| 206 | .BI "void SET64(kludge64 &" d ", uint32 " h ", uint32 " l ); |
| 207 | .BI "kludge64 X64(" hexh ", " hexl ); |
| 208 | .BI "void ASSIGN64(kludge64 &" d ", " x ); |
| 209 | .BI "uint32 HI64(kludge64" x ); |
| 210 | .BI "uint32 LO64(kludge64" x ); |
| 211 | .IB ty " GET64(" ty ", kludge64 " x ); |
| 212 | .BI "void AND64(kludge64 &" d ", kludge64 " x ", kludge64 " y ); |
| 213 | .BI "void OR64(kludge64 &" d ", kludge64 " x ", kludge64 " y ); |
| 214 | .BI "void XOR64(kludge64 &" d ", kludge64 " x ", kludge64 " y ); |
| 215 | .BI "void CPL64(kludge64 &" d ", kludge64 " x ); |
| 216 | .BI "void ADD64(kludge64 &" d ", kludge64 " x ", kludge64 " y ); |
| 217 | .BI "void SUB64(kludge64 &" d ", kludge64 " x ", kludge64 " y ); |
| 218 | .BI "int CMP64(kludge64 " x ", " op ", kludge64 " y ); |
| 219 | .BI "int ZERO64(kludge64 " x ); |
| 220 | .fi |
| 221 | .SH DESCRIPTION |
| 222 | The header file |
| 223 | .B <mLib/bits.h> |
| 224 | contains a number of useful definitions for portably dealing with bit- |
| 225 | and byte-level manipulation of larger quantities. The various macros |
| 226 | and types are named fairly systematically. |
| 227 | .PP |
| 228 | The header provides utilities for working with 64-bit quantities, but a |
| 229 | 64-bit integer type is not guaranteed to exist under C89 rules. This |
| 230 | header takes two approaches. Firstly, if a 64-bit type is found, the |
| 231 | header defines the macro |
| 232 | .B HAVE_UINT64 |
| 233 | and defines the various |
| 234 | .RB ... 64 |
| 235 | macros as described below. Secondly, it unconditionally defines a type |
| 236 | .B kludge64 |
| 237 | and a family of macros for working with them. See below for details. |
| 238 | . |
| 239 | .SS "Type definitions" |
| 240 | A number of types are defined. |
| 241 | .TP |
| 242 | .B octet |
| 243 | Equivalent to |
| 244 | .BR "unsigned char" . |
| 245 | This is intended to be used when a character array is used to represent |
| 246 | the octets of some external data format. Note that on some |
| 247 | architectures the |
| 248 | .B "unsigned char" |
| 249 | type may occupy more than 8 bits. |
| 250 | .TP |
| 251 | .B uint16 |
| 252 | Equivalent to |
| 253 | .BR "unsigned short" . |
| 254 | Intended to be used when a 16-bit value is required. This type is |
| 255 | always capable of representing any 16-bit unsigned value, but the actual |
| 256 | type may be wider than 16 bits and will require masking. |
| 257 | .TP |
| 258 | .B uint24 |
| 259 | Equivalent to some (architecture-dependent) standard type. Capable of |
| 260 | representing any unsigned 24-bit value, although the the actual type may |
| 261 | be wider than 24 bits. |
| 262 | .TP |
| 263 | .B uint32 |
| 264 | Equivalent to some (architecture-dependent) standard type. Capable of |
| 265 | representing any unsigned 32-bit value, although the the actual type may |
| 266 | be wider than 32 bits. |
| 267 | pp.TP |
| 268 | .B uint64 |
| 269 | Equivalent to some (architecture-dependent) standard type, if it exists. |
| 270 | Capable of representing any unsigned 64-bit value, although the the |
| 271 | actual type may be wider than 64 bits. |
| 272 | . |
| 273 | .SS "Size/endianness suffixes" |
| 274 | Let |
| 275 | .I w |
| 276 | be one of the size suffixes: 8, 16, 24, 32, and (if available) 64. |
| 277 | Furthermore, let |
| 278 | .I we |
| 279 | be one of the size-and-endian suffixes |
| 280 | .IR w , |
| 281 | or, where |
| 282 | .IR w \~>\~8, |
| 283 | .IB w _L |
| 284 | or |
| 285 | .IB w _B \fR, |
| 286 | where |
| 287 | .RB ` _L ' |
| 288 | denotes little-endian (Intel, VAX) representation, and |
| 289 | .RB ` _B ' |
| 290 | denotes big-endian (IBM, network) representation; omitting an explicit |
| 291 | suffix gives big-endian order by default, since this is most common in |
| 292 | portable data formats. |
| 293 | .PP |
| 294 | The macro invocation |
| 295 | .BI DOUINTSZ( f ) |
| 296 | invokes a given macro |
| 297 | .I f |
| 298 | repeatedly, as |
| 299 | .IB f ( w ) |
| 300 | for each size suffix |
| 301 | .I w |
| 302 | listed above. |
| 303 | .PP |
| 304 | The macro invocation |
| 305 | .BI DOUINTCONV( f ) |
| 306 | invokes a given macro |
| 307 | .I f |
| 308 | repeatedly, as |
| 309 | .IR f ( w ", " we ", " suff ) |
| 310 | where |
| 311 | .I we |
| 312 | ranges over size-and-endian suffixes as described above, |
| 313 | .I w |
| 314 | is just the corresponding bit width, as an integer, and |
| 315 | .I suff |
| 316 | is a suffix |
| 317 | .IR w , |
| 318 | .IB w l\fR, |
| 319 | or |
| 320 | .IB w b\fR, |
| 321 | suitable for a C function name. |
| 322 | .PP |
| 323 | These macros are intended to be used to define families of related |
| 324 | functions. |
| 325 | . |
| 326 | .SS "Utility macros" |
| 327 | For each size-and-endian suffix |
| 328 | .IR we , |
| 329 | the following macros are defined. |
| 330 | .TP |
| 331 | .BI TY_ we |
| 332 | A synonym for the appropriate one of the types |
| 333 | .BR octet , |
| 334 | .BR uint32 , |
| 335 | etc.\& listed above. |
| 336 | .TP |
| 337 | .BI SZ_ we |
| 338 | The number of octets needed to represent a value of the corresponding |
| 339 | type; i.e., this is |
| 340 | .IR w /8. |
| 341 | .TP |
| 342 | .BI MASK_ we |
| 343 | The largest integer representable in the corresponding type; i.e., this |
| 344 | is |
| 345 | .RI 2\*(ss w \*(se\~\-\~1. |
| 346 | .PP |
| 347 | (Note that the endianness suffix is irrelevant in the above |
| 348 | definitions.) |
| 349 | .PP |
| 350 | For each size suffix |
| 351 | .IR w , |
| 352 | the macro invocation |
| 353 | .BI U w ( x ) |
| 354 | coerces an integer |
| 355 | .I x |
| 356 | to the appropriate type; specifically, it returns the smallest |
| 357 | nonnegative integer congruent to |
| 358 | .I x |
| 359 | (modulo |
| 360 | .RI 2\*(ss w \*(se). |
| 361 | . |
| 362 | .SS "Shift and rotate" |
| 363 | For each size suffix |
| 364 | .IR w , |
| 365 | the macro invocations |
| 366 | .BI LSL w ( x ", " n ) |
| 367 | and |
| 368 | .BI LSR w ( x ", " n ) |
| 369 | shift a |
| 370 | .IR w -bit |
| 371 | quantity |
| 372 | .I x |
| 373 | left or right, respectively, by |
| 374 | .I n |
| 375 | places; if |
| 376 | .IR n \~\(>=\~ w |
| 377 | then |
| 378 | .I n |
| 379 | is reduced modulo |
| 380 | .IR w . |
| 381 | (This behaviour is unfortunate, but (a) it's what a number of CPUs |
| 382 | provide natively, and (b) it's a cheap way to prevent undefined |
| 383 | behaviour.) Similarly, |
| 384 | .BI ROL w ( x ", " n ) |
| 385 | and |
| 386 | .BI ROR w ( x ", " n ) |
| 387 | rotate a |
| 388 | .IR w -bit |
| 389 | quantity |
| 390 | .I x |
| 391 | left or right, respectively, by |
| 392 | .I n |
| 393 | places. |
| 394 | . |
| 395 | .SS "Byte order conversions" |
| 396 | For each size suffix |
| 397 | .IR w , |
| 398 | the macro invocation |
| 399 | .BI ENDSWAP w ( x ) |
| 400 | returns the |
| 401 | .IR w -bit |
| 402 | value |
| 403 | .IR x |
| 404 | with its bytes reversed. The |
| 405 | .B ENDSWAP8 |
| 406 | macro does nothing (except truncate its operand to 8 bits), but is |
| 407 | provided for the sake of completeness. |
| 408 | .PP |
| 409 | A |
| 410 | .I big-endian |
| 411 | representation stores the most significant octet of an integer at the |
| 412 | lowest address, with the following octets in decreasing order of |
| 413 | significance. A |
| 414 | .I little-endian |
| 415 | representation instead stores the |
| 416 | .I least |
| 417 | significant octet at the lowest address, with the following octets in |
| 418 | increasing order of significance. An environment has a preferred order |
| 419 | for arranging the constituent octets of an integer of some given size in |
| 420 | memory; this might be either the big- or little-endian representation |
| 421 | just described, or something else strange. |
| 422 | .PP |
| 423 | It might be possible to rearrange the bits in an integer so that, when |
| 424 | that integer is stored to memory in the environment's preferred manner, |
| 425 | you end up with the big- or little-endian representation of the original |
| 426 | integer; and, similarly, it might be possible to load a big- or |
| 427 | little-endian representation of an integer into a variable using the |
| 428 | environment's preferred ordering and then rearrange the bits so as to |
| 429 | recover the integer value originally represented. If the environment is |
| 430 | sufficiently strange, these things might not be possible, but this is |
| 431 | actually quite rare. |
| 432 | .PP |
| 433 | Say that an integer has been converted to |
| 434 | .I big- |
| 435 | or |
| 436 | .I "little-endian form" |
| 437 | if, when it is stored in memory in the environment's preferred manner, |
| 438 | one ends up with a big- or little-endian representation of the original |
| 439 | integer. Equivalently, if one starts with a big- or little-endian |
| 440 | representation of some integer, and loads it into a variable using the |
| 441 | environment's preferred manner, one ends up with the big- or |
| 442 | little-endian form of the original integer. |
| 443 | .PP |
| 444 | If these things are possible, then the following macros are defined. |
| 445 | .TP |
| 446 | .BI HTOL w ( x ) |
| 447 | Convert a |
| 448 | .IR w -bit |
| 449 | integer |
| 450 | .I x |
| 451 | to little-endian form. |
| 452 | .TP |
| 453 | .BI HTOB w ( x ) |
| 454 | Convert a |
| 455 | .IR w -bit |
| 456 | integer |
| 457 | .I x |
| 458 | to big-endian form. |
| 459 | .TP |
| 460 | .BI LTOH w ( x ) |
| 461 | Convert a |
| 462 | .IR w -bit |
| 463 | integer |
| 464 | .I x |
| 465 | from little-endian form. |
| 466 | .TP |
| 467 | .BI BTOH w ( x ) |
| 468 | Convert a |
| 469 | .IR w -bit |
| 470 | integer |
| 471 | .I x |
| 472 | from big-endian form. |
| 473 | . |
| 474 | .SS "Load and store" |
| 475 | The macro invocation |
| 476 | .BI GETBYTE( p ", " o ) |
| 477 | returns the |
| 478 | .IR o th |
| 479 | octet following the address |
| 480 | .IR p . |
| 481 | Conversely, |
| 482 | .BI PUTBYTE( p ", " o ", " v) |
| 483 | stores |
| 484 | .I |
| 485 | v in the |
| 486 | .IR o th |
| 487 | byte following the address |
| 488 | .IR p . |
| 489 | These macros always operate on byte offsets regardless of the type of |
| 490 | the pointer |
| 491 | .IR p . |
| 492 | .PP |
| 493 | For each size suffix |
| 494 | .IR w , |
| 495 | there may be a macro such that the invocation |
| 496 | .BI RAW w ( p ) |
| 497 | is an lvalue designating the |
| 498 | .IR w /8 |
| 499 | octets starting at address |
| 500 | .IR p , |
| 501 | interpreted according to the environment's preferred representation, |
| 502 | except that |
| 503 | .I p |
| 504 | need not be aligned in any particular fashion. There are many reasons |
| 505 | why this might not be possible; programmers are not normally expected to |
| 506 | use these macros directly, and they are documented in case they are |
| 507 | useful for special effects. |
| 508 | .PP |
| 509 | For each size-and-endian suffix |
| 510 | .IR we , |
| 511 | the macro invocation |
| 512 | .BI LOAD we ( p ) |
| 513 | loads and returns a value in the corresponding format at address |
| 514 | .IR p ; |
| 515 | similarly, |
| 516 | .BI STORE we ( p ", " x ) |
| 517 | stores the value |
| 518 | .I x |
| 519 | at address |
| 520 | .I p |
| 521 | in the corresponding format. |
| 522 | . |
| 523 | .SS "64-bit support" |
| 524 | For portability to environments without native 64-bit integers, the |
| 525 | structure |
| 526 | .B kludge64 |
| 527 | is defined. If the target platform is known to have an unsigned 64-bit |
| 528 | integer type, then this structure merely encapsulates a native integer, |
| 529 | and a decent optimizing compiler can be expected to handle this exactly |
| 530 | as if it were the native type. Otherwise, it contains two 32-bit halves |
| 531 | which are processed the hard way. |
| 532 | .PP |
| 533 | For each of the above macros with a suffix |
| 534 | .BR 64 , |
| 535 | .BR 64_L , |
| 536 | or |
| 537 | .BR 64_B , |
| 538 | an additional `kludge' macro is defined, whose name has an additional |
| 539 | final underscore; e.g., the kludge macro corresponding to |
| 540 | .B ROR64 |
| 541 | is |
| 542 | .BR ROR64_ ; |
| 543 | and that corresponding to |
| 544 | .B LOAD64_L |
| 545 | is |
| 546 | .BR LOAD64_L_ . |
| 547 | If the original macro would have |
| 548 | .I returned |
| 549 | a value of type |
| 550 | .BR uint64 , |
| 551 | then the kludge macro has an additional first argument, denoted |
| 552 | .IR d , |
| 553 | which should be an lvalue of type |
| 554 | .BR kludge64 , |
| 555 | and the kludge macro will store its result in |
| 556 | .IR d . |
| 557 | The kludge macro's remaining arguments are the same as the original |
| 558 | macro, except that where the original macro accepts an argument of type |
| 559 | .BR uint64 , |
| 560 | the kludge macro accepts an argument of type |
| 561 | .B kludge64 |
| 562 | instead. |
| 563 | .PP |
| 564 | Finally, a number of additional macros are provided, to make working |
| 565 | with |
| 566 | .B kludge64 |
| 567 | somewhat less awful. |
| 568 | .TP |
| 569 | .BI SET64( d ", " h ", " l ) |
| 570 | Set the high 32 bits of |
| 571 | .I d |
| 572 | to be |
| 573 | .IR h , |
| 574 | and the low 32 bits to be |
| 575 | .IR l . |
| 576 | Both |
| 577 | .I h |
| 578 | and |
| 579 | .I l |
| 580 | may be arbitrary integers. |
| 581 | .TP |
| 582 | .BI X64( hexh ", " hexl ) |
| 583 | Expands to an initializer for an object of type |
| 584 | .B kludge64 |
| 585 | where |
| 586 | .I hexh |
| 587 | and |
| 588 | .I hexl |
| 589 | encode the high and low 32-bit halves in hexadecimal, without any |
| 590 | .B 0x |
| 591 | prefix. |
| 592 | .TP |
| 593 | .BI ASSIGN( d ", " x ) |
| 594 | Make |
| 595 | .I d |
| 596 | be a copy of the |
| 597 | .B kludge64 |
| 598 | .IR x . |
| 599 | .TP |
| 600 | .BI HI64( x ) |
| 601 | Return the high 32 bits of |
| 602 | .IR x . |
| 603 | .TP |
| 604 | .BI LO64( x ) |
| 605 | Return the low 32 bits of |
| 606 | .IR x . |
| 607 | .TP |
| 608 | .BI GET64( t ", " x ) |
| 609 | Return the value of |
| 610 | .I x |
| 611 | as a value of type |
| 612 | .IR t . |
| 613 | If |
| 614 | .I t |
| 615 | is an unsigned integer type, then the value will be truncated to fit as |
| 616 | necessary; if |
| 617 | .I t |
| 618 | is a signed integer type, then the behaviour is undefined if the value |
| 619 | of |
| 620 | .I x |
| 621 | is too large. |
| 622 | .TP |
| 623 | .BI AND64( d ", " x ", " y ) |
| 624 | Set |
| 625 | .I d |
| 626 | to be the bitwise-and of the two |
| 627 | .B kludge64 |
| 628 | arguments |
| 629 | .I x |
| 630 | and |
| 631 | .IR y . |
| 632 | .TP |
| 633 | .BI OR64( d ", " x ", " y ) |
| 634 | Set |
| 635 | .I d |
| 636 | to be the bitwise-or of the two |
| 637 | .B kludge64 |
| 638 | arguments |
| 639 | .I x |
| 640 | and |
| 641 | .IR y . |
| 642 | .TP |
| 643 | .BI XOR64( d ", " x ", " y ) |
| 644 | Set |
| 645 | .I d |
| 646 | to be the bitwise-exclusive-or of the two |
| 647 | .B kludge64 |
| 648 | arguments |
| 649 | .I x |
| 650 | and |
| 651 | .IR y . |
| 652 | .TP |
| 653 | .BI CPL64( d ", " x ) |
| 654 | Set |
| 655 | .I d |
| 656 | to be the bitwise complement of the |
| 657 | .B kludge64 |
| 658 | argument |
| 659 | .IR x . |
| 660 | .TP |
| 661 | .BI ADD64( d ", " x ", " y ) |
| 662 | Set |
| 663 | .I d |
| 664 | to be the sum of the two |
| 665 | .B kludge64 |
| 666 | arguments |
| 667 | .I x |
| 668 | and |
| 669 | .IR y . |
| 670 | .TP |
| 671 | .BI SUB64( d ", " x ", " y ) |
| 672 | Set |
| 673 | .I d |
| 674 | to be the difference of the two |
| 675 | .B kludge64 |
| 676 | arguments |
| 677 | .I x |
| 678 | and |
| 679 | .IR y . |
| 680 | .TP |
| 681 | .BI CMP64( x ", " op ", " y ) |
| 682 | Here, |
| 683 | .I x |
| 684 | and |
| 685 | .I y |
| 686 | should be arguments of type |
| 687 | .B kludge64 |
| 688 | and |
| 689 | .I op |
| 690 | should be one of the relational operators |
| 691 | .BR == , |
| 692 | .BR < , |
| 693 | .BR <= , |
| 694 | .BR > , |
| 695 | or |
| 696 | .B >= |
| 697 | \(en |
| 698 | .I not |
| 699 | .BR !=. |
| 700 | Evaluates nonzero if |
| 701 | .IR x \~ op \~ y . |
| 702 | .TP |
| 703 | .BI ZERO64( x ) |
| 704 | Evaluates nonzero if the |
| 705 | .B kludge64 |
| 706 | argument |
| 707 | .I x |
| 708 | is exactly zero. |
| 709 | .SH "SEE ALSO" |
| 710 | .BR mLib (3). |
| 711 | .SH AUTHOR |
| 712 | Mark Wooding, <mdw@distorted.org.uk> |
| 713 | |