mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 05:31:32 +00:00
Add atomic.rmw operations, excluding xchg and cmpxchg.
Sizes are now ordered, to facilitate an assertion that one size is less (smaller) than another. panic! error messages are provided for remaining emitter functions.
This commit is contained in:
@ -1587,7 +1587,7 @@ impl X64FunctionCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a memory operation.
|
/// Emits a memory operation.
|
||||||
fn emit_cas_loop_op<F: FnOnce(&mut Assembler, &mut Machine, GPR, GPR)>(
|
fn emit_compare_and_swap<F: FnOnce(&mut Assembler, &mut Machine, GPR, GPR)>(
|
||||||
module_info: &ModuleInfo,
|
module_info: &ModuleInfo,
|
||||||
config: &CodegenConfig,
|
config: &CodegenConfig,
|
||||||
a: &mut Assembler,
|
a: &mut Assembler,
|
||||||
@ -1597,8 +1597,12 @@ impl X64FunctionCode {
|
|||||||
ret: Location,
|
ret: Location,
|
||||||
memarg: &MemoryImmediate,
|
memarg: &MemoryImmediate,
|
||||||
value_size: usize,
|
value_size: usize,
|
||||||
|
memory_sz: Size,
|
||||||
|
stack_sz: Size,
|
||||||
cb: F,
|
cb: F,
|
||||||
) {
|
) {
|
||||||
|
assert!(memory_sz <= stack_sz);
|
||||||
|
|
||||||
let compare = m.reserve_temp_gpr(GPR::RAX);
|
let compare = m.reserve_temp_gpr(GPR::RAX);
|
||||||
let value = if loc == Location::GPR(GPR::R14) {
|
let value = if loc == Location::GPR(GPR::R14) {
|
||||||
GPR::R13
|
GPR::R13
|
||||||
@ -1607,7 +1611,7 @@ impl X64FunctionCode {
|
|||||||
};
|
};
|
||||||
a.emit_push(Size::S64, Location::GPR(value));
|
a.emit_push(Size::S64, Location::GPR(value));
|
||||||
|
|
||||||
a.emit_mov(Size::S32, loc, Location::GPR(value));
|
a.emit_mov(stack_sz, loc, Location::GPR(value));
|
||||||
|
|
||||||
let retry = a.get_label();
|
let retry = a.get_label();
|
||||||
a.emit_label(retry);
|
a.emit_label(retry);
|
||||||
@ -1622,10 +1626,10 @@ impl X64FunctionCode {
|
|||||||
true,
|
true,
|
||||||
value_size,
|
value_size,
|
||||||
|a, m, addr| {
|
|a, m, addr| {
|
||||||
a.emit_mov(Size::S32, Location::Memory(addr, 0), Location::GPR(compare));
|
a.emit_mov(memory_sz, Location::Memory(addr, 0), Location::GPR(compare));
|
||||||
a.emit_mov(Size::S32, Location::GPR(compare), ret);
|
a.emit_mov(stack_sz, Location::GPR(compare), ret);
|
||||||
cb(a, m, compare, value);
|
cb(a, m, compare, value);
|
||||||
a.emit_lock_cmpxchg(Size::S32, Location::GPR(value), Location::Memory(addr, 0));
|
a.emit_lock_cmpxchg(memory_sz, Location::GPR(value), Location::Memory(addr, 0));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -5541,6 +5545,36 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
||||||
self.machine.release_temp_gpr(value);
|
self.machine.release_temp_gpr(value);
|
||||||
}
|
}
|
||||||
|
Operator::I64AtomicRmwAdd { 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::I64, 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::S64, loc, Location::GPR(value));
|
||||||
|
Self::emit_memory_op(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
target,
|
||||||
|
memarg,
|
||||||
|
true,
|
||||||
|
8,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S64, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
Operator::I32AtomicRmw8UAdd { ref memarg } => {
|
Operator::I32AtomicRmw8UAdd { ref memarg } => {
|
||||||
let loc =
|
let loc =
|
||||||
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
@ -5563,7 +5597,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
target,
|
target,
|
||||||
memarg,
|
memarg,
|
||||||
true,
|
true,
|
||||||
4,
|
1,
|
||||||
|a, _m, addr| {
|
|a, _m, addr| {
|
||||||
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
},
|
},
|
||||||
@ -5593,7 +5627,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
target,
|
target,
|
||||||
memarg,
|
memarg,
|
||||||
true,
|
true,
|
||||||
4,
|
2,
|
||||||
|a, _m, addr| {
|
|a, _m, addr| {
|
||||||
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
},
|
},
|
||||||
@ -5601,6 +5635,96 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
||||||
self.machine.release_temp_gpr(value);
|
self.machine.release_temp_gpr(value);
|
||||||
}
|
}
|
||||||
|
Operator::I64AtomicRmw8UAdd { 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::I64, 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::S64, Location::GPR(value));
|
||||||
|
Self::emit_memory_op(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
target,
|
||||||
|
memarg,
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw16UAdd { 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::I64, 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::S64, Location::GPR(value));
|
||||||
|
Self::emit_memory_op(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
target,
|
||||||
|
memarg,
|
||||||
|
true,
|
||||||
|
2,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw32UAdd { 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::I64, 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));
|
||||||
|
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::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
Operator::I32AtomicRmwSub { ref memarg } => {
|
Operator::I32AtomicRmwSub { ref memarg } => {
|
||||||
let loc =
|
let loc =
|
||||||
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
@ -5632,6 +5756,37 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
||||||
self.machine.release_temp_gpr(value);
|
self.machine.release_temp_gpr(value);
|
||||||
}
|
}
|
||||||
|
Operator::I64AtomicRmwSub { 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::I64, 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::S64, loc, Location::GPR(value));
|
||||||
|
a.emit_neg(Size::S64, Location::GPR(value));
|
||||||
|
Self::emit_memory_op(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
target,
|
||||||
|
memarg,
|
||||||
|
true,
|
||||||
|
8,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S64, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
Operator::I32AtomicRmw8USub { ref memarg } => {
|
Operator::I32AtomicRmw8USub { ref memarg } => {
|
||||||
let loc =
|
let loc =
|
||||||
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
@ -5655,7 +5810,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
target,
|
target,
|
||||||
memarg,
|
memarg,
|
||||||
true,
|
true,
|
||||||
4,
|
1,
|
||||||
|a, _m, addr| {
|
|a, _m, addr| {
|
||||||
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
},
|
},
|
||||||
@ -5686,7 +5841,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
target,
|
target,
|
||||||
memarg,
|
memarg,
|
||||||
true,
|
true,
|
||||||
4,
|
2,
|
||||||
|a, _m, addr| {
|
|a, _m, addr| {
|
||||||
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
},
|
},
|
||||||
@ -5694,6 +5849,99 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
a.emit_mov(Size::S32, Location::GPR(value), ret);
|
||||||
self.machine.release_temp_gpr(value);
|
self.machine.release_temp_gpr(value);
|
||||||
}
|
}
|
||||||
|
Operator::I64AtomicRmw8USub { 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::I64, 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::S64, 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,
|
||||||
|
1,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S8, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw16USub { 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::I64, 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::S64, 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,
|
||||||
|
2,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S16, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw32USub { 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::I64, 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,
|
||||||
|
2,
|
||||||
|
|a, _m, addr| {
|
||||||
|
a.emit_lock_xadd(Size::S32, Location::GPR(value), Location::Memory(addr, 0))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
a.emit_mov(Size::S64, Location::GPR(value), ret);
|
||||||
|
self.machine.release_temp_gpr(value);
|
||||||
|
}
|
||||||
Operator::I32AtomicRmwAnd { ref memarg } => {
|
Operator::I32AtomicRmwAnd { ref memarg } => {
|
||||||
let loc =
|
let loc =
|
||||||
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
@ -5706,7 +5954,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
)[0];
|
)[0];
|
||||||
self.value_stack.push(ret);
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
Self::emit_cas_loop_op(
|
Self::emit_compare_and_swap(
|
||||||
module_info,
|
module_info,
|
||||||
&self.config,
|
&self.config,
|
||||||
a,
|
a,
|
||||||
@ -5716,11 +5964,593 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
ret,
|
ret,
|
||||||
memarg,
|
memarg,
|
||||||
4,
|
4,
|
||||||
|
Size::S32,
|
||||||
|
Size::S32,
|
||||||
|a, _m, src, dst| {
|
|a, _m, src, dst| {
|
||||||
a.emit_and(Size::S32, Location::GPR(src), Location::GPR(dst));
|
a.emit_and(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Operator::I64AtomicRmwAnd { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
8,
|
||||||
|
Size::S64,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw8UAnd { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw16UAnd { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw8UAnd { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw16UAnd { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw32UAnd { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S32,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_and(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmwOr { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
4,
|
||||||
|
Size::S32,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmwOr { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
8,
|
||||||
|
Size::S64,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw8UOr { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw16UOr { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw8UOr { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw16UOr { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw32UOr { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S32,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_or(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmwXor { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
4,
|
||||||
|
Size::S32,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmwXor { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
8,
|
||||||
|
Size::S64,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw8UXor { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32AtomicRmw16UXor { 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);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S32,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw8UXor { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S8,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw16UXor { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S16,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I64AtomicRmw32UXor { 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::I64, MachineValue::WasmStack(self.value_stack.len()))],
|
||||||
|
false,
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push(ret);
|
||||||
|
|
||||||
|
Self::emit_compare_and_swap(
|
||||||
|
module_info,
|
||||||
|
&self.config,
|
||||||
|
a,
|
||||||
|
&mut self.machine,
|
||||||
|
loc,
|
||||||
|
target,
|
||||||
|
ret,
|
||||||
|
memarg,
|
||||||
|
1,
|
||||||
|
Size::S32,
|
||||||
|
Size::S64,
|
||||||
|
|a, _m, src, dst| {
|
||||||
|
a.emit_xor(Size::S64, Location::GPR(src), Location::GPR(dst));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CodegenError {
|
return Err(CodegenError {
|
||||||
message: format!("not yet implemented: {:?}", op),
|
message: format!("not yet implemented: {:?}", op),
|
||||||
|
@ -28,7 +28,7 @@ pub enum Condition {
|
|||||||
Signed,
|
Signed,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum Size {
|
pub enum Size {
|
||||||
S8,
|
S8,
|
||||||
S16,
|
S16,
|
||||||
@ -584,7 +584,9 @@ impl Emitter for Assembler {
|
|||||||
dynasm!(self ; cqo);
|
dynasm!(self ; cqo);
|
||||||
}
|
}
|
||||||
fn emit_xor(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_xor(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(xor, self, sz, src, dst, { unreachable!() });
|
binop_all_nofp!(xor, self, sz, src, dst, {
|
||||||
|
panic!("XOR {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_jmp(&mut self, condition: Condition, label: Self::Label) {
|
fn emit_jmp(&mut self, condition: Condition, label: Self::Label) {
|
||||||
match condition {
|
match condition {
|
||||||
@ -666,72 +668,110 @@ impl Emitter for Assembler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_add(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_add(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(add, self, sz, src, dst, { unreachable!() });
|
binop_all_nofp!(add, self, sz, src, dst, {
|
||||||
|
panic!("ADD {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_sub(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_sub(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(sub, self, sz, src, dst, { unreachable!() });
|
binop_all_nofp!(sub, self, sz, src, dst, {
|
||||||
|
panic!("SUB {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_neg(&mut self, sz: Size, value: Location) {
|
fn emit_neg(&mut self, sz: Size, value: Location) {
|
||||||
match (sz, value) {
|
match (sz, value) {
|
||||||
(Size::S8, Location::GPR(value)) => { dynasm!(self ; neg Rb(value as u8)) }
|
(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::S8, Location::Memory(value, disp)) => {
|
||||||
(Size::S16, Location::GPR(value)) => { dynasm!(self ; neg Rw(value as u8)) }
|
dynasm!(self ; neg [Rq(value as u8) + disp])
|
||||||
(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::S16, Location::GPR(value)) => dynasm!(self ; neg Rw(value as u8)),
|
||||||
(Size::S32, Location::Memory(value, disp)) => { dynasm!(self ; neg [Rq(value as u8) + disp]) }
|
(Size::S16, Location::Memory(value, disp)) => {
|
||||||
(Size::S64, Location::GPR(value)) => { dynasm!(self ; neg Rq(value as u8)) }
|
dynasm!(self ; neg [Rq(value as u8) + disp])
|
||||||
(Size::S64, 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),
|
_ => panic!("NEG {:?} {:?}", sz, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn emit_imul(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_imul(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_gpr_gpr!(imul, self, sz, src, dst, {
|
binop_gpr_gpr!(imul, self, sz, src, dst, {
|
||||||
binop_mem_gpr!(imul, self, sz, src, dst, { unreachable!() })
|
binop_mem_gpr!(imul, self, sz, src, dst, {
|
||||||
|
panic!("IMUL {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_imul_imm32_gpr64(&mut self, src: u32, dst: GPR) {
|
fn emit_imul_imm32_gpr64(&mut self, src: u32, dst: GPR) {
|
||||||
dynasm!(self ; imul Rq(dst as u8), Rq(dst as u8), src as i32);
|
dynasm!(self ; imul Rq(dst as u8), Rq(dst as u8), src as i32);
|
||||||
}
|
}
|
||||||
fn emit_div(&mut self, sz: Size, divisor: Location) {
|
fn emit_div(&mut self, sz: Size, divisor: Location) {
|
||||||
unop_gpr_or_mem!(div, self, sz, divisor, { unreachable!() });
|
unop_gpr_or_mem!(div, self, sz, divisor, {
|
||||||
|
panic!("DIV {:?} {:?}", sz, divisor)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_idiv(&mut self, sz: Size, divisor: Location) {
|
fn emit_idiv(&mut self, sz: Size, divisor: Location) {
|
||||||
unop_gpr_or_mem!(idiv, self, sz, divisor, { unreachable!() });
|
unop_gpr_or_mem!(idiv, self, sz, divisor, {
|
||||||
|
panic!("IDIV {:?} {:?}", sz, divisor)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(shl, self, sz, src, dst, { unreachable!() });
|
binop_shift!(shl, self, sz, src, dst, {
|
||||||
|
panic!("SHL {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(shr, self, sz, src, dst, { unreachable!() });
|
binop_shift!(shr, self, sz, src, dst, {
|
||||||
|
panic!("SHR {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(sar, self, sz, src, dst, { unreachable!() });
|
binop_shift!(sar, self, sz, src, dst, {
|
||||||
|
panic!("SAR {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(rol, self, sz, src, dst, { unreachable!() });
|
binop_shift!(rol, self, sz, src, dst, {
|
||||||
|
panic!("ROL {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(ror, self, sz, src, dst, { unreachable!() });
|
binop_shift!(ror, self, sz, src, dst, {
|
||||||
|
panic!("ROR {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_and(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_and(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(and, self, sz, src, dst, { unreachable!() });
|
binop_all_nofp!(and, self, sz, src, dst, {
|
||||||
|
panic!("AND {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn emit_or(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_or(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_all_nofp!(or, self, sz, src, dst, { unreachable!() });
|
binop_all_nofp!(or, self, sz, src, dst, {
|
||||||
|
panic!("OR {:?} {:?} {:?}", 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, { unreachable!() })
|
binop_mem_gpr!(lzcnt, self, sz, src, dst, {
|
||||||
|
panic!("LZCNT {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_gpr_gpr!(tzcnt, self, sz, src, dst, {
|
binop_gpr_gpr!(tzcnt, self, sz, src, dst, {
|
||||||
binop_mem_gpr!(tzcnt, self, sz, src, dst, { unreachable!() })
|
binop_mem_gpr!(tzcnt, self, sz, src, dst, {
|
||||||
|
panic!("TZCNT {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_gpr_gpr!(popcnt, self, sz, src, dst, {
|
binop_gpr_gpr!(popcnt, self, sz, src, dst, {
|
||||||
binop_mem_gpr!(popcnt, self, sz, src, dst, { unreachable!() })
|
binop_mem_gpr!(popcnt, self, sz, src, dst, {
|
||||||
|
panic!("POPCNT {:?} {:?} {:?}", sz, src, dst)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_movzx(&mut self, sz_src: Size, src: Location, sz_dst: Size, dst: Location) {
|
fn emit_movzx(&mut self, sz_src: Size, src: Location, sz_dst: Size, dst: Location) {
|
||||||
|
Reference in New Issue
Block a user