Я пишу программу для преобразования между BCD (4 бит на десятичную цифру) и Плотно упакованное десятичное число (DPD) (10 бит на 3 десятичных разряда). DPD далее документируется (с предложением использовать программное обеспечение для использования справочных таблиц) на веб-сайте Майк Коулисау.
Эта процедура требует только младшего 16 бит регистров, которые она использует, но для более короткого кодирования команд я использовал, по возможности, 32-битные инструкции. Это ограничение скорости, связанное с кодом вроде:
mov data,%eax # high 16 bit of data are cleared
...
shl %al
shr %eax
или
and $0x888,%edi         #   = 0000 a000 e000 i000
imul $0x0490,%di        #   = aei0 0000 0000 0000
 где альтернативой 16-битовому imul будет либо 32-битный imul, либо следующий and или ряд инструкций lea и окончательный and.
Весь код в моей программе можно найти ниже. Есть ли что-нибудь в этом месте, где производительность хуже, чем может быть из-за меня смешивания слов и инструкций dword?
        .section .text
        .type bcd2dpd_mul,@function
        .globl bcd2dpd_mul
        # convert BCD to DPD with multiplication tricks
        # input abcd efgh iklm in edi
        .align 8
bcd2dpd_mul:
        mov %edi,%eax           #   = 0000 abcd efgh iklm
        shl %al                 #   = 0000 abcd fghi klm0
        shr %eax                #   = 0000 0abc dfgh iklm
        test $0x880,%edi        # fast path for a = e = 0
        jz 1f
        and $0x888,%edi         #   = 0000 a000 e000 i000
        imul $0x0490,%di        #   = aei0 0000 0000 0000
        mov %eax,%esi
        and $0x66,%esi          # q = 0000 0000 0fg0 0kl0
        shr $13,%edi            # u = 0000 0000 0000 0aei
        imul tab-8(,%rdi,4),%si # v = q * tab[u-2][0]
        and $0x397,%eax         # r = 0000 00bc d00h 0klm
        xor %esi,%eax           # w = r ^ v
        or tab-6(,%rdi,4),%ax   # x = w | tab[u-2][1]
        and $0x3ff,%eax         #   = 0000 00xx xxxx xxxx
1:      ret
        .size bcd2dpd_mul,.-bcd2dpd_mul
        .section .rodata
        .align 4
tab:
        .short 0x0011 ; .short 0x000a
        .short 0x0000 ; .short 0x004e
        .short 0x0081 ; .short 0x000c
        .short 0x0008 ; .short 0x002e
        .short 0x0081 ; .short 0x000e
        .short 0x0000 ; .short 0x006e
        .size tab,.-tab
Улучшенный код
После применения некоторых предложений от ответа и комментариев и некоторых других обманов, вот мой улучшенный код.
        .section .text
        .type bcd2dpd_mul,@function
        .globl bcd2dpd_mul
        # convert BCD to DPD with multiplication tricks
        # input abcd efgh iklm in edi
        .align 8
bcd2dpd_mul:
        mov %edi,%eax           #   = 0000 abcd efgh iklm
        shl %al                 #   = 0000 abcd fghi klm0
        shr %eax                #   = 0000 0abc dfgh iklm
        test $0x880,%edi        # fast path for a = e = 0
        jnz 1f
        ret
        .align 8
1:      and $0x888,%edi         #   = 0000 a000 e000 i000
        imul $0x49,%edi         #   = 0ae0 aei0 ei00 i000
        mov %eax,%esi
        and $0x66,%esi          # q = 0000 0000 0fg0 0kl0
        shr $8,%edi             #   = 0000 0000 0ae0 aei0
        and $0xe,%edi           #   = 0000 0000 0000 aei0
        mov lookup-4(%rdi),%dx
        movzbl %dl,%edi
        imul %edi,%esi          # v = q * tab[u-2][0]
        and $0x397,%eax         # r = 0000 00bc d00h 0klm
        xor %esi,%eax           # w = r ^ v
        or %dh,%al              #   = w | tab[u-2][1]
        and $0x3ff,%eax         #   = 0000 00xx xxxx xxxx
        ret
        .size bcd2dpd_mul,.-bcd2dpd_mul
        .section .rodata
        .align 4
lookup:
        .byte 0x11
        .byte 0x0a
        .byte 0x00
        .byte 0x4e
        .byte 0x81
        .byte 0x0c
        .byte 0x08
        .byte 0x2e
        .byte 0x81
        .byte 0x0e
        .byte 0x00
        .byte 0x6e
        .size lookup,.-lookup
