Search code examples
cassemblyembeddedendiannesspowerpc

How to understand this GNU C inline assembly macro for PowerPC stwbrx


This is basically to perform swap for the buffers while transferring a message buffer. This statement left me puzzled (because of my unfamiliarity with the embedded assembly code in c). This is a power pc instruction

#define ASMSWAP32(dest_addr,data) __asm__ volatile ("stwbrx %0, 0, %1" : : "r" (data), "r" (dest_addr))

Solution

  • #define ASMSWAP32(dest_addr,data) ...

    This part should be clear

    __asm__ volatile ( ... : : "r" (data), "r" (dest_addr))

    This is the actual inline assembly:

    Two values are passed to the assmbly code; no value is returned from the assembly code (this is the colons after the actual assembly code).

    Both parameters are passed in registers ("r"). The expression %0 will be replaced by the register that contains the value of data while the expression %1 will be replaced by the register that contains the value of dest_addr (which will be a pointer in this case).

    The volatile here means that the assembly code has to be executed at this point and cannot be moved to somewhere else.

    So if you use the following code in the C source:

    ASMSWAP(&a, b);
    

    ... the following assembler code will be generated:

    # write the address of a to register 5 (for example)
    ...
    # write the value of b to register 6
    ...
    stwbrx 6, 0, 5
    

    So the first argument of the stwbrx instruction is the value of b and the last argument is the address of a.

    stwbrx x, 0, y

    This instruction writes the value in register x to the address stored in register y; however it writes the value in "reverse endian" (on a big-endian CPU it writes the value "little endian".

    The following code:

    uint32 a;
    ASMSWAP32(&a, 0x12345678);
    

    ... should therefore result in a = 0x78563412.