mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-18 19:31:22 +00:00
Reimplement I32Clz without relying on LZCNT.
This commit is contained in:
@ -2341,12 +2341,57 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
Condition::Equal,
|
Condition::Equal,
|
||||||
Location::Imm32(0),
|
Location::Imm32(0),
|
||||||
),
|
),
|
||||||
Operator::I32Clz => Self::emit_xcnt_i32(
|
Operator::I32Clz => {
|
||||||
a,
|
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
&mut self.machine,
|
let src = match loc {
|
||||||
&mut self.value_stack,
|
Location::Imm32(_) | Location::Memory(_, _) => {
|
||||||
Assembler::emit_lzcnt,
|
let tmp = self.machine.acquire_temp_gpr().unwrap();
|
||||||
),
|
a.emit_mov(Size::S32, loc, Location::GPR(tmp));
|
||||||
|
tmp
|
||||||
|
},
|
||||||
|
Location::GPR(reg) => reg,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ret = self.machine.acquire_locations(
|
||||||
|
a,
|
||||||
|
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
let dst = match ret {
|
||||||
|
Location::Memory(_, _) => { self.machine.acquire_temp_gpr().unwrap() },
|
||||||
|
Location::GPR(reg) => reg,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let zero_path = a.get_label();
|
||||||
|
let end = a.get_label();
|
||||||
|
|
||||||
|
a.emit_test_gpr_64(src);
|
||||||
|
a.emit_jmp(Condition::Equal, zero_path);
|
||||||
|
a.emit_bsr(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
a.emit_xor(Size::S32, Location::Imm32(31), Location::GPR(dst));
|
||||||
|
a.emit_jmp(Condition::None, end);
|
||||||
|
a.emit_label(zero_path);
|
||||||
|
a.emit_mov(Size::S32, Location::Imm32(32), Location::GPR(dst));
|
||||||
|
a.emit_label(end);
|
||||||
|
|
||||||
|
match loc {
|
||||||
|
Location::Imm32(_) | Location::Memory(_, _) => {
|
||||||
|
self.machine.release_temp_gpr(src);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
match ret {
|
||||||
|
Location::Memory(_, _) => {
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(dst), ret);
|
||||||
|
self.machine.release_temp_gpr(dst);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
},
|
||||||
Operator::I32Ctz => Self::emit_xcnt_i32(
|
Operator::I32Ctz => Self::emit_xcnt_i32(
|
||||||
a,
|
a,
|
||||||
&mut self.machine,
|
&mut self.machine,
|
||||||
|
@ -90,6 +90,7 @@ pub trait Emitter {
|
|||||||
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_and(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_and(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_or(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_or(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_bsr(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
@ -753,6 +754,15 @@ impl Emitter for Assembler {
|
|||||||
panic!("singlepass can't emit OR {:?} {:?} {:?}", sz, src, dst)
|
panic!("singlepass can't emit OR {:?} {:?} {:?}", sz, src, dst)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_bsr(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_gpr_gpr!(bsr, self, sz, src, dst, {
|
||||||
|
binop_mem_gpr!(bsr, self, sz, src, dst, {
|
||||||
|
panic!("singlepass can't emit BSR {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_gpr_gpr!(lzcnt, self, sz, src, dst, {
|
binop_gpr_gpr!(lzcnt, self, sz, src, dst, {
|
||||||
binop_mem_gpr!(lzcnt, self, sz, src, dst, {
|
binop_mem_gpr!(lzcnt, self, sz, src, dst, {
|
||||||
|
Reference in New Issue
Block a user