Как прочитать флаг условия в сборке ARMv7 Thumb-2? - PullRequest
0 голосов
/ 02 января 2019

Я использую процессор ARMv7 с инструкциями Thumb-2.

Я выполнил ADD, SUB или CMP.Теперь я хочу переместить флаг условия LE в r2.После этого r2 должен содержать либо 0, либо 1.

. Я просматривал руководство по Thumb-2, но не нашел условной инструкции MOV или специальной инструкции дляпрочитайте флаги.

Какой самый эффективный способ сделать это?Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 02 января 2019

Я просматривал руководство по Thumb-2, но не нашел условной инструкции MOV или специальной инструкции для чтения флагов.

Вы можете использовать MRS, чтобы скопировать условные флаги в регистр (т.е. r2).

Какой самый эффективный способ сделать это?

До сих пор вы не включили требование, в котором условного кода выполнения недостаточно, так что это наиболее эффективный способ.

0 голосов
/ 02 января 2019

В 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 или даже хуже, чем clang с -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, с двумя предикатными инструкциями.

Кодогенерация режима 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
0 голосов
/ 02 января 2019

Вам нужно запустить условный блок с помощью инструкции 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-инструкции. Подробнее читайте в руководстве.

...