]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
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>( | |
6a06907d | 9 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
29967ef6 XL |
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); | |
6a06907d XL |
34 | let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu"))); |
35 | let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI"))); | |
36 | let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel"))); | |
37 | fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]); | |
29967ef6 XL |
38 | |
39 | fx.bcx.switch_to_block(leaf_1); | |
40 | let cpu_signature = fx.bcx.ins().iconst(types::I32, 0); | |
41 | let additional_information = fx.bcx.ins().iconst(types::I32, 0); | |
42 | let ecx_features = fx.bcx.ins().iconst(types::I32, 0); | |
6a06907d XL |
43 | let edx_features = fx.bcx.ins().iconst(types::I32, 1 << 25 /* sse */ | 1 << 26 /* sse2 */); |
44 | fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]); | |
29967ef6 XL |
45 | |
46 | fx.bcx.switch_to_block(leaf_8000_0000); | |
47 | let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0); | |
48 | let zero = fx.bcx.ins().iconst(types::I32, 0); | |
6a06907d | 49 | fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]); |
29967ef6 XL |
50 | |
51 | fx.bcx.switch_to_block(leaf_8000_0001); | |
52 | let zero = fx.bcx.ins().iconst(types::I32, 0); | |
53 | let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0); | |
54 | let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0); | |
6a06907d | 55 | fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]); |
29967ef6 XL |
56 | |
57 | fx.bcx.switch_to_block(unsupported_leaf); | |
58 | crate::trap::trap_unreachable( | |
59 | fx, | |
60 | "__cpuid_count arch intrinsic doesn't yet support specified leaf", | |
61 | ); | |
62 | ||
63 | fx.bcx.switch_to_block(dest); | |
64 | fx.bcx.ins().nop(); | |
65 | ||
66 | (eax, ebx, ecx, edx) | |
67 | } |