Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save przemoc/2991972 to your computer and use it in GitHub Desktop.
Save przemoc/2991972 to your computer and use it in GitHub Desktop.
Patch for festalon 0.5.5 to make it compilable on amd64 (Ryan C. Underwood's one is needlessly big and breaking DRY rule). // http://projects.raphnet.net/#festalon
From: Przemyslaw Pawelczyk <przemoc@gmail.com>
Date: Sun, 8 May 2011 23:16:55 +0200
Subject: [PATCH] Fix CPUID availability test for x86_64.
Before you got following gcc/clang error in x86_64:
cputest.c: Assembler messages:
cputest.c:38: Error: suffix or operands invalid for `pop'
cputest.c:41: Error: suffix or operands invalid for `push'
cputest.c:44: Error: suffix or operands invalid for `pop'
"=a" (int32_t) ties %N to 32-bit register, thus eax is obligatorily used
also in 64-bit code. Maybe it's debatable behaviour, but let's leave it.
So what's the problem with pop/push, is popl/pushl eax incorrect in x64?
Exactly! Doubts? See: http://www.x86-64.org/documentation/assembly.html.
There is no need to use preprocessor and clutter this simple code.
Introducing dummy long variable in "a" guarantees that %N will be tied
with with register of processor's word size, i.e. rax in x64. Cost of
this simplification is compiler spitting useless xor eax,eax in front of
the asm block (at least in gcc 4.4), but it's really negligible.
In the end we get same asm block output in x86 and x86_64: (xor)
(31 c0) 9c 58 89 c1 35 00 00 20 00 50 9d 9c 58
Signed-off-by: Przemyslaw Pawelczyk <przemoc@gmail.com>
---
src/cputest.c | 35 ++++++++++++++---------------------
1 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/src/cputest.c b/src/cputest.c
index fffbc16..b09609b 100644
--- a/src/cputest.c
+++ b/src/cputest.c
@@ -32,37 +32,30 @@ static int mm_support(void)
#ifdef ARCH_X86
int rval;
int eax, ebx, ecx, edx;
+ long dummy;
char vendor[13] = "UnknownVndr";
+ /* CPUID availability (xFLAGS ID bit togglability) test */
__asm__ __volatile__ (
- /* See if CPUID instruction is supported ... */
- /* ... Get copies of EFLAGS into eax and ecx */
+ /* Load xFLAGS into xAX */
"pushf\n\t"
-#ifdef __x86_64__
- "pop %0\n\t"
-#else
- "popl %0\n\t"
-#endif
+ "pop %2\n\t"
- "movl %0, %1\n\t"
+ /* Copy EAX to ECX (low 32-bits of xFLAGS) */
+ "mov %0, %1\n\t"
-
- /* ... Toggle the ID bit in one copy and store */
- /* to the EFLAGS reg */
- "xorl $0x200000, %0\n\t"
+ /* Toggle xFLAGS.ID bit in EAX */
+ "xor $0x200000, %0\n\t"
- "push %0\n\t"
+ /* Load xAX into xFLAGS */
+ "push %2\n\t"
"popf\n\t"
-
- /* ... Get the (hopefully modified) EFLAGS */
+ /* Load (hopefully modified) xFLAGS into xAX */
"pushf\n\t"
-#ifdef __x86_64__
- "pop %0\n\t"
-#else
- "popl %0\n\t"
-#endif
+ "pop %2\n\t"
: "=a" (eax), "=c" (ecx)
- :
+ : "a" (dummy)
: "cc"
);
+ /* Check whether xFLAGS.ID bit was toggled */
if (eax == ecx)
return 0; /* CPUID not supported */
--
1.7.4.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment