mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-19 20:01:20 +00:00
Reimplement I32Clz without relying on LZCNT.
This commit is contained in:
@ -2341,12 +2341,57 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
Condition::Equal,
|
||||
Location::Imm32(0),
|
||||
),
|
||||
Operator::I32Clz => Self::emit_xcnt_i32(
|
||||
Operator::I32Clz => {
|
||||
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||
let src = match loc {
|
||||
Location::Imm32(_) | Location::Memory(_, _) => {
|
||||
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,
|
||||
&mut self.machine,
|
||||
&mut self.value_stack,
|
||||
Assembler::emit_lzcnt,
|
||||
),
|
||||
&[(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(
|
||||
a,
|
||||
&mut self.machine,
|
||||
|
@ -90,6 +90,7 @@ pub trait Emitter {
|
||||
fn emit_ror(&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_bsr(&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_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)
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
binop_gpr_gpr!(lzcnt, self, sz, src, dst, {
|
||||
binop_mem_gpr!(lzcnt, self, sz, src, dst, {
|
||||
|
Reference in New Issue
Block a user