github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-cpuid-x86.c (about) 1 /* 2 * jit-cpuid-x86.c - Wrapper for the CPUID instruction. 3 * 4 * Copyright (C) 2004 Southern Storm Software, Pty Ltd. 5 * 6 * This file is part of the libjit library. 7 * 8 * The libjit library is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation, either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * The libjit library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with the libjit library. If not, see 20 * <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "jit-cpuid-x86.h" 24 25 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) 26 27 /* 28 * Determine if the "cpuid" instruction is present by twiddling 29 * bit 21 of the EFLAGS register. 30 */ 31 static int cpuid_present(void) 32 { 33 #if defined(__GNUC__) 34 int result; 35 __asm__ __volatile__ ( 36 "\tpushfl\n" 37 "\tpopl %%eax\n" 38 "\tmovl %%eax, %%ecx\n" 39 "\tandl $0x200000, %%ecx\n" 40 "\txorl $0x200000, %%eax\n" 41 "\tpushl %%eax\n" 42 "\tpopfl\n" 43 "\tpushfl\n" 44 "\tandl $0x200000, %%eax\n" 45 "\txorl %%ecx, %%eax\n" 46 "\tmovl %%eax, %0\n" 47 : "=m" (result) : : "eax", "ecx" 48 ); 49 return (result != 0); 50 #else 51 return 0; 52 #endif 53 } 54 55 /* 56 * Issue a "cpuid" query and get the result. 57 */ 58 static void cpuid_query(unsigned int index, jit_cpuid_x86_t *info) 59 { 60 #if defined(__GNUC__) 61 __asm__ __volatile__ ( 62 "\tmovl %0, %%eax\n" 63 "\tpushl %%ebx\n" 64 "\txorl %%ebx, %%ebx\n" 65 "\txorl %%ecx, %%ecx\n" 66 "\txorl %%edx, %%edx\n" 67 "\t.byte 0x0F\n" /* cpuid, safe against old assemblers */ 68 "\t.byte 0xA2\n" 69 "\tmovl %1, %%esi\n" 70 "\tmovl %%eax, (%%esi)\n" 71 "\tmovl %%ebx, 4(%%esi)\n" 72 "\tmovl %%ecx, 8(%%esi)\n" 73 "\tmovl %%edx, 12(%%esi)\n" 74 "\tpopl %%ebx\n" 75 : : "m"(index), "m"(info) : "eax", "ecx", "edx", "esi" 76 ); 77 #endif 78 } 79 80 int _jit_cpuid_x86_get(unsigned int index, jit_cpuid_x86_t *info) 81 { 82 /* Determine if this cpu has the "cpuid" instruction */ 83 if(!cpuid_present()) 84 { 85 return 0; 86 } 87 88 /* Validate the index */ 89 if((index & 0x80000000) == 0) 90 { 91 cpuid_query(0, info); 92 } 93 else 94 { 95 cpuid_query(0x80000000, info); 96 } 97 if(index > info->eax) 98 { 99 return 0; 100 } 101 102 /* Execute the actual requested query */ 103 cpuid_query(index, info); 104 return 1; 105 } 106 107 int _jit_cpuid_x86_has_feature(unsigned int feature) 108 { 109 jit_cpuid_x86_t info; 110 if(!_jit_cpuid_x86_get(JIT_X86CPUID_FEATURES, &info)) 111 { 112 return 0; 113 } 114 return ((info.edx & feature) != 0); 115 } 116 117 unsigned int _jit_cpuid_x86_line_size(void) 118 { 119 jit_cpuid_x86_t info; 120 if(!_jit_cpuid_x86_get(JIT_X86CPUID_FEATURES, &info)) 121 { 122 return 0; 123 } 124 if((info.edx & JIT_X86FEATURE_CLFSH) == 0) 125 { 126 return 0; 127 } 128 return ((info.ebx & 0x0000FF00) >> 5); 129 } 130 131 #endif /* i386 */