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.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
mareiou
  • 404
  • 2
  • 11

2 Answers2

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.

Alexguitar
  • 722
  • 4
  • 15
  • So despite of having a "movd" between two 64b registers, will it still do a 64b mov? – mareiou Aug 06 '15 at 00:32
  • 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: http://x86.renejeschke.de/html/file_module_x86_id_181.html – Alexguitar Aug 06 '15 at 00:37
  • So yes, movd will do a 64b mov where appropriate. – Alexguitar Aug 06 '15 at 00:38
  • @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) https://www.felixcloutier.com/x86/movd:movq vs. https://www.felixcloutier.com/x86/movq. – Peter Cordes May 31 '19 at 03:54
  • 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. – Peter Cordes May 31 '19 at 03:57
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.

o11c
  • 15,265
  • 4
  • 50
  • 75
  • 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. – Ross Ridge Aug 06 '15 at 01:59