Home | History | Annotate | Download | only in libpng
      1 /* pnggccrd.c was removed from libpng-1.2.20. */
      2 
      3 /* This code snippet is for use by configure's compilation test. */
      4 
      5 #if (!defined _MSC_VER) && \
      6     defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
      7     defined(PNG_MMX_CODE_SUPPORTED)
      8 
      9 int PNGAPI png_dummy_mmx_support(void);
     10 
     11 static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested
     12 
     13 int PNGAPI
     14 png_dummy_mmx_support(void) __attribute__((noinline));
     15 
     16 int PNGAPI
     17 png_dummy_mmx_support(void)
     18 {
     19    int result;
     20 #ifdef PNG_MMX_CODE_SUPPORTED  // superfluous, but what the heck
     21     __asm__ __volatile__ (
     22 #ifdef __x86_64__
     23         "pushq %%rbx          \n\t"  // rbx gets clobbered by CPUID instruction
     24         "pushq %%rcx          \n\t"  // so does rcx...
     25         "pushq %%rdx          \n\t"  // ...and rdx (but rcx & rdx safe on Linux)
     26         "pushfq               \n\t"  // save Eflag to stack
     27         "popq %%rax           \n\t"  // get Eflag from stack into rax
     28         "movq %%rax, %%rcx    \n\t"  // make another copy of Eflag in rcx
     29         "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
     30         "pushq %%rax          \n\t"  // save modified Eflag back to stack
     31         "popfq                \n\t"  // restore modified value to Eflag reg
     32         "pushfq               \n\t"  // save Eflag to stack
     33         "popq %%rax           \n\t"  // get Eflag from stack
     34         "pushq %%rcx          \n\t"  // save original Eflag to stack
     35         "popfq                \n\t"  // restore original Eflag
     36 #else
     37         "pushl %%ebx          \n\t"  // ebx gets clobbered by CPUID instruction
     38         "pushl %%ecx          \n\t"  // so does ecx...
     39         "pushl %%edx          \n\t"  // ...and edx (but ecx & edx safe on Linux)
     40         "pushfl               \n\t"  // save Eflag to stack
     41         "popl %%eax           \n\t"  // get Eflag from stack into eax
     42         "movl %%eax, %%ecx    \n\t"  // make another copy of Eflag in ecx
     43         "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
     44         "pushl %%eax          \n\t"  // save modified Eflag back to stack
     45         "popfl                \n\t"  // restore modified value to Eflag reg
     46         "pushfl               \n\t"  // save Eflag to stack
     47         "popl %%eax           \n\t"  // get Eflag from stack
     48         "pushl %%ecx          \n\t"  // save original Eflag to stack
     49         "popfl                \n\t"  // restore original Eflag
     50 #endif
     51         "xorl %%ecx, %%eax    \n\t"  // compare new Eflag with original Eflag
     52         "jz 0f                \n\t"  // if same, CPUID instr. is not supported
     53 
     54         "xorl %%eax, %%eax    \n\t"  // set eax to zero
     55 //      ".byte  0x0f, 0xa2    \n\t"  // CPUID instruction (two-byte opcode)
     56         "cpuid                \n\t"  // get the CPU identification info
     57         "cmpl $1, %%eax       \n\t"  // make sure eax return non-zero value
     58         "jl 0f                \n\t"  // if eax is zero, MMX is not supported
     59 
     60         "xorl %%eax, %%eax    \n\t"  // set eax to zero and...
     61         "incl %%eax           \n\t"  // ...increment eax to 1.  This pair is
     62                                      // faster than the instruction "mov eax, 1"
     63         "cpuid                \n\t"  // get the CPU identification info again
     64         "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
     65         "cmpl $0, %%edx       \n\t"  // 0 = MMX not supported
     66         "jz 0f                \n\t"  // non-zero = yes, MMX IS supported
     67 
     68         "movl $1, %%eax       \n\t"  // set return value to 1
     69         "jmp  1f              \n\t"  // DONE:  have MMX support
     70 
     71     "0:                       \n\t"  // .NOT_SUPPORTED: target label for jump instructions
     72         "movl $0, %%eax       \n\t"  // set return value to 0
     73     "1:                       \n\t"  // .RETURN: target label for jump instructions
     74 #ifdef __x86_64__
     75         "popq %%rdx           \n\t"  // restore rdx
     76         "popq %%rcx           \n\t"  // restore rcx
     77         "popq %%rbx           \n\t"  // restore rbx
     78 #else
     79         "popl %%edx           \n\t"  // restore edx
     80         "popl %%ecx           \n\t"  // restore ecx
     81         "popl %%ebx           \n\t"  // restore ebx
     82 #endif
     83 
     84 //      "ret                  \n\t"  // DONE:  no MMX support
     85                                      // (fall through to standard C "ret")
     86 
     87         : "=a" (result)              // output list
     88 
     89         :                            // any variables used on input (none)
     90 
     91                                      // no clobber list
     92 //      , "%ebx", "%ecx", "%edx"     // GRR:  we handle these manually
     93 //      , "memory"   // if write to a variable gcc thought was in a reg
     94 //      , "cc"       // "condition codes" (flag bits)
     95     );
     96     _mmx_supported = result;
     97 #else
     98     _mmx_supported = 0;
     99 #endif /* PNG_MMX_CODE_SUPPORTED */
    100 
    101     return _mmx_supported;
    102 }
    103 #endif
    104