Reputation: 1765
Linux 64.
GCC 4.8.2 (with -O3 -march=native)
The x86_64 abi under my left hand, opened at page 21.
int main (int argc, char ** argv) {
int16_t h = atoi(argv[1]) ;
int16_t p;
__asm__ ("mov %2, %0\n\t"
"rol $8,%1\n\t"
: "=r" (p) /* output operands */
: "0"(p),"g"(h)/* input operands */
:"cc"); /* clobbered operands */
printf("%d %d\n", h, p);
return 0;
}
...
movl $10, %edx
movq 8(%rsi), %rdi
xorl %esi, %esi
call strtol
xorl %edx, %edx
movl $.LC0, %edi
#APP
# 1627 "test2ptr.c" 1
movl %ax, %dx <- set in %dx
rol $8,%dx
# 0 "" 2
#NO_APP
movswl %ax, %esi
movswl %dx, %edx <- Then this line should not appear
xorl %eax, %eax
call printf
xorl %eax, %eax
...
If I comment it, the result is fine.
But I cannot rely on modifying the source (unmaintainable : every time one change something in the source, one would have to come back in that spot to be sure it is still working.. no go).
Why is the line movswl %dx, %edx
kept ?
It should move a long in a word. But it is already done by me and cost me one superfluous clock.
Is there any workaround ?
Is it just an option I didn't set ?
Thanks
Upvotes: 1
Views: 40
Reputation: 1765
Ok,
So the workaround is to set int32_t and not int16_t.
Now the code is... 2 cpu cycles faster.
That is ridiculous.
But I like assembly so much now :)
Upvotes: 0
Reputation: 58762
Since you specified a 16 bit type, but printf
expects 32 bit integers, your result needs to be sign extended which is what that code does. Nevertheless, if you used the proper format for printf
both versions should produce identical output.
As usual, you don't need inline asm for a rotate, and also if you ever use a mov
in inline asm chances are you are doing it wrong.
Upvotes: 1