1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "CPUID.hpp" 16 17 #if defined(_WIN32) 18 #ifndef WIN32_LEAN_AND_MEAN 19 #define WIN32_LEAN_AND_MEAN 20 #endif 21 #include <windows.h> 22 #include <intrin.h> 23 #include <float.h> 24 #else 25 #include <unistd.h> 26 #include <sched.h> 27 #include <sys/types.h> 28 #endif 29 30 namespace rr 31 { 32 bool CPUID::MMX = detectMMX(); 33 bool CPUID::CMOV = detectCMOV(); 34 bool CPUID::SSE = detectSSE(); 35 bool CPUID::SSE2 = detectSSE2(); 36 bool CPUID::SSE3 = detectSSE3(); 37 bool CPUID::SSSE3 = detectSSSE3(); 38 bool CPUID::SSE4_1 = detectSSE4_1(); 39 40 bool CPUID::enableMMX = true; 41 bool CPUID::enableCMOV = true; 42 bool CPUID::enableSSE = true; 43 bool CPUID::enableSSE2 = true; 44 bool CPUID::enableSSE3 = true; 45 bool CPUID::enableSSSE3 = true; 46 bool CPUID::enableSSE4_1 = true; 47 48 void CPUID::setEnableMMX(bool enable) 49 { 50 enableMMX = enable; 51 52 if(!enableMMX) 53 { 54 enableSSE = false; 55 enableSSE2 = false; 56 enableSSE3 = false; 57 enableSSSE3 = false; 58 enableSSE4_1 = false; 59 } 60 } 61 62 void CPUID::setEnableCMOV(bool enable) 63 { 64 enableCMOV = enable; 65 66 if(!CMOV) 67 { 68 enableSSE = false; 69 enableSSE2 = false; 70 enableSSE3 = false; 71 enableSSSE3 = false; 72 enableSSE4_1 = false; 73 } 74 } 75 76 void CPUID::setEnableSSE(bool enable) 77 { 78 enableSSE = enable; 79 80 if(enableSSE) 81 { 82 enableMMX = true; 83 enableCMOV = true; 84 } 85 else 86 { 87 enableSSE2 = false; 88 enableSSE3 = false; 89 enableSSSE3 = false; 90 enableSSE4_1 = false; 91 } 92 } 93 94 void CPUID::setEnableSSE2(bool enable) 95 { 96 enableSSE2 = enable; 97 98 if(enableSSE2) 99 { 100 enableMMX = true; 101 enableCMOV = true; 102 enableSSE = true; 103 } 104 else 105 { 106 enableSSE3 = false; 107 enableSSSE3 = false; 108 enableSSE4_1 = false; 109 } 110 } 111 112 void CPUID::setEnableSSE3(bool enable) 113 { 114 enableSSE3 = enable; 115 116 if(enableSSE3) 117 { 118 enableMMX = true; 119 enableCMOV = true; 120 enableSSE = true; 121 enableSSE2 = true; 122 } 123 else 124 { 125 enableSSSE3 = false; 126 enableSSE4_1 = false; 127 } 128 } 129 130 void CPUID::setEnableSSSE3(bool enable) 131 { 132 enableSSSE3 = enable; 133 134 if(enableSSSE3) 135 { 136 enableMMX = true; 137 enableCMOV = true; 138 enableSSE = true; 139 enableSSE2 = true; 140 enableSSE3 = true; 141 } 142 else 143 { 144 enableSSE4_1 = false; 145 } 146 } 147 148 void CPUID::setEnableSSE4_1(bool enable) 149 { 150 enableSSE4_1 = enable; 151 152 if(enableSSE4_1) 153 { 154 enableMMX = true; 155 enableCMOV = true; 156 enableSSE = true; 157 enableSSE2 = true; 158 enableSSE3 = true; 159 enableSSSE3 = true; 160 } 161 } 162 163 static void cpuid(int registers[4], int info) 164 { 165 #if defined(__i386__) || defined(__x86_64__) 166 #if defined(_WIN32) 167 __cpuid(registers, info); 168 #else 169 __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info)); 170 #endif 171 #else 172 registers[0] = 0; 173 registers[1] = 0; 174 registers[2] = 0; 175 registers[3] = 0; 176 #endif 177 } 178 179 bool CPUID::detectMMX() 180 { 181 int registers[4]; 182 cpuid(registers, 1); 183 return MMX = (registers[3] & 0x00800000) != 0; 184 } 185 186 bool CPUID::detectCMOV() 187 { 188 int registers[4]; 189 cpuid(registers, 1); 190 return CMOV = (registers[3] & 0x00008000) != 0; 191 } 192 193 bool CPUID::detectSSE() 194 { 195 int registers[4]; 196 cpuid(registers, 1); 197 return SSE = (registers[3] & 0x02000000) != 0; 198 } 199 200 bool CPUID::detectSSE2() 201 { 202 int registers[4]; 203 cpuid(registers, 1); 204 return SSE2 = (registers[3] & 0x04000000) != 0; 205 } 206 207 bool CPUID::detectSSE3() 208 { 209 int registers[4]; 210 cpuid(registers, 1); 211 return SSE3 = (registers[2] & 0x00000001) != 0; 212 } 213 214 bool CPUID::detectSSSE3() 215 { 216 int registers[4]; 217 cpuid(registers, 1); 218 return SSSE3 = (registers[2] & 0x00000200) != 0; 219 } 220 221 bool CPUID::detectSSE4_1() 222 { 223 int registers[4]; 224 cpuid(registers, 1); 225 return SSE4_1 = (registers[2] & 0x00080000) != 0; 226 } 227 } 228