Как прочитать флаг условия в сборке ARMv7 Thumb-2?
Я использую процессор ARMv7 с инструкциями Thumb-2.
Я выполнил ADD
, SUB
или CMP
, Теперь я хочу переместить флаг условия LE
в r2
, После этого, r2
должен содержать либо 0
или же 1
,
Я просматривал руководство по Thumb-2, но не нашел условной инструкции MOV или специальной инструкции для чтения флагов.
Какой самый эффективный способ сделать это? Заранее спасибо!
3 ответа
Вы должны начать условный блок с ite
(если-то-еще), а затем просто использовать условные присваивания:
ite le @ if-then-else (le)
movle r2, #1 @ if (le) then r2 = #1
movgt r2, #0 @ else r2 = #0
В общем, вы можете использовать произвольные условные инструкции в Thumb-2, если вы добавите к ним соответствующие IT-инструкции. Прочитайте руководство для деталей.
В ARM (почти) любая инструкция может быть предиката. В режиме большого пальца это требует it
Инструкция для кодирования предиката и шаблона отрицается или нет для следующих нескольких инструкций.
Но в унифицированном синтаксисе ассемблер может сделать это за вас без объяснения причин. it
, Я думаю.
например movle r0, #1
наборы r0 = 1
если условие LE верно для флагов, в противном случае оно остается неизменным. Так что вам нужно mov r0, #0
первый.
ARM32 не имеет инструкции set-from-condition, как в x86 setcc
,
AArch64 делает: превращение состояния флага в целое число занимает всего один cset
инструкция.
Этот источник C:
int booleanize(int x, int y) { return x<y; }
int booleanize_u(unsigned a, unsigned b) { return a<b; }
компилирует для большого пальца ARM32 с помощью clang -O3 ( в проводнике компилятора Godbolt), выявляя некоторые глупые пропущенные оптимизации. gcc похож, делает ветвистый код без -mcpu
или даже хуже, чем лязг с -mcpu=cortex-a53
, Ветвление, возможно, не совсем необоснованно на простом микроконтроллере.
@@ 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
Это определенно хуже, чем ite le
/ movle / movgt из ответа @ fuz, с двумя предикатными инструкциями.
Code-gen режима ARM более или менее точен, когда каждое 32-битное слово инструкции имеет 4 бита в кодировании для условия предиката. (По умолчанию без суффикса в исходном коде asm al
= всегда.)
@ 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, но не нашел условной инструкции MOV или специальной инструкции для чтения флагов.
Ты можешь использовать MRS
, чтобы скопировать условные флаги в регистр (т.е. r2
).
Какой самый эффективный способ сделать это?
До сих пор вы не включили требование, в котором недостаточно кода условного выполнения, так что это наиболее эффективный способ.