Electronic – Microchip XC8: multi-byte assignment with reverse endian

hi-tech-compileroptimizationxc8

Most, if not all, chips targeted by XC8 process one byte at a time. To assign a value from one multi-byte variable to another, it has to load the first 8 bits from the source into WREG and store them into the first 8 bits of the destination and then do that again with the next 8 bits. At the assembly level, this makes it trivial to adjust the endianness at the same time simply by reordering the load instructions or the store instructions (but not both).

But I can't seem to make XC8 do that. I've tried various combinations of shifting by 8, or'ing components, and'ing with masks, etc., and the smallest assembly code I can get comes from a straight assignment followed by an xor swap:

union
{
    unsigned int i;
    struct
    {
        unsigned char lo;
        unsigned char hi;
    };
} address;

    address.i = Packet->dest_addr;
    address.hi ^= address.lo;   //xor swap: valA ^ valB = diff (bitwise difference, not arithmetic)
    address.lo ^= address.hi;   //xor swap: valA ^ diff = valB
    address.hi ^= address.lo;   //xor swap: valB ^ diff = valA

I would think that the pointer source would help or make no difference, depending on whether it took advantage of the pointer inc/decrement instructions, but it insists on recalculating the pointer for each byte except for a direct assignment like this.

Am I missing something?

(I included the hi-tech tag because XC8 is descended from Hi-Tech after Microchip bought it. Maybe there's an old trick from there that still works?)

Best Answer

First, if you care about the machine instructions, use assembler.

Second, if you want to use a different encoding scheme than what the compiler uses for a multi-byte integer, then you might as well declare it as a byte array in the first place. The compiler won't be able to operate on a byte-flipped integer properly anyway.