mirror of
https://github.com/nasa/trick.git
synced 2024-12-24 07:16:41 +00:00
18f0d7e871
Makes it easier to edit the files. So if we press 'end of line' we are really at the end of line.
100 lines
4.0 KiB
C
100 lines
4.0 KiB
C
/*
|
|
PURPOSE: (Insert a value into a bitfield.)
|
|
|
|
REFERENCE: ((meow) (woof))
|
|
|
|
PROGRAMMERS: (((Jane Falgout) (LinCom)) ((Alex Lin) (NASA) (8/00))) */
|
|
|
|
#include "trick/bitfield_proto.h"
|
|
|
|
unsigned int insert_bitfield_any(unsigned int bitfield, /* In: Bitfiled to insert value into */
|
|
int value, /* In: Value */
|
|
int size, /* In: Declared size of bitfield */
|
|
int start, /* In: Starting bit */
|
|
int bits)
|
|
{ /* In: Number of bits in bitfield */
|
|
|
|
unsigned int mask;
|
|
static int numbits = sizeof(unsigned int) * 8;
|
|
|
|
union {
|
|
long l;
|
|
char c[sizeof(long)];
|
|
} un;
|
|
|
|
un.l = 1; /* Used for Little/Big Endian Detection */
|
|
|
|
/* Mask out sign extension bits in case the value is negative */
|
|
value &= (0xFFFFFFFF >> (32 - bits));
|
|
|
|
/*
|
|
* Create a mask for the purpose of clearing the previous value of
|
|
* the bit field parameter for which an input was received, while
|
|
* preserving the other values in the underlying memory location
|
|
* shared by other bit field parameters. Do a bitwise AND of this
|
|
* mask with the underlying bit field memory location. The input
|
|
* value has been copied into an unsigned int. Shift the bits of
|
|
* that unsigned int the appropriate number of bits so that the bit
|
|
* position of the input value withing the unsigned int maps to the
|
|
* bit position at which it needs to be stored in the underlying bit
|
|
* field memory location. Do a bitwise OR of the shifted value with
|
|
* the underlying bit field memory location, thus replacing the
|
|
* previous value of the input bit field parameter with the input
|
|
* value while preserving the values of other bit field parameters
|
|
* that share the same underlying memory location.
|
|
* On big endian architectures, the most significant byte (MSB) of an
|
|
* integer is the first byte (i.e, the byte at the starting memory
|
|
* location of the integer). On little endian architectures. the
|
|
* least significant byte (LSB) is the first byte. The manner in
|
|
* which bit fields are packed into a structure is not defined in
|
|
* the ANSI standard, but what has been observed on several
|
|
* platforms is that the bit field values are stored in the order in
|
|
* which they were declared, with the first bit field starting at
|
|
* the first byte. Therefore, the first bit field of a structure
|
|
* on a big endian machine is stored at the high order end of its
|
|
* memory location; on a little endian machine, the first bit field
|
|
* is stored at the low order end of its memory location. These
|
|
* storage differences influence the construction of the bit field
|
|
* mask and the number of bits by which the input value is shifted.
|
|
*
|
|
* Keith says that the comment above might be the longest
|
|
* in Trick source code. I haven't read it. It might even
|
|
* be longer than the sum total of all other comments.
|
|
* When the comments are longer than the code it worries me.
|
|
*/
|
|
|
|
if (un.c[sizeof(long) - 1] == 1) {
|
|
/* Big endian */
|
|
|
|
if (start == 0)
|
|
mask = 0x00000000;
|
|
else
|
|
mask = 0xFFFFFFFF >> (numbits - start);
|
|
if (start + bits < 32)
|
|
mask |= (0xFFFFFFFF << (start + bits));
|
|
bitfield &= mask;
|
|
bitfield |= (value << start);
|
|
} else {
|
|
/* Little endian */
|
|
|
|
/* if bitfield is smaller than 32 bits, adjust start accordingly */
|
|
if (size == sizeof(short)) {
|
|
start += 16;
|
|
} else if (size == sizeof(char)) {
|
|
start += 24;
|
|
}
|
|
|
|
if (start == 0)
|
|
mask = 0x00000000;
|
|
else
|
|
mask = 0xFFFFFFFF << (numbits - start);
|
|
if (start + bits < 32)
|
|
mask |= (0xFFFFFFFF >> (start + bits));
|
|
|
|
bitfield &= mask;
|
|
bitfield |= (value << (32 - (start + bits)));
|
|
}
|
|
|
|
return (bitfield);
|
|
}
|