Skip to content

Commit

Permalink
Add real implementation of _xgetbv()
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Nov 2, 2023
1 parent 909513e commit f6a8c3a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 8 deletions.
80 changes: 80 additions & 0 deletions src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,3 +729,83 @@ fn call_inline_asm<'tcx>(
place.write_cvalue(fx, CValue::by_val(value, place.layout()));
}
}

pub(crate) fn codegen_xgetbv<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
xcr_no: Value,
ret: CPlace<'tcx>,
) {
// FIXME add .eh_frame unwind info directives

let operands = vec![
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
value: xcr_no,
},
CInlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
late: true,
place: Some(ret),
},
CInlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
late: true,
place: None,
},
];
let options = InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM;

let mut inputs = Vec::new();
let mut outputs = Vec::new();

let mut asm_gen = InlineAssemblyGenerator {
tcx: fx.tcx,
arch: fx.tcx.sess.asm_arch.unwrap(),
enclosing_def_id: fx.instance.def_id(),
template: &[InlineAsmTemplatePiece::String(
"
xgetbv
// out = rdx << 32 | rax
shl rdx, 32
or rax, rdx
"
.to_string(),
)],
operands: &operands,
options,
registers: Vec::new(),
stack_slots_clobber: Vec::new(),
stack_slots_input: Vec::new(),
stack_slots_output: Vec::new(),
stack_slot_size: Size::from_bytes(0),
};
asm_gen.allocate_registers();
asm_gen.allocate_stack_slots();

let inline_asm_index = fx.cx.inline_asm_index.get();
fx.cx.inline_asm_index.set(inline_asm_index + 1);
let asm_name = format!(
"__inline_asm_{}_n{}",
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
inline_asm_index
);

let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
fx.cx.global_asm.push_str(&generated_asm);

for (i, operand) in operands.iter().enumerate() {
match operand {
CInlineAsmOperand::In { reg: _, value } => {
inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value));
}
CInlineAsmOperand::Out { reg: _, late: _, place } => {
if let Some(place) = place {
outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place));
}
}
_ => unreachable!(),
}
}

call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
}
11 changes: 3 additions & 8 deletions src/intrinsics/llvm_x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(

// Used by is_x86_feature_detected!();
"llvm.x86.xgetbv" => {
// FIXME use the actual xgetbv instruction
intrinsic_args!(fx, args => (v); intrinsic);
intrinsic_args!(fx, args => (xcr_no); intrinsic);

let v = v.load_scalar(fx);
let xcr_no = xcr_no.load_scalar(fx);

// As of writing on XCR0 exists
fx.bcx.ins().trapnz(v, TrapCode::UnreachableCodeReached);

let res = fx.bcx.ins().iconst(types::I64, 1 /* bit 0 must be set */);
ret.write_cvalue(fx, CValue::by_val(res, fx.layout_of(fx.tcx.types.i64)));
crate::inline_asm::codegen_xgetbv(fx, xcr_no, ret);
}

"llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
Expand Down

0 comments on commit f6a8c3a

Please sign in to comment.