Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Adam_Warner
Beginner
120 Views

MOVD: Zero-extension of general purpose register as destination

[cpp]#include 
#include 
#include 

typedef uint32_t u32x4_t __attribute__ ((vector_size (16)));

void hello_world() {
  printf("Hello, World!\n");
  exit(0);
}

int main() {
  register void (*fn)() asm("rbx");

  u32x4_t addresses={(uint32_t) hello_world, (uint32_t) hello_world,
		     (uint32_t) hello_world, (uint32_t) hello_world};

  //Put an invalid function address in the function pointer
  asm("movq %[from], %[to]\n" : [to] "=r" (fn) : [from] "x" (addresses));

  //If MOVD zero-extends to 64-bits the function address will be valid
  asm("movd %[from], %%ebx\n" : : [from] "x" (addresses));

  goto *fn;
}[/cpp]

The above code demonstrates that Intel Core 2 zeroes out the high 32-bits in RBX when the destination is EBX and the instruction is MOVD.

Without explicit register variable contortions I can't stop GCC from zero-extending EBX to RBX (a missed optimisation) and/or avoid GAS incorrectly upgrading the movd instruction to movq (which causes invalid code generation as 64-bits are loaded into RBX instead of 32-bits into EBX with zero-extension to RBX).

[This is the small code model where functions are located in the lower 2GB of the address space]

Confirmation about the documented behaviour of MOVD is appreciated before I submit any bug reports about this issue to GCC/GAS developers.

Thanks,
Adam
0 Kudos
2 Replies
neni
New Contributor II
120 Views

When in 64-bit mode, operand size determines the number of valid bits in the destination

general-purpose register:

64-bit operands generate a 64-bit result in the destination general-purpose

register.

32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the

destination general-purpose register.

8-bit and 16-bit operands generate an 8-bit or 16-bit result. The upper 56 bits or

48 bits (respectively) of the destination general-purpose register are not be

modified by the operation. If the result of an 8-bit or 16-bit operation is intended

for 64-bit address calculation, explicitly sign-extend the register to the full

64-bits.


Quote from Intel SDM vol1 section 3.4.1.1

Adam_Warner
Beginner
120 Views

Many thanks neni,

I suspect not being able to move a doubleword into a 64-bit register is a bug in GNU as (GAS) mnemonic translation. I have submitted this bug report:
http://sourceware.org/bugzilla/show_bug.cgi?id=11818

Regards,
Adam
Reply