updated
Changed the 2nd line of assembly to the mnemonic actually being used (mflr
) and added more info at the bottom.
I ran across some code (using gcc) resembling the following (paraphrased):
#define SOME_MACRO( someVar ) \
do { \
__asm__ ( \
" b 0f\n" \
"0: mflr %0\n" \
: "=r"( someVar ) \
); \
} while(0)
... where the b
instruction (ppc) is a short jmp and mflr
is getting the contents of the 'link register' -- which is similar to the program counter in some respects. I've seen this sort of thing for intel code as well (cf. the accepted answer in this question).
The branch acts as a no-op ... my question: what purpose does this serve?
I'm guessing it has something to do with branch prediction stuff, but so far I've only found people's code using this idiom while searching.
It looks like I was wrong on the branch prediction guess. mflr
grabs the contents of the link register.
So, my question boils down to: why is the branch necessary.
The interesting bits of code like this tend to happen in somethingelse
. Some known purposes of such code are:
__asm__("call 0f\n0: pop %0\n" : "=r"(pc))
call
pushes it to the stack is used to retrieve it).asm("lea 0f(%%rip), %0\n0:\n" : "=r"(pc))
NOP
slots in there that tracing utilities at runtime can modify to dynamically hook into the code. Solaris DTrace uses such techniques.Whether unconditional branches like this cause branch prediction miss penalties or other type of stalls is very CPU-dependent.