如何读取 ARMv7 Thumb-2 程序集中的条件标志?
How to read a condition flag in ARMv7 Thumb-2 assembly?
我正在使用带有 Thumb-2 指令的 ARMv7 处理器。
我执行了 ADD
、SUB
或 CMP
。现在我想将条件标志 LE
移动到 r2
。此后,r2
应包含 0
或 1
.
我一直在查看 Thumb-2 手册,但我没有找到条件 MOV 指令或读取标志的特殊指令。
最有效的方法是什么?提前致谢!
您需要使用 ite
(if-then-else) 指令开始一个条件块,然后只使用条件赋值:
ite le @ if-then-else (le)
movle r2, #1 @ if (le) then r2 = #1
movgt r2, #0 @ else r2 = #0
一般来说,如果您在 Thumb-2 中使用适当的 IT 指令作为前缀,则可以在 Thumb-2 中使用任意条件指令。详细阅读手册。
I've been looking through the Thumb-2 manual, but I haven't found a conditional MOV instruction or a special instruction to read the flags.
您可以使用 MRS
,以便将条件标志复制到寄存器(即 r2
)。
What's the most efficient way to do this?
到目前为止,您还没有包含 conditional execution code 不够的要求,因此这是最有效的方法。
在 ARM 中,(几乎)任何指令都可以断言。在拇指模式下,这需要一个 it
指令来为接下来的几条指令编码谓词和否定模式。
但我认为,在统一语法中,汇编器可以为您做到这一点,而无需显式 it
。
例如如果标志中的 LE 条件为真,movle r0, #1
设置 r0 = 1
,否则保持不变。所以你首先需要一个mov r0, #0
。
ARM32 没有像 x86 的 setcc
.
那样的条件设置指令
AArch64 做到了:将标志条件转换为整数只需要一条 cset
指令。
此 C 源代码:
int booleanize(int x, int y) { return x<y; }
int booleanize_u(unsigned a, unsigned b) { return a<b; }
使用 clang -O3 (on the Godbolt compiler explorer) 为 ARM32 thumb 编译,揭示了一些愚蠢的遗漏优化。 gcc 类似,使分支代码没有 -mcpu
甚至比带有 -mcpu=cortex-a53
的 clang 更糟糕。 Branchy 在简单的微控制器上可能并非完全不合理。
@@ BAD EXAMPLE, compiler missed optimizations
@ clang7.0 -target arm -mthumb -mcpu=cortex-a53
booleanize(int, int):
movs r2, #0 @ movs is 16-bit, mov is a 32-bit instruction, I think.
cmp r0, r1
it lt
movlt r2, #1
mov r0, r2 @ wasted instruction because the compiler wanted to mov #0 before cmp
bx lr
booleanize_u(unsigned int, unsigned int):
movs r2, #0
cmp r0, r1
it lo
movlo r2, #1
mov r0, r2
bx lr
这绝对比@fuz 的回答中的 ite le
/ movle / movgt 差很多,有 2 个谓词指令。
ARM 模式代码生成或多或少很好,其中每个 32 位指令字在编码中都有 4 位用于谓词条件。 (asm源码中没有后缀的默认是al
= always.)
@ gcc8.2 -O3 -mcpu=cortex-a53
booleanize(int, int):
cmp r0, r1
movge r0, #0 @ a simple mov without predication or flag-setting would work
movlt r0, #1
bx lr
booleanize_u(unsigned int, unsigned int):
cmp r0, r1
movcs r0, #0
movcc r0, #1
bx lr
AArch64 有 cset
, 布尔化。
@ clang and gcc make the same efficient code
booleanize(int, int):
cmp w0, w1
cset w0, lt @ signed less-than
ret
booleanize_u(unsigned int, unsigned int):
cmp w0, w1
cset w0, lo @ unsigned lower
ret
我正在使用带有 Thumb-2 指令的 ARMv7 处理器。
我执行了 ADD
、SUB
或 CMP
。现在我想将条件标志 LE
移动到 r2
。此后,r2
应包含 0
或 1
.
我一直在查看 Thumb-2 手册,但我没有找到条件 MOV 指令或读取标志的特殊指令。
最有效的方法是什么?提前致谢!
您需要使用 ite
(if-then-else) 指令开始一个条件块,然后只使用条件赋值:
ite le @ if-then-else (le)
movle r2, #1 @ if (le) then r2 = #1
movgt r2, #0 @ else r2 = #0
一般来说,如果您在 Thumb-2 中使用适当的 IT 指令作为前缀,则可以在 Thumb-2 中使用任意条件指令。详细阅读手册。
I've been looking through the Thumb-2 manual, but I haven't found a conditional MOV instruction or a special instruction to read the flags.
您可以使用 MRS
,以便将条件标志复制到寄存器(即 r2
)。
What's the most efficient way to do this?
到目前为止,您还没有包含 conditional execution code 不够的要求,因此这是最有效的方法。
在 ARM 中,(几乎)任何指令都可以断言。在拇指模式下,这需要一个 it
指令来为接下来的几条指令编码谓词和否定模式。
但我认为,在统一语法中,汇编器可以为您做到这一点,而无需显式 it
。
例如如果标志中的 LE 条件为真,movle r0, #1
设置 r0 = 1
,否则保持不变。所以你首先需要一个mov r0, #0
。
ARM32 没有像 x86 的 setcc
.
AArch64 做到了:将标志条件转换为整数只需要一条 cset
指令。
此 C 源代码:
int booleanize(int x, int y) { return x<y; }
int booleanize_u(unsigned a, unsigned b) { return a<b; }
使用 clang -O3 (on the Godbolt compiler explorer) 为 ARM32 thumb 编译,揭示了一些愚蠢的遗漏优化。 gcc 类似,使分支代码没有 -mcpu
甚至比带有 -mcpu=cortex-a53
的 clang 更糟糕。 Branchy 在简单的微控制器上可能并非完全不合理。
@@ BAD EXAMPLE, compiler missed optimizations
@ clang7.0 -target arm -mthumb -mcpu=cortex-a53
booleanize(int, int):
movs r2, #0 @ movs is 16-bit, mov is a 32-bit instruction, I think.
cmp r0, r1
it lt
movlt r2, #1
mov r0, r2 @ wasted instruction because the compiler wanted to mov #0 before cmp
bx lr
booleanize_u(unsigned int, unsigned int):
movs r2, #0
cmp r0, r1
it lo
movlo r2, #1
mov r0, r2
bx lr
这绝对比@fuz 的回答中的 ite le
/ movle / movgt 差很多,有 2 个谓词指令。
ARM 模式代码生成或多或少很好,其中每个 32 位指令字在编码中都有 4 位用于谓词条件。 (asm源码中没有后缀的默认是al
= always.)
@ gcc8.2 -O3 -mcpu=cortex-a53
booleanize(int, int):
cmp r0, r1
movge r0, #0 @ a simple mov without predication or flag-setting would work
movlt r0, #1
bx lr
booleanize_u(unsigned int, unsigned int):
cmp r0, r1
movcs r0, #0
movcc r0, #1
bx lr
AArch64 有 cset
, 布尔化。
@ clang and gcc make the same efficient code
booleanize(int, int):
cmp w0, w1
cset w0, lt @ signed less-than
ret
booleanize_u(unsigned int, unsigned int):
cmp w0, w1
cset w0, lo @ unsigned lower
ret