Page 1 of 1

gcc compiling wrong or am I wrong

Posted: Mon Mar 16, 2009 10:16 am
by FlashBurn
I have the following c code:

Code: Select all

static inline uint32t getEFlags() {
	uint32t val;
	
	asm volatile("pushfl\n\tpopl %%eax"
		:"=A"(val));
	
	return val;
}

static inline void setEFlags(uint32t flags) {
	asm volatile("pushl %%eax\n\tpopfl"
		:
		:"A"(flags));
}

uint32t checkCPUID() {
	uint32t flags= getEFlags();
	
	setEFlags(flags ^ 0x200000);
	
	if(unlikely((flags ^ getEFlags()) == 0))
		return 0;
	
	return 1;
}
And this is what gcc makes out of it:

Code: Select all

.globl checkCPUID
	.type	checkCPUID, @function
checkCPUID:
	pushl	%ebp
	movl	%esp, %ebp
/APP
/ 171 "../src/include/asm.h" 1
	pushfl
	popl %eax
/ 0 "" 2
/NO_APP
	movl	%edx, %eax
	xorl	$2097152, %eax
/APP
/ 178 "../src/include/asm.h" 1
	pushl %eax
	popfl
/ 0 "" 2
/ 171 "../src/include/asm.h" 1
	pushfl
	popl %eax
/ 0 "" 2
/NO_APP
	cmpl	%eax, %edx
	popl	%ebp
	setne	%al
	movzbl	%al, %eax
	ret
	.size	checkCPUID, .-checkCPUID
The problem there is the line after I get the eflags, gcc should save eax into edx, but it moves edx into eax or am I getting this wrong?

The funny thing is, my code worked all the time, because I compiled it with the -O2 flag and so gcc has some "good" value in edx, but today I wanted to see how much space I can save if I´m compiling with the -Os flag and now there is a "bad" value in edx and my code doesn´t work anymore ;)

Re: gcc compiling wrong or am I wrong

Posted: Mon Mar 16, 2009 11:38 am
by JamesM
Hi,

A couple of things - firstly the inline asm code for register EAX is "a", not "A". The case does matter, for example "d" is EDX and "D" is EDI.

I think that GCC hasn't understood your constraint properly and so is assigning a random register for your variable "val", which happens to be EDX.

The solution is either to change your "A" to "a", or remove the constraint entirely and let GCC allocate a register for you. This is the option I would suggest.

Code: Select all

static inline uint32t getEFlags() {
   uint32t val;
   
   asm volatile("pushfl\n\tpopl %0"
      :"=r"(val));
   
   return val;
}

static inline void setEFlags(uint32t flags) {
   asm volatile("pushl %0\n\tpopfl"
      :
      :"r"(flags));
}

uint32t checkCPUID() {
   uint32t flags= getEFlags();
   
   setEFlags(flags ^ 0x200000);
   
   if(unlikely((flags ^ getEFlags()) == 0))
      return 0;
   
   return 1;
}
Cheers,

James

Re: gcc compiling wrong or am I wrong

Posted: Mon Mar 16, 2009 1:15 pm
by FlashBurn
Thanks!!!

That I didn´t see this my self!? "A" stands for a 64bit value in edx:eax. Now my code works for every optimizing level.