]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_cranelift/src/intrinsics/cpuid.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / compiler / rustc_codegen_cranelift / src / intrinsics / cpuid.rs
CommitLineData
29967ef6
XL
1//! Emulation of a subset of the cpuid x86 instruction.
2
3use 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.
8pub(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}