如何让编译器选择标志更新ARM指令?

sup*_*owl 0 c assembly flags arm

我试图在我的代码执行算术运算时使用CPSR标志,而不是使用一系列if语句来检查溢出,进位等,以便拥有更小,更快的代码.一个简单的例子是这个加法操作:

int16_t a = 0x5000;
int16_t b = 0x4000;
int16_t result = a+b;
uint32_t flags = getFlags();
Run Code Online (Sandbox Code Playgroud)

代码需要在各种平台上运行,因此getFlags()是允许包含特定于体系结构的程序集的代码的唯一部分.

inline uint32_t getFlags() {
    uint32_t flags = 0;
    asm (“mrs %0, cpsr”
        : “=r” (flags)
        :
        : );
    return flags;
}
Run Code Online (Sandbox Code Playgroud)

问题是编译器没有任何方式知道此示例中的加法操作应该设置标志,因此它生成类似于以下的指令:

ldrsh r3, [r0]
ldrsh r4, [r1]
add r3, r3, r4
strh r3, [r2]
mrs r3, cpsr
Run Code Online (Sandbox Code Playgroud)

为了使CPSR包含任何有用的东西,我需要编译器使用adds而不是add(s suffix = update CPSR).我可以在我的C代码或可能的编译器选项中更改它会导致它选择标志更新指令吗?我可以使用GCC或Clang.

fuz*_*fuz 6

这种代码无法以有用的方式工作,因为编译器可以随意重新排列代码.在mrs指令运行之前,甚至没有保证添加是最后一个标志更新指令.如果要实现此目的,请将标志设置添加和mrs指令放在一个asm语句中.