[llvm-dev] BUGS n code generated for target i386 compiling __bswapdi3, and for target x86-64 compiling __bswapsi2()

Fabian Giesen via llvm-dev llvm-dev at lists.llvm.org
Sun Nov 25 13:38:37 PST 2018


On 11/25/2018 11:38 AM, Stefan Kanthak via llvm-dev wrote:
> "Craig Topper" <craig.topper at gmail.com> wrote:
> 
>> bswapdi2 for i386 is correct
> 
> OUCH!
> 
>> Bits 31:0 of the source are loaded into edx. Bits 63:32 are loaded into
>> eax. Those are each bswapped.
> 
> This exchanges the high byte of each 32-bit PART with its low byte, but
> NOT the high byte of the whole 64-bit operand with its low byte!

Incorrect.

This reverses the bytes within the low and high 32-bit halves, and also 
swaps the two halves, which _is_ equivalent to byte-reversing the entire 
64-bit value.

It's a classic divide-and-conquer approach: one way to reverse a 
sequence is to cut it into two contiguous pieces (doesn't matter how; in 
this case, split at the halfway point), reverse the two pieces 
individually (the two BSWAPs), and then combine the two pieces in 
reverse order (accomplished implicitly by loading the original top half 
into eax and the bottom half into edx).

> Please get a clue!

Throwing insults around will not help you get your problem resolved any 
quicker, it will just get you ignored.

> Just run the following code on x86-64:
> 
>      mov    rdi, 0123456789abcdefh    ; pass (fake) argument in RDI
> ; split argument into high and low part
>      mov    rdx, rdi
>      shr    rdx, 32                   ; high part in EDX
>      mov    eax, rdi                  ; low part in EAX
> ; perform __bswapdi2() as in 32-bit mode
>      xchg   eax, edx                  ; swap parts, argument now loaded
>                                       ;  like in 32-bit mode
>      bswap  edx
>      bswap  eax                       ; result like that in 32-bit mode
> ; load result into 64-bit register
>      shl    rdx, 32
>      or     rax, rdx
> ; perform _bswapdi2() in native 64-bit mode
>      bswap  rdi
> ; compare results
>      xor    rax, rdi

Syntax error aside (that should be "mov eax, edi" not "mov eax, rdi" up 
there), I get:

(gdb) set disassembly-flavor intel
(gdb) x/20i main
    0x4004a0 <main>:     movabs rdi,0x123456789abcdef
    0x4004aa <main+10>:  mov    rdx,rdi
    0x4004ad <main+13>:  shr    rdx,0x20
    0x4004b1 <main+17>:  mov    eax,edi
    0x4004b3 <main+19>:  xchg   edx,eax
    0x4004b4 <main+20>:  bswap  edx
    0x4004b6 <main+22>:  bswap  eax
    0x4004b8 <main+24>:  shl    rdx,0x20
    0x4004bc <main+28>:  or     rax,rdx
    0x4004bf <main+31>:  bswap  rdi
    0x4004c2 <main+34>:  xor    rax,rdi
    0x4004c5 <main+37>:  int3
    0x4004c6 <main+38>:  nop    WORD PTR cs:[rax+rax*1+0x0]
    0x4004d0 <__libc_csu_init>:  push   r15
    0x4004d2 <__libc_csu_init+2>:        mov    r15,rdx
    0x4004d5 <__libc_csu_init+5>:        push   r14
    0x4004d7 <__libc_csu_init+7>:        mov    r14,rsi
    0x4004da <__libc_csu_init+10>:       push   r13
    0x4004dc <__libc_csu_init+12>:       mov    r13d,edi
    0x4004df <__libc_csu_init+15>:       push   r12
(gdb) r
Starting program: /home/fabiang/code/bswap/bswap

Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004004c6 in main ()
(gdb) x/i $pc
=> 0x4004c6 <main+38>:  nop    WORD PTR cs:[rax+rax*1+0x0]
(gdb) p $rax
$1 = 0

exactly as it should be. So your point is?

-Fabian


More information about the llvm-dev mailing list