diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 5c1f90b3b..bf40f6eb5 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -5489,6 +5489,188 @@ impl FunctionCodeGenerator 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), diff --git a/lib/singlepass-backend/src/emitter_x64.rs b/lib/singlepass-backend/src/emitter_x64.rs index 9344197ff..4bea37d3e 100644 --- a/lib/singlepass-backend/src/emitter_x64.rs +++ b/lib/singlepass-backend/src/emitter_x64.rs @@ -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!() })