Using condition flags as GNU C inline asm outputs

别等时光非礼了梦想. 提交于 2019-12-01 04:38:13

Starting with GCC6 on x86 you can actually use "=@ccCOND" as output (where COND is any valid x86 condition code).

Example originally from here, cleaned up by David's suggestions:

int variable_test_bit(long n, volatile const unsigned long *addr)
{
    int oldbit;
    asm volatile("bt %[value],%[bit]"
                 : "=@ccc" (oldbit)
                 : [value] "m" (*addr), [bit] "Jr" (n));
    return oldbit;
}

Before using this, you should test if __GCC_ASM_FLAG_OUTPUTS__ is defined.

Documentation at https://gcc.gnu.org.

I have a partial solution, but I don't really like it because it requires putting the branch instruction inside the asm, and because it requires a very ugly GCC feature that other "GNU C compatible" compilers might not support: asm goto. It does however allow the branch outside the asm to be eliminated. The idea is:

static inline int foo(...)
{
    __asm__ goto ( " .... ; cond_jmp %l[ret0]" : : "r"(...) ... 
                   : "clobbers" : ret0 );
    return 1;
ret0:
    return 0;
}

When inlined into the caller that does if (foo(...)) ... else ..., the conditional jump in the asm block ends up pointing directly to the else branch, even though at the abstract-machine level there are return values involved.

Unfortunately GCC doesn't support accessing condition flags outside of asm statements. If you don't want to set a value then you'll have to move the conditional branch into the asm statement. That means either using asm goto labels that you've already discovered, or also bringing branch target into your asm statement.

You might also want to check to see if either GCC's old style __sync atomic builtins or the newer memory model based atomics provide the functionality you want out of the atomic instructions you're using.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!