Emulate the cpuid arch intrinsic
This commit is contained in:
parent
847cc7ab2a
commit
c1a68b1386
5 changed files with 107 additions and 43 deletions
|
@ -126,6 +126,8 @@ fn panic(_: u128) {
|
||||||
|
|
||||||
#[target_feature(enable = "sse2")]
|
#[target_feature(enable = "sse2")]
|
||||||
unsafe fn test_simd() {
|
unsafe fn test_simd() {
|
||||||
|
assert!(is_x86_feature_detected!("sse2"));
|
||||||
|
|
||||||
let x = _mm_setzero_si128();
|
let x = _mm_setzero_si128();
|
||||||
let y = _mm_set1_epi16(7);
|
let y = _mm_set1_epi16(7);
|
||||||
let or = _mm_or_si128(x, y);
|
let or = _mm_or_si128(x, y);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
From 7403e2998345ef0650fd50628d7098d4d1e88e5c Mon Sep 17 00:00:00 2001
|
|
||||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
|
||||||
Date: Sat, 6 Apr 2019 12:16:21 +0200
|
|
||||||
Subject: [PATCH] Remove usage of unsized locals
|
|
||||||
|
|
||||||
---
|
|
||||||
library/stdarch/crates/core_arch/src/x86/cpuid.rs | 2 ++
|
|
||||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/library/stdarch/crates/core_arch/src/x86/cpuid.rs b/library/stdarch/crates/core_arch/src/x86/cpuid.rs
|
|
||||||
index f313c42..ff952bc 100644
|
|
||||||
--- a/library/stdarch/crates/core_arch/src/x86/cpuid.rs
|
|
||||||
+++ b/library/stdarch/crates/core_arch/src/x86/cpuid.rs
|
|
||||||
@@ -84,6 +84,11 @@ pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
|
|
||||||
/// Does the host support the `cpuid` instruction?
|
|
||||||
#[inline]
|
|
||||||
pub fn has_cpuid() -> bool {
|
|
||||||
+ // __cpuid intrinsic is not yet implemented
|
|
||||||
+ #[cfg(target_feature = "cg_clif")] {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
#[cfg(target_env = "sgx")]
|
|
||||||
{
|
|
||||||
false
|
|
||||||
--
|
|
||||||
2.20.1 (Apple Git-117)
|
|
52
src/base.rs
52
src/base.rs
|
@ -681,37 +681,57 @@ fn trans_stmt<'tcx>(
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
let LlvmInlineAsm {
|
let LlvmInlineAsm {
|
||||||
asm,
|
asm,
|
||||||
outputs: _,
|
outputs,
|
||||||
inputs: _,
|
inputs,
|
||||||
} = &**asm;
|
} = &**asm;
|
||||||
let rustc_hir::LlvmInlineAsmInner {
|
let rustc_hir::LlvmInlineAsmInner {
|
||||||
asm: asm_code, // Name
|
asm: asm_code, // Name
|
||||||
outputs, // Vec<Name>
|
outputs: output_names, // Vec<LlvmInlineAsmOutput>
|
||||||
inputs, // Vec<Name>
|
inputs: input_names, // Vec<Name>
|
||||||
clobbers, // Vec<Name>
|
clobbers, // Vec<Name>
|
||||||
volatile, // bool
|
volatile, // bool
|
||||||
alignstack, // bool
|
alignstack, // bool
|
||||||
dialect: _, // rustc_ast::ast::AsmDialect
|
dialect: _,
|
||||||
asm_str_style: _,
|
asm_str_style: _,
|
||||||
} = asm;
|
} = asm;
|
||||||
match &*asm_code.as_str() {
|
match asm_code.as_str().trim() {
|
||||||
"" => {
|
"" => {
|
||||||
// Black box
|
// Black box
|
||||||
}
|
}
|
||||||
cpuid if cpuid.contains("cpuid") => {
|
"mov %rbx, %rsi\n cpuid\n xchg %rbx, %rsi" => {
|
||||||
crate::trap::trap_unimplemented(
|
assert_eq!(input_names, &[Symbol::intern("{eax}"), Symbol::intern("{ecx}")]);
|
||||||
fx,
|
assert_eq!(output_names.len(), 4);
|
||||||
"__cpuid_count arch intrinsic is not supported",
|
for (i, c) in (&["={eax}", "={esi}", "={ecx}", "={edx}"]).iter().enumerate() {
|
||||||
);
|
assert_eq!(&output_names[i].constraint.as_str(), c);
|
||||||
|
assert!(!output_names[i].is_rw);
|
||||||
|
assert!(!output_names[i].is_indirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(clobbers, &[]);
|
||||||
|
|
||||||
|
assert!(!volatile);
|
||||||
|
assert!(!alignstack);
|
||||||
|
|
||||||
|
assert_eq!(inputs.len(), 2);
|
||||||
|
let leaf = trans_operand(fx, &inputs[0].1).load_scalar(fx); // %eax
|
||||||
|
let subleaf = trans_operand(fx, &inputs[1].1).load_scalar(fx); // %ecx
|
||||||
|
|
||||||
|
let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, subleaf);
|
||||||
|
|
||||||
|
assert_eq!(outputs.len(), 4);
|
||||||
|
trans_place(fx, outputs[0]).write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.tcx.types.u32)));
|
||||||
|
trans_place(fx, outputs[1]).write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32)));
|
||||||
|
trans_place(fx, outputs[2]).write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32)));
|
||||||
|
trans_place(fx, outputs[3]).write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32)));
|
||||||
}
|
}
|
||||||
"xgetbv" => {
|
"xgetbv" => {
|
||||||
assert_eq!(inputs, &[Symbol::intern("{ecx}")]);
|
assert_eq!(input_names, &[Symbol::intern("{ecx}")]);
|
||||||
|
|
||||||
assert_eq!(outputs.len(), 2);
|
assert_eq!(output_names.len(), 2);
|
||||||
for (i, c) in (&["={eax}", "={edx}"]).iter().enumerate() {
|
for (i, c) in (&["={eax}", "={edx}"]).iter().enumerate() {
|
||||||
assert_eq!(&outputs[i].constraint.as_str(), c);
|
assert_eq!(&output_names[i].constraint.as_str(), c);
|
||||||
assert!(!outputs[i].is_rw);
|
assert!(!output_names[i].is_rw);
|
||||||
assert!(!outputs[i].is_indirect);
|
assert!(!output_names[i].is_indirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(clobbers, &[]);
|
assert_eq!(clobbers, &[]);
|
||||||
|
|
67
src/intrinsics/cpuid.rs
Normal file
67
src/intrinsics/cpuid.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Emulates a subset of the cpuid call.
|
||||||
|
///
|
||||||
|
/// This emulates an intel cpu with sse and sse2 support, but which doesn't support anything else.
|
||||||
|
pub(crate) fn codegen_cpuid_call<'tcx>(
|
||||||
|
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
|
||||||
|
leaf: Value,
|
||||||
|
_subleaf: Value,
|
||||||
|
) -> (Value, Value, Value, Value) {
|
||||||
|
let leaf_0 = fx.bcx.create_block();
|
||||||
|
let leaf_1 = fx.bcx.create_block();
|
||||||
|
let leaf_8000_0000 = fx.bcx.create_block();
|
||||||
|
let leaf_8000_0001 = fx.bcx.create_block();
|
||||||
|
let unsupported_leaf = fx.bcx.create_block();
|
||||||
|
|
||||||
|
let dest = fx.bcx.create_block();
|
||||||
|
let eax = fx.bcx.append_block_param(dest, types::I32);
|
||||||
|
let ebx = fx.bcx.append_block_param(dest, types::I32);
|
||||||
|
let ecx = fx.bcx.append_block_param(dest, types::I32);
|
||||||
|
let edx = fx.bcx.append_block_param(dest, types::I32);
|
||||||
|
|
||||||
|
let mut switch = cranelift_frontend::Switch::new();
|
||||||
|
switch.set_entry(0, leaf_0);
|
||||||
|
switch.set_entry(1, leaf_1);
|
||||||
|
switch.set_entry(0x8000_0000, leaf_8000_0000);
|
||||||
|
switch.set_entry(0x8000_0001, leaf_8000_0001);
|
||||||
|
switch.emit(&mut fx.bcx, leaf, unsupported_leaf);
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(leaf_0);
|
||||||
|
let max_basic_leaf = fx.bcx.ins().iconst(types::I32, 1);
|
||||||
|
let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu")));
|
||||||
|
let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI")));
|
||||||
|
let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel")));
|
||||||
|
fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]);
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(leaf_1);
|
||||||
|
let cpu_signature = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
let additional_information = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
let ecx_features = fx.bcx.ins().iconst(
|
||||||
|
types::I32,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
let edx_features = fx.bcx.ins().iconst(
|
||||||
|
types::I32,
|
||||||
|
1 << 25 /* sse */ | 1 << 26 /* sse2 */,
|
||||||
|
);
|
||||||
|
fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]);
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(leaf_8000_0000);
|
||||||
|
let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]);
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(leaf_8000_0001);
|
||||||
|
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0);
|
||||||
|
fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]);
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(unsupported_leaf);
|
||||||
|
crate::trap::trap_unreachable(fx, "__cpuid_count arch intrinsic doesn't yet support specified leaf");
|
||||||
|
|
||||||
|
fx.bcx.switch_to_block(dest);
|
||||||
|
|
||||||
|
(eax, ebx, ecx, edx)
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
|
mod cpuid;
|
||||||
mod llvm;
|
mod llvm;
|
||||||
mod simd;
|
mod simd;
|
||||||
|
|
||||||
|
pub(crate) use cpuid::codegen_cpuid_call;
|
||||||
pub(crate) use llvm::codegen_llvm_intrinsic_call;
|
pub(crate) use llvm::codegen_llvm_intrinsic_call;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue