trick/trick_source/sim_services/MemoryManager/insert_bitfield.c

100 lines
4.0 KiB
C
Raw Permalink Normal View History

/*
2015-02-26 15:02:31 +00:00
PURPOSE: (Insert a value into a bitfield.)
REFERENCE: ((meow) (woof))
PROGRAMMERS: (((Jane Falgout) (LinCom)) ((Alex Lin) (NASA) (8/00))) */
#include "trick/bitfield_proto.h"
2015-02-26 15:02:31 +00:00
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));
/*
2015-02-26 15:02:31 +00:00
* 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
2015-02-26 15:02:31 +00:00
* 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
2015-02-26 15:02:31 +00:00
* 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
2015-02-26 15:02:31 +00:00
* which bit fields are packed into a structure is not defined in
* the ANSI standard, but what has been observed on several
2015-02-26 15:02:31 +00:00
* platforms is that the bit field values are stored in the order in
* which they were declared, with the first bit field starting at
2015-02-26 15:02:31 +00:00
* 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
2015-02-26 15:02:31 +00:00
* 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
2015-02-26 15:02:31 +00:00
* mask and the number of bits by which the input value is shifted.
*
* Keith says that the comment above might be the longest
2015-02-26 15:02:31 +00:00
* 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);
}