I have a uint64 variable which often only requires high or low 32 bit access. I am using a 32-bit ARM Cortex M0, and to help with speed and I am trying to overlap the uint64 var
To clarify what I've learned:
It turns out C doesn't allow global members of anonymous structs/unions. Oh well. But using named structs/unions generates efficient code anyway, as the member offset is known at compile time and can be added without incurring extra instructions.
Regarding using shifts & masks instead of a union, this may work well for reads, but for writes it results in extra instructions (9 vs 5) and pointless accesses to the low uint32. On the other hand, it is more endian portable than a union, but that isn't important in my application.
union status {
struct { uint32_t user, system; };
uint64_t all;
};
volatile union status status;
status.system |= 1u; // write to high uint32 member directly
2301 movs r3, #1
4A02 ldr r2, 0x00002910
6851 ldr r1, [r2, #4]
430B orrs r3, r1
6053 str r3, [r2, #4]
status.all |= ((uint64_t)1)<<32; // write to full uint64
2001 movs r0, #1
4905 ldr r1, 0x00002910
680C ldr r4, [r1]
684D ldr r5, [r1, #4]
4328 orrs r0, r5
1C22 adds r2, r4, #0
1C03 adds r3, r0, #0
600A str r2, [r1] // this is not atomic, and pointless
604B str r3, [r1, #4] // this is the important part