Add i32 rmw add and sub.

This commit is contained in:
Nick Lewycky
2019-08-30 18:00:10 -07:00
parent 98f35ef84a
commit efc89e829d
2 changed files with 196 additions and 0 deletions

View File

@ -5489,6 +5489,188 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
ret);
self.machine.release_temp_gpr(value);
}
Operator::I32AtomicRmw8UAdd { ref memarg } => {
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let target =
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let ret = self.machine.acquire_locations(
a,
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
false,
)[0];
self.value_stack.push(ret);
let value = self.machine.acquire_temp_gpr().unwrap();
a.emit_movzx(
Size::S8,
loc,
Size::S32,
Location::GPR(value));
Self::emit_memory_op(
module_info,
&self.config,
a,
&mut self.machine,
target,
memarg,
true,
4,
|a, _m, addr| {
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
}
);
a.emit_mov(
Size::S32,
Location::GPR(value),
ret);
self.machine.release_temp_gpr(value);
}
Operator::I32AtomicRmw16UAdd { ref memarg } => {
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let target =
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let ret = self.machine.acquire_locations(
a,
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
false,
)[0];
self.value_stack.push(ret);
let value = self.machine.acquire_temp_gpr().unwrap();
a.emit_movzx(
Size::S16,
loc,
Size::S32,
Location::GPR(value));
Self::emit_memory_op(
module_info,
&self.config,
a,
&mut self.machine,
target,
memarg,
true,
4,
|a, _m, addr| {
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
}
);
a.emit_mov(
Size::S32,
Location::GPR(value),
ret);
self.machine.release_temp_gpr(value);
}
Operator::I32AtomicRmwSub { ref memarg } => {
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let target =
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let ret = self.machine.acquire_locations(
a,
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
false,
)[0];
self.value_stack.push(ret);
let value = self.machine.acquire_temp_gpr().unwrap();
a.emit_mov(
Size::S32,
loc,
Location::GPR(value));
a.emit_neg(Size::S32, Location::GPR(value));
Self::emit_memory_op(
module_info,
&self.config,
a,
&mut self.machine,
target,
memarg,
true,
4,
|a, _m, addr| {
a.emit_lock_xadd(Size::S32, Location::GPR(value), Location::Memory(addr, 0))
}
);
a.emit_mov(
Size::S32,
Location::GPR(value),
ret);
self.machine.release_temp_gpr(value);
}
Operator::I32AtomicRmw8USub { ref memarg } => {
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let target =
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let ret = self.machine.acquire_locations(
a,
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
false,
)[0];
self.value_stack.push(ret);
let value = self.machine.acquire_temp_gpr().unwrap();
a.emit_movzx(
Size::S8,
loc,
Size::S32,
Location::GPR(value));
a.emit_neg(Size::S8, Location::GPR(value));
Self::emit_memory_op(
module_info,
&self.config,
a,
&mut self.machine,
target,
memarg,
true,
4,
|a, _m, addr| {
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
}
);
a.emit_mov(
Size::S32,
Location::GPR(value),
ret);
self.machine.release_temp_gpr(value);
}
Operator::I32AtomicRmw16USub { ref memarg } => {
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let target =
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
let ret = self.machine.acquire_locations(
a,
&[(WpType::I32, MachineValue::WasmStack(self.value_stack.len()))],
false,
)[0];
self.value_stack.push(ret);
let value = self.machine.acquire_temp_gpr().unwrap();
a.emit_movzx(
Size::S16,
loc,
Size::S32,
Location::GPR(value));
a.emit_neg(Size::S16, Location::GPR(value));
Self::emit_memory_op(
module_info,
&self.config,
a,
&mut self.machine,
target,
memarg,
true,
4,
|a, _m, addr| {
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
}
);
a.emit_mov(
Size::S32,
Location::GPR(value),
ret);
self.machine.release_temp_gpr(value);
}
_ => {
return Err(CodegenError {
message: format!("not yet implemented: {:?}", op),

View File

@ -78,6 +78,7 @@ pub trait Emitter {
fn emit_cmp(&mut self, sz: Size, left: Location, right: Location);
fn emit_add(&mut self, sz: Size, src: Location, dst: Location);
fn emit_sub(&mut self, sz: Size, src: Location, dst: Location);
fn emit_neg(&mut self, sz: Size, value: Location);
fn emit_imul(&mut self, sz: Size, src: Location, dst: Location);
fn emit_imul_imm32_gpr64(&mut self, src: u32, dst: GPR);
fn emit_div(&mut self, sz: Size, divisor: Location);
@ -669,6 +670,19 @@ impl Emitter for Assembler {
fn emit_sub(&mut self, sz: Size, src: Location, dst: Location) {
binop_all_nofp!(sub, self, sz, src, dst, { unreachable!() });
}
fn emit_neg(&mut self, sz: Size, value: Location) {
match (sz, value) {
(Size::S8, Location::GPR(value)) => { dynasm!(self ; neg Rb(value as u8)) }
(Size::S8, Location::Memory(value, disp)) => { dynasm!(self ; neg [Rq(value as u8) + disp]) }
(Size::S16, Location::GPR(value)) => { dynasm!(self ; neg Rw(value as u8)) }
(Size::S16, Location::Memory(value, disp)) => { dynasm!(self ; neg [Rq(value as u8) + disp]) }
(Size::S32, Location::GPR(value)) => { dynasm!(self ; neg Rd(value as u8)) }
(Size::S32, Location::Memory(value, disp)) => { dynasm!(self ; neg [Rq(value as u8) + disp]) }
(Size::S64, Location::GPR(value)) => { dynasm!(self ; neg Rq(value as u8)) }
(Size::S64, Location::Memory(value, disp)) => { dynasm!(self ; neg [Rq(value as u8) + disp]) }
_ => panic!("NEG {:?} {:?}", sz, value),
}
}
fn emit_imul(&mut self, sz: Size, src: Location, dst: Location) {
binop_gpr_gpr!(imul, self, sz, src, dst, {
binop_mem_gpr!(imul, self, sz, src, dst, { unreachable!() })