Add real implementation of _xgetbv() · rust-lang/rust@f6a8c3a (original) (raw)

`@@ -729,3 +729,83 @@ fn call_inline_asm<'tcx>(

`

729

729

` place.write_cvalue(fx, CValue::by_val(value, place.layout()));

`

730

730

`}

`

731

731

`}

`

``

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

`+

}

`