[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