(
&mut self,
arg: &MemArg,
size: OperandSize,
extend: Option<Extend<Zero>>,
)
| 2351 | } |
| 2352 | |
| 2353 | pub(crate) fn emit_atomic_cmpxchg( |
| 2354 | &mut self, |
| 2355 | arg: &MemArg, |
| 2356 | size: OperandSize, |
| 2357 | extend: Option<Extend<Zero>>, |
| 2358 | ) -> Result<()> { |
| 2359 | // At this point in the stack we have: |
| 2360 | // [ address, expected, replacement ] |
| 2361 | // |
| 2362 | // Therefore, emission for this instruction is a bit |
| 2363 | // trickier. The address for the CAS is the 3rd from the top |
| 2364 | // of the stack, and we must emit instruction to compute the |
| 2365 | // actual address with |
| 2366 | // `emit_compute_heap_address_align_checked`, while we still |
| 2367 | // have access to self. However, some ISAs have requirements |
| 2368 | // with regard to the registers used for some arguments, so we |
| 2369 | // need to pass the context to the masm. To solve this issue, |
| 2370 | // we pop the two first arguments from the stack, compute the |
| 2371 | // address, push back the arguments, and hand over the control |
| 2372 | // to masm. The implementer of `atomic_cas` can expect to find |
| 2373 | // `expected` and `replacement` at the top the context's |
| 2374 | // stack. |
| 2375 | |
| 2376 | let replacement = self.context.pop_to_reg(self.masm, None)?; |
| 2377 | let expected = self.context.pop_to_reg(self.masm, None)?; |
| 2378 | |
| 2379 | let memory_index = MemoryIndex::from_u32(arg.memory); |
| 2380 | let heap = self.env.resolve_heap(memory_index); |
| 2381 | if let Some(addr) = self.emit_compute_heap_address_align_checked(&heap, arg, size)? { |
| 2382 | self.context.stack.push(expected.into()); |
| 2383 | self.context.stack.push(replacement.into()); |
| 2384 | |
| 2385 | let src = self.masm.address_at_reg(addr, 0)?; |
| 2386 | self.masm |
| 2387 | .atomic_cas(&mut self.context, src, size, UNTRUSTED_FLAGS, extend)?; |
| 2388 | |
| 2389 | self.context.free_reg(addr); |
| 2390 | } |
| 2391 | Ok(()) |
| 2392 | } |
| 2393 | |
| 2394 | /// Emit the sequence of instruction for a `memory.atomic.wait*`. |
| 2395 | pub fn emit_atomic_wait(&mut self, arg: &MemArg, kind: AtomicWaitKind) -> Result<()> { |
no test coverage detected