]> git.lizzy.rs Git - rust.git/blob - src/intrinsics/cpuid.rs
9d971d97b88c6d32e32bd13a185f4f62941bd51b
[rust.git] / src / intrinsics / cpuid.rs
1 use crate::prelude::*;
2
3 /// Emulates a subset of the cpuid call.
4 ///
5 /// This emulates an intel cpu with sse and sse2 support, but which doesn't support anything else.
6 pub(crate) fn codegen_cpuid_call<'tcx>(
7     fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
8     leaf: Value,
9     _subleaf: Value,
10 ) -> (Value, Value, Value, Value) {
11     let leaf_0 = fx.bcx.create_block();
12     let leaf_1 = fx.bcx.create_block();
13     let leaf_8000_0000 = fx.bcx.create_block();
14     let leaf_8000_0001 = fx.bcx.create_block();
15     let unsupported_leaf = fx.bcx.create_block();
16
17     let dest = fx.bcx.create_block();
18     let eax = fx.bcx.append_block_param(dest, types::I32);
19     let ebx = fx.bcx.append_block_param(dest, types::I32);
20     let ecx = fx.bcx.append_block_param(dest, types::I32);
21     let edx = fx.bcx.append_block_param(dest, types::I32);
22
23     let mut switch = cranelift_frontend::Switch::new();
24     switch.set_entry(0, leaf_0);
25     switch.set_entry(1, leaf_1);
26     switch.set_entry(0x8000_0000, leaf_8000_0000);
27     switch.set_entry(0x8000_0001, leaf_8000_0001);
28     switch.emit(&mut fx.bcx, leaf, unsupported_leaf);
29
30     fx.bcx.switch_to_block(leaf_0);
31     let max_basic_leaf = fx.bcx.ins().iconst(types::I32, 1);
32     let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu")));
33     let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI")));
34     let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel")));
35     fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]);
36
37     fx.bcx.switch_to_block(leaf_1);
38     let cpu_signature = fx.bcx.ins().iconst(types::I32, 0);
39     let additional_information = fx.bcx.ins().iconst(types::I32, 0);
40     let ecx_features = fx.bcx.ins().iconst(
41         types::I32,
42         0,
43     );
44     let edx_features = fx.bcx.ins().iconst(
45         types::I32,
46         1 << 25 /* sse */ | 1 << 26 /* sse2 */,
47     );
48     fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]);
49
50     fx.bcx.switch_to_block(leaf_8000_0000);
51     let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0);
52     let zero = fx.bcx.ins().iconst(types::I32, 0);
53     fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]);
54
55     fx.bcx.switch_to_block(leaf_8000_0001);
56     let zero = fx.bcx.ins().iconst(types::I32, 0);
57     let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0);
58     let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0);
59     fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]);
60
61     fx.bcx.switch_to_block(unsupported_leaf);
62     crate::trap::trap_unreachable(fx, "__cpuid_count arch intrinsic doesn't yet support specified leaf");
63
64     fx.bcx.switch_to_block(dest);
65     fx.bcx.ins().nop();
66
67     (eax, ebx, ecx, edx)
68 }