source: core/c/jcpuid/src/jcpuid.c @ 38a6e6b

Last change on this file since 38a6e6b was 38a6e6b, checked in by zzz <zzz@…>, 10 years ago

restore old cpuid assembly for x64

  • Property mode set to 100644
File size: 3.0 KB
Line 
1#include "jcpuid.h"
2
3/**
4
5From: http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
6See also: http://homesource.nekomimicon.net/sourceforum/viewtopic.php?f=15&t=303
7
8Perhaps the most accessible documentation on what PIC code is and how an ELF dynamic linker works is
9John Levine's Linkers and Loaders (and it has amazing sketches, too!). The Gentoo documentation also
10has an Introduction to Position Independent Code. I'd like to give a few hints on how to fix the
11shlib-with-non-pic-code lintian error caused by inline assembly on the i386 and amd64 platforms,
12as well as build errors that may occur due to inline assembly being used.
13
14I'm not going to cover the trivial "all objects were not built using gcc's -fPIC flag" problem.
15It usually requires a fix to the build system, not to the code.
16
17  gcc can't find a register (i386)
18
19  PIC on i386 uses a register to store the GOT (global offset table) address.
20  This register is usually %ebx, making it unavailable for use by inline assembly
21  (and also restricting the compiler's register usage when compiling C or C++ code).
22  So the following perfectly valid code will not build with the -fPIC flag:
23
24     void cpuid(uint32_t op, uint32_t reg[4])
25     {
26        asm volatile("cpuid"
27                     : "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
28                     : "a"(op)
29                     : "cc");
30     }
31
32  Using -fPIC, gcc will say something around the lines of error: can't find a register in class 'BREG'
33  while reloading 'asm'. Several things need to be done to fix this:
34
35    * use a register other than %ebx
36    * save %ebx if it risks being clobbered by the assembly code, and don't tell gcc about %ebx at all (it doesn't need to know anyway)
37    * if we saved %ebx by pushing it on the stack, make sure the inline assembly code takes the new stack offset into account
38
39  And here is the PIC-compliant version:
40
41**/
42
43//Executes the indicated subfunction of the CPUID operation
44JNIEXPORT jobject JNICALL Java_freenet_support_CPUInformation_CPUID_doCPUID
45  (JNIEnv * env, jclass cls, jint iFunction)
46{
47        int a,b,c,d;
48        jclass clsResult = (*env)->FindClass(env, "freenet/support/CPUInformation/CPUID$CPUIDResult");
49        jmethodID constructor = (*env)->GetMethodID(env, clsResult,"<init>","(IIII)V" );
50        #ifdef _MSC_VER
51                //Use MSVC assembler notation
52                _asm
53                {
54                        mov eax, iFunction
55                        cpuid
56                        mov a, eax
57                        mov b, ebx
58                        mov c, ecx
59                        mov d, edx
60                }
61        #else
62                //Use GCC assembler notation
63                asm volatile
64                (
65#if (!defined(__X86_64__)) && (!defined(__x86_64__))
66                        /* 32 bit */
67                        "pushl %%ebx      \n\t" /* save %ebx */
68#endif
69                        "cpuid            \n\t"
70#if (!defined(__X86_64__)) && (!defined(__x86_64__))
71                        /* 32 bit */
72                        "movl %%ebx, %1   \n\t" /* save what cpuid just put in %ebx */
73                        "popl %%ebx       \n\t" /* restore the old %ebx */
74                        : "=a" (a), "=r" (b), "=c" (c), "=d" (d)
75#else
76                        /* 64 bit */
77                        : "=a" (a), "=b" (b), "=c" (c), "=d" (d)
78#endif
79                        :"a"(iFunction)
80                        : "cc"
81                );
82        #endif
83        return (*env)->NewObject(env, clsResult,constructor,a,b,c,d);
84}
85
Note: See TracBrowser for help on using the repository browser.