Why the compiler changes movq to movd when doing 64bit operations?
Asked Answered
M

2

6

I am programming the following:

__asm__ volatile ("movq %%rax, %%mm1\n"
                  "movq %%rcx, %%mm2\n"
                  : : "a" (0xDEADBEEFDEADBEEF), "c" (0xBADFACE5BADFACE5));

In this case, I am moving the value from rax to mm1 which both are 64b registers (moving a qword value from one register to another). But when I compile my code I see:

mov  rax, 0xDEADBEEFDEADBEEF
mov  rcx, 0xBADFACE5BADFACE5
movd mm1, rax     <-------------- Why it is doing a dword operation ??
movd mm2, rcx     <-------------- Why it is doing a dword operation ?? 

I am compiling my code in 64bit mode, I am not sure why it is changing a 64bit operation to a 32bit.

Malignancy answered 5/8, 2015 at 23:32 Comment(0)
M
4

From this bugzilla:

This is done on purpose to provide backward compatibility since vmovq isn't in original x86-64 spec and older assemblers don't support it. From i386-opc.tbl in binutils:

These really shouldn't allow for Reg64 (movq is the right mnemonic for copying between Reg64/Mem64 and RegXMM/RegMMX, as is mandated by Intel's spec). AMD's spec, having been in existence for much longer, failed to recognize that and specified movd for 32- and 64-bit operations.

vmovd really shouldn't allow for 64bit operand (vmovq is the right mnemonic for copying between Reg64/Mem64 and RegXMM, as is mandated by Intel AVX spec). To avoid extra template in gcc x86 backend and support assembler for AMD64, we accept 64bit operand on vmovd so that we can use one template for both SSE and AVX instructions.

Martineau answered 5/8, 2015 at 23:40 Comment(5)
So despite of having a "movd" between two 64b registers, will it still do a 64b mov?Malignancy
When the destination operand is 64 bits movd will copy all 64 bits from the register if it is 64 bits. Otherwise if the register is 32 bits it will extend it with zeroes. There's a helpful reference here: x86.renejeschke.de/html/file_module_x86_id_181.htmlMartineau
So yes, movd will do a 64b mov where appropriate.Martineau
@mareiou: This answer isn't very clear. GCC isn't modifying your instruction. It's still the reg,xmm version of movq, but your disassembler is using the AMD convention when disassembling. (Maybe AMD wanted to distinguish the movq xmm, xmm/m64 form (XMM version of MMX whole-register load/copy opcode) from the movq xmm, r64/m64 form (movd with a REX.W prefix, 64-bit mode only) felixcloutier.com/x86/movd:movq vs. felixcloutier.com/x86/movq.Eulogistic
It makes some sense if you look consider the situation before AMD64 existed, where only movd could go between vector and general-purpose integer registers. (SSE2 existed before AMD64, so movd %eax, %xmm0 did exist). Before AMD64, the movq mnemonic was only for opcodes that access vector regs, (and optionally memory) not GP integer. So Intel's design makes more sense, but requires the assembler to look at operands to figure out which opcode. But that's not a new thing.Eulogistic
G
0

Despite the linked bug report, I cannot reproduce.

I tested gcc 4.4 though 4.9, with various optimization levels:

x86_64-linux-gnu-gcc-$VERSION $OPTIMIZATION -S -o x.s x.c

In all cases, the resulting x.s file contained only movq, not movd.

Galligaskins answered 5/8, 2015 at 23:45 Comment(1)
This doesn't really answer the question. Anyways, it's not clear from the question, but he's talking about what he sees after disassembling the object or executable generated by the compiler.Levitt

© 2022 - 2024 — McMap. All rights reserved.