| ... | ... | @@ -72,14 +72,18 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | 74 | // Now we detect the model. |
| 75 | | switch (vendor) { |
| 76 | | 0x756e6547 => { |
| 77 | | detectIntelProcessor(&cpu, family, model, brand_id); |
| 78 | | }, |
| 79 | | 0x68747541 => { |
| 80 | | if (detectAMDProcessor(cpu, family, model)) |m| cpu.model = m; |
| 81 | | }, |
| 82 | | else => {}, |
| 75 | if (switch (vendor) { |
| 76 | 0x756e6547 => detectIntelProcessor(&cpu, family, model, brand_id), |
| 77 | 0x68747541 => detectAmdProcessor(&cpu, family, model), |
| 78 | else => null, |
| 79 | }) |m| b: { |
| 80 | // Some hypervisors are evil liars and will operate in long mode while identifying as a |
| 81 | // CPU model that never had long mode in reality. We've seen this in practice with |
| 82 | // athlon_xp (AMD K7). Catch this contradiction and fall back to using a generic CPU |
| 83 | // model with the features we detected earlier. |
| 84 | if (cpu.has(.x86, .@"64bit") and !Target.x86.featureSetHas(m.features, .@"64bit")) break :b; |
| 85 | |
| 86 | cpu.model = m; |
| 83 | 87 | } |
| 84 | 88 | } |
| 85 | 89 | |
| ... | ... | @@ -93,239 +97,85 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T |
| 93 | 97 | return cpu; |
| 94 | 98 | } |
| 95 | 99 | |
| 96 | | fn detectIntelProcessor(cpu: *Target.Cpu, family: u32, model: u32, brand_id: u32) void { |
| 97 | | if (brand_id != 0) { |
| 98 | | return; |
| 99 | | } |
| 100 | | switch (family) { |
| 101 | | 3 => { |
| 102 | | cpu.model = &Target.x86.cpu.i386; |
| 103 | | return; |
| 104 | | }, |
| 105 | | 4 => { |
| 106 | | cpu.model = &Target.x86.cpu.i486; |
| 107 | | return; |
| 108 | | }, |
| 109 | | 5 => { |
| 110 | | if (cpu.has(.x86, .mmx)) { |
| 111 | | cpu.model = &Target.x86.cpu.pentium_mmx; |
| 112 | | return; |
| 113 | | } |
| 114 | | cpu.model = &Target.x86.cpu.pentium; |
| 115 | | return; |
| 116 | | }, |
| 117 | | 6 => { |
| 118 | | switch (model) { |
| 119 | | 0x01 => { |
| 120 | | cpu.model = &Target.x86.cpu.pentiumpro; |
| 121 | | return; |
| 122 | | }, |
| 123 | | 0x03, 0x05, 0x06 => { |
| 124 | | cpu.model = &Target.x86.cpu.pentium2; |
| 125 | | return; |
| 126 | | }, |
| 127 | | 0x07, 0x08, 0x0a, 0x0b => { |
| 128 | | cpu.model = &Target.x86.cpu.pentium3; |
| 129 | | return; |
| 130 | | }, |
| 131 | | 0x09, 0x0d, 0x15 => { |
| 132 | | cpu.model = &Target.x86.cpu.pentium_m; |
| 133 | | return; |
| 134 | | }, |
| 135 | | 0x0e => { |
| 136 | | cpu.model = &Target.x86.cpu.yonah; |
| 137 | | return; |
| 138 | | }, |
| 139 | | 0x0f, 0x16 => { |
| 140 | | cpu.model = &Target.x86.cpu.core2; |
| 141 | | return; |
| 142 | | }, |
| 143 | | 0x17, 0x1d => { |
| 144 | | cpu.model = &Target.x86.cpu.penryn; |
| 145 | | return; |
| 146 | | }, |
| 147 | | 0x1a, 0x1e, 0x1f, 0x2e => { |
| 148 | | cpu.model = &Target.x86.cpu.nehalem; |
| 149 | | return; |
| 150 | | }, |
| 151 | | 0x25, 0x2c, 0x2f => { |
| 152 | | cpu.model = &Target.x86.cpu.westmere; |
| 153 | | return; |
| 154 | | }, |
| 155 | | 0x2a, 0x2d => { |
| 156 | | cpu.model = &Target.x86.cpu.sandybridge; |
| 157 | | return; |
| 158 | | }, |
| 159 | | 0x3a, 0x3e => { |
| 160 | | cpu.model = &Target.x86.cpu.ivybridge; |
| 161 | | return; |
| 162 | | }, |
| 163 | | 0x3c, 0x3f, 0x45, 0x46 => { |
| 164 | | cpu.model = &Target.x86.cpu.haswell; |
| 165 | | return; |
| 166 | | }, |
| 167 | | 0x3d, 0x47, 0x4f, 0x56 => { |
| 168 | | cpu.model = &Target.x86.cpu.broadwell; |
| 169 | | return; |
| 170 | | }, |
| 171 | | 0x4e, 0x5e, 0x8e, 0x9e, 0xa5, 0xa6 => { |
| 172 | | cpu.model = &Target.x86.cpu.skylake; |
| 173 | | return; |
| 174 | | }, |
| 175 | | 0xa7 => { |
| 176 | | cpu.model = &Target.x86.cpu.rocketlake; |
| 177 | | return; |
| 178 | | }, |
| 179 | | 0x55 => { |
| 180 | | if (cpu.has(.x86, .avx512bf16)) { |
| 181 | | cpu.model = &Target.x86.cpu.cooperlake; |
| 182 | | return; |
| 183 | | } else if (cpu.has(.x86, .avx512vnni)) { |
| 184 | | cpu.model = &Target.x86.cpu.cascadelake; |
| 185 | | return; |
| 186 | | } else { |
| 187 | | cpu.model = &Target.x86.cpu.skylake_avx512; |
| 188 | | return; |
| 189 | | } |
| 190 | | }, |
| 191 | | 0x66 => { |
| 192 | | cpu.model = &Target.x86.cpu.cannonlake; |
| 193 | | return; |
| 194 | | }, |
| 195 | | 0x7d, 0x7e => { |
| 196 | | cpu.model = &Target.x86.cpu.icelake_client; |
| 197 | | return; |
| 198 | | }, |
| 199 | | 0x6a, 0x6c => { |
| 200 | | cpu.model = &Target.x86.cpu.icelake_server; |
| 201 | | return; |
| 202 | | }, |
| 203 | | 0x8c, 0x8d => { |
| 204 | | cpu.model = &Target.x86.cpu.tigerlake; |
| 205 | | return; |
| 206 | | }, |
| 207 | | 0x97, 0x9a => { |
| 208 | | cpu.model = &Target.x86.cpu.alderlake; |
| 209 | | return; |
| 210 | | }, |
| 211 | | 0xbe => { |
| 212 | | cpu.model = &Target.x86.cpu.gracemont; |
| 213 | | return; |
| 214 | | }, |
| 215 | | 0xb7, 0xba, 0xbf => { |
| 216 | | cpu.model = &Target.x86.cpu.raptorlake; |
| 217 | | return; |
| 218 | | }, |
| 219 | | 0xaa, 0xac => { |
| 220 | | cpu.model = &Target.x86.cpu.meteorlake; |
| 221 | | return; |
| 222 | | }, |
| 223 | | 0xc5, 0xb5 => { |
| 224 | | cpu.model = &Target.x86.cpu.arrowlake; |
| 225 | | return; |
| 226 | | }, |
| 227 | | 0xc6 => { |
| 228 | | cpu.model = &Target.x86.cpu.arrowlake_s; |
| 229 | | return; |
| 230 | | }, |
| 231 | | 0xbd => { |
| 232 | | cpu.model = &Target.x86.cpu.lunarlake; |
| 233 | | return; |
| 234 | | }, |
| 235 | | 0xcc, 0xd5 => { |
| 236 | | cpu.model = &Target.x86.cpu.pantherlake; |
| 237 | | return; |
| 238 | | }, |
| 239 | | 0xad => { |
| 240 | | cpu.model = &Target.x86.cpu.graniterapids; |
| 241 | | return; |
| 242 | | }, |
| 243 | | 0xae => { |
| 244 | | cpu.model = &Target.x86.cpu.graniterapids_d; |
| 245 | | return; |
| 246 | | }, |
| 247 | | 0xcf => { |
| 248 | | cpu.model = &Target.x86.cpu.emeraldrapids; |
| 249 | | return; |
| 250 | | }, |
| 251 | | 0x8f => { |
| 252 | | cpu.model = &Target.x86.cpu.sapphirerapids; |
| 253 | | return; |
| 254 | | }, |
| 255 | | 0x1c, 0x26, 0x27, 0x35, 0x36 => { |
| 256 | | cpu.model = &Target.x86.cpu.bonnell; |
| 257 | | return; |
| 258 | | }, |
| 259 | | 0x37, 0x4a, 0x4d, 0x5a, 0x5d, 0x4c => { |
| 260 | | cpu.model = &Target.x86.cpu.silvermont; |
| 261 | | return; |
| 262 | | }, |
| 263 | | 0x5c, 0x5f => { |
| 264 | | cpu.model = &Target.x86.cpu.goldmont; |
| 265 | | return; |
| 266 | | }, |
| 267 | | 0x7a => { |
| 268 | | cpu.model = &Target.x86.cpu.goldmont_plus; |
| 269 | | return; |
| 270 | | }, |
| 271 | | 0x86, 0x8a, 0x96, 0x9c => { |
| 272 | | cpu.model = &Target.x86.cpu.tremont; |
| 273 | | return; |
| 274 | | }, |
| 275 | | 0xaf => { |
| 276 | | cpu.model = &Target.x86.cpu.sierraforest; |
| 277 | | return; |
| 278 | | }, |
| 279 | | 0xb6 => { |
| 280 | | cpu.model = &Target.x86.cpu.grandridge; |
| 281 | | return; |
| 282 | | }, |
| 283 | | 0xdd => { |
| 284 | | cpu.model = &Target.x86.cpu.clearwaterforest; |
| 285 | | return; |
| 286 | | }, |
| 287 | | 0x57 => { |
| 288 | | cpu.model = &Target.x86.cpu.knl; |
| 289 | | return; |
| 290 | | }, |
| 291 | | 0x85 => { |
| 292 | | cpu.model = &Target.x86.cpu.knm; |
| 293 | | return; |
| 294 | | }, |
| 295 | | else => return, // Unknown CPU Model |
| 296 | | } |
| 297 | | }, |
| 298 | | 15 => { |
| 299 | | if (cpu.has(.x86, .@"64bit")) { |
| 300 | | cpu.model = &Target.x86.cpu.nocona; |
| 301 | | return; |
| 302 | | } |
| 303 | | if (cpu.has(.x86, .sse3)) { |
| 304 | | cpu.model = &Target.x86.cpu.prescott; |
| 305 | | return; |
| 306 | | } |
| 307 | | cpu.model = &Target.x86.cpu.pentium4; |
| 308 | | return; |
| 100 | fn detectIntelProcessor(cpu: *const Target.Cpu, family: u32, model: u32, brand_id: u32) ?*const Target.Cpu.Model { |
| 101 | if (brand_id != 0) return null; |
| 102 | |
| 103 | return switch (family) { |
| 104 | 3 => &Target.x86.cpu.i386, |
| 105 | 4 => &Target.x86.cpu.i486, |
| 106 | 5 => if (cpu.has(.x86, .mmx)) |
| 107 | &Target.x86.cpu.pentium_mmx |
| 108 | else |
| 109 | &Target.x86.cpu.pentium, |
| 110 | 6 => switch (model) { |
| 111 | 0x01 => &Target.x86.cpu.pentiumpro, |
| 112 | 0x03, 0x05, 0x06 => &Target.x86.cpu.pentium2, |
| 113 | 0x07, 0x08, 0x0a, 0x0b => &Target.x86.cpu.pentium3, |
| 114 | 0x09, 0x0d, 0x15 => &Target.x86.cpu.pentium_m, |
| 115 | 0x0e => &Target.x86.cpu.yonah, |
| 116 | 0x0f, 0x16 => &Target.x86.cpu.core2, |
| 117 | 0x17, 0x1d => &Target.x86.cpu.penryn, |
| 118 | 0x1a, 0x1e, 0x1f, 0x2e => &Target.x86.cpu.nehalem, |
| 119 | 0x25, 0x2c, 0x2f => &Target.x86.cpu.westmere, |
| 120 | 0x2a, 0x2d => &Target.x86.cpu.sandybridge, |
| 121 | 0x3a, 0x3e => &Target.x86.cpu.ivybridge, |
| 122 | 0x3c, 0x3f, 0x45, 0x46 => &Target.x86.cpu.haswell, |
| 123 | 0x3d, 0x47, 0x4f, 0x56 => &Target.x86.cpu.broadwell, |
| 124 | 0x4e, 0x5e, 0x8e, 0x9e, 0xa5, 0xa6 => &Target.x86.cpu.skylake, |
| 125 | 0xa7 => &Target.x86.cpu.rocketlake, |
| 126 | 0x55 => if (cpu.has(.x86, .avx512bf16)) |
| 127 | &Target.x86.cpu.cooperlake |
| 128 | else if (cpu.has(.x86, .avx512vnni)) |
| 129 | &Target.x86.cpu.cascadelake |
| 130 | else |
| 131 | &Target.x86.cpu.skylake_avx512, |
| 132 | 0x66 => &Target.x86.cpu.cannonlake, |
| 133 | 0x7d, 0x7e => &Target.x86.cpu.icelake_client, |
| 134 | 0x6a, 0x6c => &Target.x86.cpu.icelake_server, |
| 135 | 0x8c, 0x8d => &Target.x86.cpu.tigerlake, |
| 136 | 0x97, 0x9a => &Target.x86.cpu.alderlake, |
| 137 | 0xbe => &Target.x86.cpu.gracemont, |
| 138 | 0xb7, 0xba, 0xbf => &Target.x86.cpu.raptorlake, |
| 139 | 0xaa, 0xac => &Target.x86.cpu.meteorlake, |
| 140 | 0xc5, 0xb5 => &Target.x86.cpu.arrowlake, |
| 141 | 0xc6 => &Target.x86.cpu.arrowlake_s, |
| 142 | 0xbd => &Target.x86.cpu.lunarlake, |
| 143 | 0xcc, 0xd5 => &Target.x86.cpu.pantherlake, |
| 144 | 0xad => &Target.x86.cpu.graniterapids, |
| 145 | 0xae => &Target.x86.cpu.graniterapids_d, |
| 146 | 0xcf => &Target.x86.cpu.emeraldrapids, |
| 147 | 0x8f => &Target.x86.cpu.sapphirerapids, |
| 148 | 0x1c, 0x26, 0x27, 0x35, 0x36 => &Target.x86.cpu.bonnell, |
| 149 | 0x37, 0x4a, 0x4d, 0x5a, 0x5d, 0x4c => &Target.x86.cpu.silvermont, |
| 150 | 0x5c, 0x5f => &Target.x86.cpu.goldmont, |
| 151 | 0x7a => &Target.x86.cpu.goldmont_plus, |
| 152 | 0x86, 0x8a, 0x96, 0x9c => &Target.x86.cpu.tremont, |
| 153 | 0xaf => &Target.x86.cpu.sierraforest, |
| 154 | 0xb6 => &Target.x86.cpu.grandridge, |
| 155 | 0xdd => &Target.x86.cpu.clearwaterforest, |
| 156 | 0x57 => &Target.x86.cpu.knl, |
| 157 | 0x85 => &Target.x86.cpu.knm, |
| 158 | else => null, |
| 309 | 159 | }, |
| 160 | 15 => if (cpu.has(.x86, .@"64bit")) |
| 161 | &Target.x86.cpu.nocona |
| 162 | else if (cpu.has(.x86, .sse3)) |
| 163 | &Target.x86.cpu.prescott |
| 164 | else |
| 165 | &Target.x86.cpu.pentium4, |
| 310 | 166 | 18 => switch (model) { |
| 311 | | 0x01, 0x03 => { |
| 312 | | cpu.model = &Target.x86.cpu.novalake; |
| 313 | | return; |
| 314 | | }, |
| 315 | | else => return, // Unknown CPU Model |
| 167 | 0x01, 0x03 => &Target.x86.cpu.novalake, |
| 168 | else => null, |
| 316 | 169 | }, |
| 317 | 170 | 19 => switch (model) { |
| 318 | | 0x01 => { |
| 319 | | cpu.model = &Target.x86.cpu.diamondrapids; |
| 320 | | return; |
| 321 | | }, |
| 322 | | else => return, // Unknown CPU Model |
| 171 | 0x01 => &Target.x86.cpu.diamondrapids, |
| 172 | else => null, |
| 323 | 173 | }, |
| 324 | | else => return, // Unknown CPU Model |
| 325 | | } |
| 174 | else => null, |
| 175 | }; |
| 326 | 176 | } |
| 327 | 177 | |
| 328 | | fn detectAMDProcessor(cpu: Target.Cpu, family: u32, model: u32) ?*const Target.Cpu.Model { |
| 178 | fn detectAmdProcessor(cpu: *const Target.Cpu, family: u32, model: u32) ?*const Target.Cpu.Model { |
| 329 | 179 | return switch (family) { |
| 330 | 180 | 4 => &Target.x86.cpu.i486, |
| 331 | 181 | 5 => switch (model) { |