Inline assembly movd reg32/mem, xmmreg instruction produces incorrect machine code

pmoore pmoore_member at pathlink.com
Tue Mar 14 11:44:29 PST 2006


In the DMD code generator I believe the modrm reg and rm bits are being
interpreted the wrong way round for this instruction.

Consider this assembly code:

asm
{
movd ECX, XMM0;	
movd ECX, XMM1;	
movd ECX, XMM2;
movd ECX, XMM3;
movd ECX, XMM4;
movd ECX, XMM5;
movd ECX, XMM6;
movd ECX, XMM7;
}

In visual C++ 2005 express (and my own calculations) produces the following
machine code:

66 0f 7e c1	 ;movd	 ecx, xmm0
66 0f 7e c9	 ;movd	 ecx, xmm1
66 0f 7e d1	 ;movd	 ecx, xmm2
66 0f 7e d9	 ;movd	 ecx, xmm3
66 0f 7e e1	 ;movd	 ecx, xmm4
66 0f 7e e9	 ;movd	 ecx, xmm5
66 0f 7e f1	 ;movd	 ecx, xmm6
66 0f 7e f9	 ;movd	 ecx, xmm7

In DMD 0.149 it produces this:

66 0F 7E C8      ;movd EAX, XMM1
66 0F 7E C9      ;movd ECX, XMM1
66 0F 7E CA      ;movd EDX, XMM1
66 0F 7E CB      ;movd EBX, XMM1
66 0F 7E CC      ;movd ESP, XMM1
66 0F 7E CD      ;movd EBP, XMM1
66 0F 7E CE      ;movd ESI, XMM1
66 0F 7E CF      ;movd EDI, XMM1

----------------------------------------

And this assembly code:

asm
{
movd EAX, XMM0;	
movd ECX, XMM0; 
movd EDX, XMM0;
movd EBX, XMM0;
movd ESI, XMM0;
movd EDI, XMM0;
movd EBP, XMM0;
movd ESI, XMM0;
}

In Visual C++ 2005 Express (and my own calculations) produces this machine code:

66 0f 7e c0	 ;movd	 eax, xmm0
66 0f 7e c1	 ;movd	 ecx, xmm0
66 0f 7e c2	 ;movd	 edx, xmm0
66 0f 7e c3	 ;movd	 ebx, xmm0
66 0f 7e c6	 ;movd	 esi, xmm0
66 0f 7e c7	 ;movd	 edi, xmm0
66 0f 7e c5	 ;movd	 ebp, xmm0
66 0f 7e c6	 ;movd	 esi, xmm0

In DMD 0.149 it produces this:

66 0F 7E C0      ;movd EAX, XMM0
66 0F 7E C8      ;movd EAX, XMM1
66 0F 7E D0      ;movd EAX, XMM2
66 0F 7E D8      ;movd EAX, XMM3
66 0F 7E F0      ;movd EAX, XMM6
66 0F 7E F8      ;movd EAX, XMM7
66 0F 7E E8      ;movd EAX, XMM5
66 0F 7E F0      ;movd EAX, XMM6

Interestingly, if you just use the EAX register then it works ok eg.

This assembly:

asm
{
movd EAX, XMM1;
movd EAX, XMM2;
movd EAX, XMM3;
movd EAX, XMM4;
movd EAX, XMM5;
movd EAX, XMM6;
movd EAX, XMM7;
}

Produces this which is correct:

66 0F 7E C0         ;movd EAX, XMM0
66 0F 7E C8         ;movd EAX, XMM1
66 0F 7E D0         ;movd EAX, XMM2
66 0F 7E D8         ;movd EAX, XMM3
66 0F 7E E0         ;movd EAX, XMM4
66 0F 7E E8         ;movd EAX, XMM5
66 0F 7E F0         ;movd EAX, XMM6
66 0F 7E F8         ;movd EAX, XMM7

-------------------------------------------

Proof:

import std.stdio;

int main(char[][] args)
{
asm
{
// make sure XMM1 is not 0
mov EAX,1;
movd XMM1, EAX; // moving from reg32 to XMM works ok
mov EAX,0; // ok EAX is now 0

// here is the test
// we move XMM0 to the ECX register
// (EAX should be in no way affected by this)
movd ECX, XMM0; // actual instruction executed will be movd EAX,XMM1;

// right let's look at EAX now
cmp EAX,0;
je good;

// oh dear
}
writefln("EAX is not 0. We have a problem.");
return 1;
good:
writefln("EAX = 0. Everything is alright with the world");
return 0;
}

I assume that as DMD and DMC use the same backend then this bug also affects
DMC.

Regards,

pmoore





More information about the Digitalmars-d-bugs mailing list