3

I have a question related to structure bit fields, please see below as I am a bit clueless on which keywords I should use to best describe my issue:

Context: I am writing a disassembler for MIPS R3000A Assembly Instructions, the one that were used for Playstation Programs in the early 2000.

Issue: I would like to know if in this code:

struct Instruction {
    u32 other:26;
    u32 op:6;
};

//main:
Instruction instruction = *(Instruction*)(data + pc);
printf("%02x\n", instruction.op);

it is guaranteed that all compilers, using little endianness, will always using the op:6 bit-fields to store the first 6 MSB ? (which is a bit counter intuitive, you would assume that the last 6 bits are stored in the op bit field)

It is an alternative to the following code:

static uint32_t get_op_code(uint32_t data) {
    uint16_t mask = (1 << 6) - 1;
    return (data >> 26) & mask;
}

//main:
uint32_t instruction = *(uint32_t*)(data + pc);
uint32_t op = get_op_code(instruction);
printf("%02x\n", op);

It is working fine on my side and it seems slightly faster using the structure approach, not to mention that is is more intuitive and clear, but I am afraid that it would not be guaranteed that the 6 first bits are stored in the second bit-field "op" of the structure.

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81

1 Answers1

4

The C standard does not guarantee how bit-fields are arranged. It does require each implementation to define it, so it should be in the documentation for a compiler. Per C 2018 6.7.2.1 11:

An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Ok thank you I was about to answer at my own question, I found this one; "The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined." http://c0x.coding-guidelines.com/6.7.2.1.html I will give you credit for that ;) Isnt it more the 6.7.2.1 12 that answer this ? Also why would you suggest then ? To keep the second approach probably ? – Antonin GAVREL Aug 01 '19 at 11:10
  • 1
    @AntoninGAVREL: Yes, if you need to guarantee ordering of bit fields in C, you must use bitwise operators rather than bit-fields. However, many compilers provide preprocessor macros to indicate version and features, so another approach is to write preprocessor statements that test whether a known compiler and bit-field ordering is being used. Then code may conditionally compile to define the structure in one order or the other (if it recognizes the compiler being used) or to emit a message with `#error` (if it does not recognize the compiler). – Eric Postpischil Aug 01 '19 at 11:40
  • Hi @Eric, if you have time could you show a quick, minimalist example of your suggestion? – Antonin GAVREL Mar 03 '21 at 05:33
  • @AntoninGAVREL: I do not have information at hand for how GCC or other compilers indicates the order of bit-fields in preprocessor macros. The [GCC documentation](https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html#Structures-unions-enumerations-and-bit-fields-implementation) says it is determined by the ABI, so one might have to test preprocessor macros that imply which ABI is in use, or there might be direct preprocessor macros to report the order, or there might be none. You could enter another Stack Overflow question about this. – Eric Postpischil Mar 04 '21 at 21:26