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