Skip to content

Commit 82487a9

Browse files
authored
Merge pull request #1417 from rust-lang/implement_xgetbv
Implement a lot of SIMD intrinsics
2 parents 9f426ce + 8649731 commit 82487a9

File tree

3 files changed

+548
-37
lines changed

3 files changed

+548
-37
lines changed

src/inline_asm.rs

+89-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::prelude::*;
1313
enum CInlineAsmOperand<'tcx> {
1414
In {
1515
reg: InlineAsmRegOrRegClass,
16-
value: CValue<'tcx>,
16+
value: Value,
1717
},
1818
Out {
1919
reg: InlineAsmRegOrRegClass,
@@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> {
2323
InOut {
2424
reg: InlineAsmRegOrRegClass,
2525
_late: bool,
26-
in_value: CValue<'tcx>,
26+
in_value: Value,
2727
out_place: Option<CPlace<'tcx>>,
2828
},
2929
Const {
@@ -57,9 +57,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
5757
let operands = operands
5858
.into_iter()
5959
.map(|operand| match *operand {
60-
InlineAsmOperand::In { reg, ref value } => {
61-
CInlineAsmOperand::In { reg, value: crate::base::codegen_operand(fx, value) }
62-
}
60+
InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In {
61+
reg,
62+
value: crate::base::codegen_operand(fx, value).load_scalar(fx),
63+
},
6364
InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out {
6465
reg,
6566
late,
@@ -69,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
6970
CInlineAsmOperand::InOut {
7071
reg,
7172
_late: late,
72-
in_value: crate::base::codegen_operand(fx, in_value),
73+
in_value: crate::base::codegen_operand(fx, in_value).load_scalar(fx),
7374
out_place: out_place.map(|place| crate::base::codegen_place(fx, place)),
7475
}
7576
}
@@ -167,15 +168,15 @@ pub(crate) fn codegen_inline_asm<'tcx>(
167168
for (i, operand) in operands.iter().enumerate() {
168169
match operand {
169170
CInlineAsmOperand::In { reg: _, value } => {
170-
inputs.push((asm_gen.stack_slots_input[i].unwrap(), value.load_scalar(fx)));
171+
inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value));
171172
}
172173
CInlineAsmOperand::Out { reg: _, late: _, place } => {
173174
if let Some(place) = place {
174175
outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place));
175176
}
176177
}
177178
CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => {
178-
inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx)));
179+
inputs.push((asm_gen.stack_slots_input[i].unwrap(), *in_value));
179180
if let Some(out_place) = out_place {
180181
outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place));
181182
}
@@ -728,3 +729,83 @@ fn call_inline_asm<'tcx>(
728729
place.write_cvalue(fx, CValue::by_val(value, place.layout()));
729730
}
730731
}
732+
733+
pub(crate) fn codegen_xgetbv<'tcx>(
734+
fx: &mut FunctionCx<'_, '_, 'tcx>,
735+
xcr_no: Value,
736+
ret: CPlace<'tcx>,
737+
) {
738+
// FIXME add .eh_frame unwind info directives
739+
740+
let operands = vec![
741+
CInlineAsmOperand::In {
742+
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
743+
value: xcr_no,
744+
},
745+
CInlineAsmOperand::Out {
746+
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
747+
late: true,
748+
place: Some(ret),
749+
},
750+
CInlineAsmOperand::Out {
751+
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
752+
late: true,
753+
place: None,
754+
},
755+
];
756+
let options = InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM;
757+
758+
let mut inputs = Vec::new();
759+
let mut outputs = Vec::new();
760+
761+
let mut asm_gen = InlineAssemblyGenerator {
762+
tcx: fx.tcx,
763+
arch: fx.tcx.sess.asm_arch.unwrap(),
764+
enclosing_def_id: fx.instance.def_id(),
765+
template: &[InlineAsmTemplatePiece::String(
766+
"
767+
xgetbv
768+
// out = rdx << 32 | rax
769+
shl rdx, 32
770+
or rax, rdx
771+
"
772+
.to_string(),
773+
)],
774+
operands: &operands,
775+
options,
776+
registers: Vec::new(),
777+
stack_slots_clobber: Vec::new(),
778+
stack_slots_input: Vec::new(),
779+
stack_slots_output: Vec::new(),
780+
stack_slot_size: Size::from_bytes(0),
781+
};
782+
asm_gen.allocate_registers();
783+
asm_gen.allocate_stack_slots();
784+
785+
let inline_asm_index = fx.cx.inline_asm_index.get();
786+
fx.cx.inline_asm_index.set(inline_asm_index + 1);
787+
let asm_name = format!(
788+
"__inline_asm_{}_n{}",
789+
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
790+
inline_asm_index
791+
);
792+
793+
let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
794+
fx.cx.global_asm.push_str(&generated_asm);
795+
796+
for (i, operand) in operands.iter().enumerate() {
797+
match operand {
798+
CInlineAsmOperand::In { reg: _, value } => {
799+
inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value));
800+
}
801+
CInlineAsmOperand::Out { reg: _, late: _, place } => {
802+
if let Some(place) = place {
803+
outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place));
804+
}
805+
}
806+
_ => unreachable!(),
807+
}
808+
}
809+
810+
call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
811+
}

0 commit comments

Comments
 (0)